void CairoOutputDev::drawImageMaskRegular(GfxState *state, Object *ref, Stream *str,
					  int width, int height, GBool invert,
					  GBool interpolate, GBool inlineImg) {
  unsigned char *buffer;
  unsigned char *dest;
  cairo_surface_t *image;
  cairo_pattern_t *pattern;
  int x, y, i, bit;
  ImageStream *imgStr;
  Guchar *pix;
  cairo_matrix_t matrix;
  int invert_bit;
  int row_stride;
  cairo_filter_t filter;

  /* TODO: Do we want to cache these? */
  imgStr = new ImageStream(str, width, 1, 1);
  imgStr->reset();

  image = cairo_image_surface_create (CAIRO_FORMAT_A1, width, height);
  if (cairo_surface_status (image))
    goto cleanup;

  buffer = cairo_image_surface_get_data (image);
  row_stride = cairo_image_surface_get_stride (image);

  invert_bit = invert ? 1 : 0;

  for (y = 0; y < height; y++) {
    pix = imgStr->getLine();
    dest = buffer + y * row_stride;
    i = 0;
    bit = 0;
    for (x = 0; x < width; x++) {
      if (bit == 0)
	dest[i] = 0;
      if (!(pix[x] ^ invert_bit)) {
#ifdef WORDS_BIGENDIAN
	dest[i] |= (1 << (7 - bit));
#else
	dest[i] |= (1 << bit);
#endif
      }
      bit++;
      if (bit > 7) {
	bit = 0;
	i++;
      }
    }
  }

  filter = getFilterForSurface (image, interpolate);

  cairo_surface_mark_dirty (image);
  pattern = cairo_pattern_create_for_surface (image);
  cairo_surface_destroy (image);
  if (cairo_pattern_status (pattern))
    goto cleanup;

  LOG (printf ("drawImageMask %dx%d\n", width, height));

  cairo_pattern_set_filter (pattern, filter);

  if (!printing)
    cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);

  cairo_matrix_init_translate (&matrix, 0, height);
  cairo_matrix_scale (&matrix, width, -height);
  cairo_pattern_set_matrix (pattern, &matrix);
  if (cairo_pattern_status (pattern)) {
    cairo_pattern_destroy (pattern);
    goto cleanup;
  }

  if (state->getFillColorSpace()->getMode() == csPattern) {
    mask = cairo_pattern_reference (pattern);
  } else if (!printing) {
    cairo_save (cairo);
    cairo_rectangle (cairo, 0., 0., 1., 1.);
    cairo_clip (cairo);
    cairo_mask (cairo, pattern);
    cairo_restore (cairo);
  } else {
    cairo_mask (cairo, pattern);
  }

  if (cairo_shape) {
    cairo_save (cairo_shape);
    cairo_set_source (cairo_shape, pattern);
    if (!printing) {
      cairo_rectangle (cairo_shape, 0., 0., 1., 1.);
      cairo_fill (cairo_shape);
    } else {
      cairo_mask (cairo_shape, pattern);
    }
    cairo_restore (cairo_shape);
  }

  cairo_pattern_destroy (pattern);

cleanup:
  imgStr->close();
  delete imgStr;
}
void CairoOutputDev::drawImageMaskRegular(GfxState *state, Object *ref, Stream *str,
					  int width, int height, GBool invert,
					  GBool interpolate, GBool inlineImg) {
  unsigned char *buffer;
  unsigned char *dest;
  cairo_surface_t *image;
  cairo_pattern_t *pattern;
  int x, y, i, bit;
  ImageStream *imgStr;
  Guchar *pix;
  cairo_matrix_t matrix;
  int invert_bit;
  int row_stride;
  cairo_filter_t filter;

   
  imgStr = new ImageStream(str, width, 1, 1);
  imgStr->reset();

  image = cairo_image_surface_create (CAIRO_FORMAT_A1, width, height);
  if (cairo_surface_status (image))
    goto cleanup;

  buffer = cairo_image_surface_get_data (image);
  row_stride = cairo_image_surface_get_stride (image);

  invert_bit = invert ? 1 : 0;

  for (y = 0; y < height; y++) {
    pix = imgStr->getLine();
    dest = buffer + y * row_stride;
    i = 0;
    bit = 0;
    for (x = 0; x < width; x++) {
      if (bit == 0)
	dest[i] = 0;
      if (!(pix[x] ^ invert_bit)) {
#ifdef WORDS_BIGENDIAN
	dest[i] |= (1 << (7 - bit));
#else
	dest[i] |= (1 << bit);
#endif
      }
      bit++;
      if (bit > 7) {
	bit = 0;
	i++;
      }
    }
  }

  filter = getFilterForSurface (image, interpolate);

  cairo_surface_mark_dirty (image);
  pattern = cairo_pattern_create_for_surface (image);
  cairo_surface_destroy (image);
  if (cairo_pattern_status (pattern))
    goto cleanup;

  LOG (printf ("drawImageMask %dx%d\n", width, height));

  cairo_pattern_set_filter (pattern, filter);

  if (!printing)
    cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);

  cairo_matrix_init_translate (&matrix, 0, height);
  cairo_matrix_scale (&matrix, width, -height);
  cairo_pattern_set_matrix (pattern, &matrix);
  if (cairo_pattern_status (pattern)) {
    cairo_pattern_destroy (pattern);
    goto cleanup;
  }

  if (state->getFillColorSpace()->getMode() == csPattern) {
    mask = cairo_pattern_reference (pattern);
  } else if (!printing) {
    cairo_save (cairo);
    cairo_rectangle (cairo, 0., 0., 1., 1.);
    cairo_clip (cairo);
    cairo_mask (cairo, pattern);
    cairo_restore (cairo);
  } else {
    cairo_mask (cairo, pattern);
  }

  if (cairo_shape) {
    cairo_save (cairo_shape);
    cairo_set_source (cairo_shape, pattern);
    if (!printing) {
      cairo_rectangle (cairo_shape, 0., 0., 1., 1.);
      cairo_fill (cairo_shape);
    } else {
      cairo_mask (cairo_shape, pattern);
    }
    cairo_restore (cairo_shape);
  }

  cairo_pattern_destroy (pattern);

cleanup:
  imgStr->close();
  delete imgStr;
}