source: trunk/poppler/mypoppler/poppler/CairoOutputDev.cc @ 2

Last change on this file since 2 was 2, checked in by Eugene Romanenko, 16 years ago

First import

File size: 19.6 KB
Line 
1//========================================================================
2//
3// CairoOutputDev.cc
4//
5// Copyright 2003 Glyph & Cog, LLC
6// Copyright 2004 Red Hat, Inc
7//
8//========================================================================
9
10#include <config.h>
11
12#ifdef USE_GCC_PRAGMAS
13#pragma implementation
14#endif
15
16#include <string.h>
17#include <math.h>
18#include <cairo.h>
19
20#include "goo/gfile.h"
21#include "GlobalParams.h"
22#include "Error.h"
23#include "Object.h"
24#include "GfxState.h"
25#include "GfxFont.h"
26#include "Link.h"
27#include "CharCodeToUnicode.h"
28#include "FontEncodingTables.h"
29#include <fofi/FoFiTrueType.h>
30#include <splash/SplashBitmap.h>
31#include "CairoOutputDev.h"
32#include "CairoFontEngine.h"
33
34//------------------------------------------------------------------------
35
36// #define LOG_CAIRO
37
38#ifdef LOG_CAIRO
39#define LOG(x) (x)
40#else
41#define LOG(x)
42#endif
43
44
45//------------------------------------------------------------------------
46// CairoOutputDev
47//------------------------------------------------------------------------
48
49CairoOutputDev::CairoOutputDev() {
50  xref = NULL;
51
52  FT_Init_FreeType(&ft_lib);
53  fontEngine = NULL;
54  glyphs = NULL;
55  surface = NULL;
56  fill_pattern = NULL;
57  stroke_pattern = NULL;
58  stroke_opacity = 1.0;
59  fill_opacity = 1.0;
60  textClipPath = NULL;
61}
62
63CairoOutputDev::~CairoOutputDev() {
64  if (fontEngine) {
65    delete fontEngine;
66  }
67  FT_Done_FreeType(ft_lib);
68  cairo_surface_destroy (surface);
69  cairo_pattern_destroy (stroke_pattern);
70  cairo_pattern_destroy (fill_pattern);
71}
72
73void CairoOutputDev::setSurface(cairo_surface_t *surface)
74{
75  cairo_surface_destroy (this->surface);
76  cairo_surface_reference (surface);
77  this->surface = surface;
78}
79
80void CairoOutputDev::startDoc(XRef *xrefA) {
81  xref = xrefA;
82  if (fontEngine) {
83    delete fontEngine;
84  }
85  fontEngine = new CairoFontEngine(ft_lib);
86}
87
88void CairoOutputDev::startPage(int pageNum, GfxState *state) {
89  cairo = cairo_create (surface);
90}
91
92void CairoOutputDev::endPage() {
93  cairo_destroy (cairo);
94}
95
96void CairoOutputDev::drawLink(Link *link, Catalog *catalog) {
97}
98
99void CairoOutputDev::saveState(GfxState *state) {
100  LOG(printf ("save\n"));
101  cairo_save (cairo);
102}
103
104void CairoOutputDev::restoreState(GfxState *state) {
105  LOG(printf ("restore\n"));
106  cairo_restore (cairo);
107
108  /* These aren't restored by cairo_restore() since we keep them in
109   * the output device. */
110  updateFillColor(state);
111  updateStrokeColor(state);
112  updateFillOpacity(state);
113  updateStrokeOpacity(state);
114}
115
116void CairoOutputDev::updateAll(GfxState *state) {
117  updateLineDash(state);
118  updateLineJoin(state);
119  updateLineCap(state);
120  updateLineWidth(state);
121  updateFlatness(state);
122  updateMiterLimit(state);
123  updateFillColor(state);
124  updateStrokeColor(state);
125  updateFillOpacity(state);
126  updateStrokeOpacity(state);
127  needFontUpdate = gTrue;
128}
129
130void CairoOutputDev::updateCTM(GfxState *state, double m11, double m12,
131                                double m21, double m22,
132                                double m31, double m32) {
133  updateLineDash(state);
134  updateLineJoin(state);
135  updateLineCap(state);
136  updateLineWidth(state);
137}
138
139void CairoOutputDev::updateLineDash(GfxState *state) {
140  double *dashPattern;
141  int dashLength;
142  double dashStart;
143  double *transformedDash;
144  double transformedStart;
145  int i;
146
147  state->getLineDash(&dashPattern, &dashLength, &dashStart);
148
149  transformedDash = new double[dashLength];
150 
151  for (i = 0; i < dashLength; ++i) {
152    transformedDash[i] =  state->transformWidth(dashPattern[i]);
153  }
154  transformedStart = state->transformWidth(dashStart);
155  cairo_set_dash (cairo, transformedDash, dashLength, transformedStart);
156  delete [] transformedDash;
157}
158
159void CairoOutputDev::updateFlatness(GfxState *state) {
160  // cairo_set_tolerance (cairo, state->getFlatness());
161}
162
163void CairoOutputDev::updateLineJoin(GfxState *state) {
164  switch (state->getLineJoin()) {
165  case 0:
166    cairo_set_line_join (cairo, CAIRO_LINE_JOIN_MITER);
167    break;
168  case 1:
169    cairo_set_line_join (cairo, CAIRO_LINE_JOIN_ROUND);
170    break;
171  case 2:
172    cairo_set_line_join (cairo, CAIRO_LINE_JOIN_BEVEL);
173    break;
174  }
175}
176
177void CairoOutputDev::updateLineCap(GfxState *state) {
178  switch (state->getLineCap()) {
179  case 0:
180    cairo_set_line_cap (cairo, CAIRO_LINE_CAP_BUTT);
181    break;
182  case 1:
183    cairo_set_line_cap (cairo, CAIRO_LINE_CAP_ROUND);
184    break;
185  case 2:
186    cairo_set_line_cap (cairo, CAIRO_LINE_CAP_SQUARE);
187    break;
188  }
189}
190
191void CairoOutputDev::updateMiterLimit(GfxState *state) {
192  cairo_set_miter_limit (cairo, state->getMiterLimit());
193}
194
195void CairoOutputDev::updateLineWidth(GfxState *state) {
196  LOG(printf ("line width: %f\n", state->getTransformedLineWidth()));
197  if (state->getTransformedLineWidth() == 0.0) {
198      cairo_set_line_width (cairo, 72.0/300.0);
199  } else {
200      cairo_set_line_width (cairo, state->getTransformedLineWidth());
201  }
202}
203
204void CairoOutputDev::updateFillColor(GfxState *state) {
205  state->getFillRGB(&fill_color);
206
207  cairo_pattern_destroy(fill_pattern);
208  fill_pattern = cairo_pattern_create_rgba(fill_color.r / 65535.0,
209                                           fill_color.g / 65535.0,
210                                           fill_color.b / 65535.0,
211                                           fill_opacity);
212
213  LOG(printf ("fill color: %d %d %d\n",
214              fill_color.r, fill_color.g, fill_color.b));
215}
216
217void CairoOutputDev::updateStrokeColor(GfxState *state) {
218  state->getStrokeRGB(&stroke_color);
219
220  cairo_pattern_destroy(stroke_pattern);
221  stroke_pattern = cairo_pattern_create_rgba(stroke_color.r / 65535.0,
222                                             stroke_color.g / 65535.0,
223                                             stroke_color.b / 65535.0,
224                                             stroke_opacity);
225 
226  LOG(printf ("stroke color: %d %d %d\n",
227              stroke_color.r, stroke_color.g, stroke_color.b));
228}
229
230void CairoOutputDev::updateFillOpacity(GfxState *state) {
231  fill_opacity = state->getFillOpacity();
232
233  cairo_pattern_destroy(fill_pattern);
234  fill_pattern = cairo_pattern_create_rgba(fill_color.r / 65535.0,
235                                           fill_color.g / 65535.0,
236                                           fill_color.b / 65535.0,
237                                           fill_opacity);
238
239  LOG(printf ("fill opacity: %f\n", fill_opacity));
240}
241
242void CairoOutputDev::updateStrokeOpacity(GfxState *state) {
243  stroke_opacity = state->getStrokeOpacity();
244
245  cairo_pattern_destroy(stroke_pattern);
246  stroke_pattern = cairo_pattern_create_rgba(stroke_color.r / 65535.0,
247                                             stroke_color.g / 65535.0,
248                                             stroke_color.b / 65535.0,
249                                             stroke_opacity);
250 
251  LOG(printf ("stroke opacity: %f\n", stroke_opacity));
252}
253
254void CairoOutputDev::updateFont(GfxState *state) {
255  cairo_font_face_t *font_face;
256  double m11, m12, m21, m22;
257  double w;
258  cairo_matrix_t matrix;
259
260  LOG(printf ("updateFont() font=%s\n", state->getFont()->getName()->getCString()));
261
262  needFontUpdate = gFalse;
263
264  if (state->getFont()->getType() == fontType3)
265    return;
266
267  currentFont = fontEngine->getFont (state->getFont(), xref);
268
269  state->getFontTransMat(&m11, &m12, &m21, &m22);
270  m11 *= state->getHorizScaling();
271  m12 *= state->getHorizScaling();
272
273  LOG(printf ("font matrix: %f %f %f %f\n", m11, m12, m21, m22));
274 
275  font_face = currentFont->getFontFace();
276  cairo_set_font_face (cairo, font_face);
277
278  matrix.xx = m11;
279  matrix.xy = -m21;
280  matrix.yx = m12;
281  matrix.yy = -m22;
282  matrix.x0 = 0;
283  matrix.y0 = 0;
284  cairo_set_font_matrix (cairo, &matrix);
285}
286
287void CairoOutputDev::doPath(GfxState *state, GfxPath *path) {
288  GfxSubpath *subpath;
289  double x1, y1, x2, y2, x3, y3;
290  int i, j;
291
292  for (i = 0; i < path->getNumSubpaths(); ++i) {
293    subpath = path->getSubpath(i);
294    if (subpath->getNumPoints() > 0) {
295      state->transform(subpath->getX(0), subpath->getY(0), &x1, &y1);
296      cairo_move_to (cairo, x1, y1);
297      LOG (printf ("move_to %f, %f\n", x1, y1));
298      j = 1;
299      while (j < subpath->getNumPoints()) {
300        if (subpath->getCurve(j)) {
301          state->transform(subpath->getX(j), subpath->getY(j), &x1, &y1);
302          state->transform(subpath->getX(j+1), subpath->getY(j+1), &x2, &y2);
303          state->transform(subpath->getX(j+2), subpath->getY(j+2), &x3, &y3);
304          cairo_curve_to (cairo, 
305                          x1, y1,
306                          x2, y2,
307                          x3, y3);
308          LOG (printf ("curve_to %f, %f  %f, %f  %f, %f\n", x1, y1, x2, y2, x3, y3));
309          j += 3;
310        } else {
311          state->transform(subpath->getX(j), subpath->getY(j), &x1, &y1);
312          cairo_line_to (cairo, x1, y1);
313          LOG(printf ("line_to %f, %f\n", x1, y1));
314          ++j;
315        }
316      }
317      if (subpath->isClosed()) {
318        LOG (printf ("close\n"));
319        cairo_close_path (cairo);
320      }
321    }
322  }
323}
324
325void CairoOutputDev::stroke(GfxState *state) {
326  doPath (state, state->getPath());
327  cairo_set_source (cairo, stroke_pattern);
328  LOG(printf ("stroke\n"));
329  cairo_stroke (cairo);
330}
331
332void CairoOutputDev::fill(GfxState *state) {
333  doPath (state, state->getPath());
334  cairo_set_fill_rule (cairo, CAIRO_FILL_RULE_WINDING);
335  cairo_set_source (cairo, fill_pattern);
336  LOG(printf ("fill\n"));
337  cairo_fill (cairo);
338}
339
340void CairoOutputDev::eoFill(GfxState *state) {
341  doPath (state, state->getPath());
342  cairo_set_fill_rule (cairo, CAIRO_FILL_RULE_EVEN_ODD);
343  cairo_set_source (cairo, fill_pattern);
344  LOG(printf ("fill-eo\n"));
345  cairo_fill (cairo);
346}
347
348void CairoOutputDev::clip(GfxState *state) {
349  doPath (state, state->getPath());
350  cairo_set_fill_rule (cairo, CAIRO_FILL_RULE_WINDING);
351  cairo_clip (cairo);
352  LOG (printf ("clip\n"));
353}
354
355void CairoOutputDev::eoClip(GfxState *state) {
356  doPath (state, state->getPath());
357  cairo_set_fill_rule (cairo, CAIRO_FILL_RULE_EVEN_ODD);
358  cairo_clip (cairo);
359  LOG (printf ("clip-eo\n"));
360}
361
362void CairoOutputDev::beginString(GfxState *state, GooString *s)
363{
364  int len = s->getLength();
365
366  if (needFontUpdate)
367    updateFont(state);
368
369  glyphs = (cairo_glyph_t *) gmalloc (len * sizeof (cairo_glyph_t));
370  glyphCount = 0;
371}
372
373void CairoOutputDev::drawChar(GfxState *state, double x, double y,
374                              double dx, double dy,
375                              double originX, double originY,
376                              CharCode code, int nBytes, Unicode *u, int uLen)
377{
378  double tx, ty;
379
380  glyphs[glyphCount].index = currentFont->getGlyph (code, u, uLen);
381  state->transform(x, y, &tx, &ty);
382  glyphs[glyphCount].x = tx;
383  glyphs[glyphCount].y = ty;
384  glyphCount++;
385}
386
387void CairoOutputDev::endString(GfxState *state)
388{
389  int render;
390
391  if (!currentFont)
392    return;
393   
394  // ignore empty strings and invisible text -- this is used by
395  // Acrobat Capture
396  render = state->getRender();
397  if (render == 3 || glyphCount == 0) {
398    gfree(glyphs);
399    glyphs = NULL;
400    return;
401  }
402 
403  if (!(render & 1)) {
404    LOG (printf ("fill string\n"));
405    cairo_set_source (cairo, fill_pattern);
406    cairo_show_glyphs (cairo, glyphs, glyphCount);
407  }
408 
409  // stroke
410  if ((render & 3) == 1 || (render & 3) == 2) {
411    LOG (printf ("stroke string\n"));
412    cairo_set_source (cairo, stroke_pattern);
413    cairo_glyph_path (cairo, glyphs, glyphCount);
414    cairo_stroke (cairo);
415  }
416
417  // clip
418  if (render & 4) {
419    LOG (printf ("clip string\n"));
420    // append the glyph path to textClipPath.
421
422    // set textClipPath as the currentPath
423    if (textClipPath) {
424      cairo_append_path (cairo, textClipPath);
425      cairo_path_destroy (textClipPath);
426    }
427   
428    // append the glyph path
429    cairo_glyph_path (cairo, glyphs, glyphCount);
430   
431    // move the path back into textClipPath
432    // and clear the current path
433    textClipPath = cairo_copy_path (cairo);
434    cairo_new_path (cairo);
435  }
436 
437  gfree (glyphs);
438  glyphs = NULL;
439}
440
441GBool CairoOutputDev::beginType3Char(GfxState *state, double x, double y,
442                                      double dx, double dy,
443                                      CharCode code, Unicode *u, int uLen) {
444  return gFalse;
445}
446
447void CairoOutputDev::endType3Char(GfxState *state) {
448}
449
450void CairoOutputDev::type3D0(GfxState *state, double wx, double wy) {
451}
452
453void CairoOutputDev::type3D1(GfxState *state, double wx, double wy,
454                              double llx, double lly, double urx, double ury) {
455}
456
457void CairoOutputDev::endTextObject(GfxState *state) {
458  if (textClipPath) {
459    // clip the accumulated text path
460    cairo_append_path (cairo, textClipPath);
461    cairo_clip (cairo);
462    cairo_path_destroy (textClipPath);
463    textClipPath = NULL;
464  }
465
466}
467
468
469void CairoOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
470                                    int width, int height, GBool invert,
471                                    GBool inlineImg) {
472  unsigned char *buffer;
473  unsigned char *dest;
474  cairo_surface_t *image;
475  cairo_pattern_t *pattern;
476  int x, y;
477  ImageStream *imgStr;
478  Guchar *pix;
479  double *ctm;
480  cairo_matrix_t matrix;
481  int invert_bit;
482  int row_stride;
483
484  ctm = state->getCTM();
485  LOG (printf ("drawImageMask %dx%d, matrix: %f, %f, %f, %f, %f, %f\n",
486               width, height, ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]));
487  matrix.xx = ctm[0] / width;
488  matrix.xy = -ctm[2] / height;
489  matrix.yx = ctm[1] / width;
490  matrix.yy = -ctm[3] / height;
491  matrix.x0 = ctm[2] + ctm[4];
492  matrix.y0 = ctm[3] + ctm[5];
493
494  /* work around a cairo bug when scaling 1x1 surfaces */
495  if (width == 1 && height == 1) {
496    cairo_save (cairo);
497    cairo_set_matrix (cairo, &matrix);
498    cairo_rectangle (cairo, 0., 0., 1., 1.);
499    cairo_fill (cairo);
500    cairo_restore (cairo);
501    return;
502  }
503
504  row_stride = (width + 3) & ~3;
505  buffer = (unsigned char *) malloc (height * row_stride);
506  if (buffer == NULL) {
507    error(-1, "Unable to allocate memory for image.");
508    return;
509  }
510
511  /* TODO: Do we want to cache these? */
512  imgStr = new ImageStream(str, width, 1, 1);
513  imgStr->reset();
514
515  invert_bit = invert ? 1 : 0;
516
517  for (y = 0; y < height; y++) {
518    pix = imgStr->getLine();
519    dest = buffer + y * row_stride;
520    for (x = 0; x < width; x++) {
521
522      if (pix[x] ^ invert_bit)
523        *dest++ = 0;
524      else
525        *dest++ = 255;
526    }
527  }
528
529  image = cairo_image_surface_create_for_data (buffer, CAIRO_FORMAT_A8,
530                                               width, height, row_stride);
531  if (image == NULL)
532    return;
533  pattern = cairo_pattern_create_for_surface (image);
534  if (pattern == NULL)
535    return;
536
537  cairo_matrix_invert (&matrix);
538  cairo_pattern_set_matrix (pattern, &matrix);
539
540  /* we should actually be using CAIRO_FILTER_NEAREST here. However,
541   * cairo doesn't yet do minifaction filtering causing scaled down
542   * images with CAIRO_FILTER_NEAREST to look really bad */
543  cairo_pattern_set_filter (pattern, CAIRO_FILTER_BEST);
544
545  /* FIXME: Doesn't the image mask support any colorspace? */
546  cairo_set_source (cairo, fill_pattern);
547  cairo_mask (cairo, pattern);
548
549  cairo_pattern_destroy (pattern);
550  cairo_surface_destroy (image);
551  free (buffer);
552  delete imgStr;
553}
554
555void CairoOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str,
556                                int width, int height,
557                                GfxImageColorMap *colorMap,
558                                Stream *maskStr,
559                                int maskWidth, int maskHeight,
560                                GfxImageColorMap *maskColorMap)
561{
562  ImageStream *maskImgStr;
563  maskImgStr = new ImageStream(maskStr, maskWidth,
564                                       maskColorMap->getNumPixelComps(),
565                                       maskColorMap->getBits());
566  maskImgStr->reset();
567
568  int row_stride = (maskWidth + 3) & ~3;
569  unsigned char *maskBuffer;
570  maskBuffer = (unsigned char *)gmalloc (row_stride * maskHeight);
571  unsigned char *maskDest;
572  cairo_surface_t *maskImage;
573  cairo_pattern_t *maskPattern;
574  Guchar *pix;
575  int x, y;
576  for (y = 0; y < maskHeight; y++) {
577    maskDest = (unsigned char *) (maskBuffer + y * row_stride);
578    pix = maskImgStr->getLine();
579    maskColorMap->getGrayLine (pix, maskDest, maskWidth);
580  }
581
582  maskImage = cairo_image_surface_create_for_data (maskBuffer, CAIRO_FORMAT_A8,
583                                                 maskWidth, maskHeight, row_stride);
584
585  delete maskImgStr;
586  maskStr->close();
587
588  unsigned char *buffer;
589  unsigned int *dest;
590  cairo_surface_t *image;
591  cairo_pattern_t *pattern;
592  ImageStream *imgStr;
593  GfxRGB rgb;
594  int alpha, i;
595  double *ctm;
596  cairo_matrix_t matrix;
597  int is_identity_transform;
598
599  buffer = (unsigned char *)gmalloc (width * height * 4);
600
601  /* TODO: Do we want to cache these? */
602  imgStr = new ImageStream(str, width,
603                           colorMap->getNumPixelComps(),
604                           colorMap->getBits());
605  imgStr->reset();
606 
607  /* ICCBased color space doesn't do any color correction
608   * so check its underlying color space as well */
609  is_identity_transform = colorMap->getColorSpace()->getMode() == csDeviceRGB ||
610                  colorMap->getColorSpace()->getMode() == csICCBased && 
611                  ((GfxICCBasedColorSpace*)colorMap->getColorSpace())->getAlt()->getMode() == csDeviceRGB;
612
613  for (y = 0; y < height; y++) {
614    dest = (unsigned int *) (buffer + y * 4 * width);
615    pix = imgStr->getLine();
616    colorMap->getRGBLine (pix, dest, width);
617  }
618
619  image = cairo_image_surface_create_for_data (buffer, CAIRO_FORMAT_RGB24,
620                                                 width, height, width * 4);
621
622  if (image == NULL)
623    return;
624  pattern = cairo_pattern_create_for_surface (image);
625  maskPattern = cairo_pattern_create_for_surface (maskImage);
626  if (pattern == NULL)
627    return;
628
629  ctm = state->getCTM();
630  LOG (printf ("drawImageMask %dx%d, matrix: %f, %f, %f, %f, %f, %f\n",
631               width, height, ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]));
632  matrix.xx = ctm[0] / width;
633  matrix.xy = -ctm[2] / height;
634  matrix.yx = ctm[1] / width;
635  matrix.yy = -ctm[3] / height;
636  matrix.x0 = ctm[2] + ctm[4];
637  matrix.y0 = ctm[3] + ctm[5];
638
639  cairo_matrix_invert (&matrix);
640
641  cairo_pattern_set_matrix (pattern, &matrix);
642  cairo_pattern_set_matrix (maskPattern, &matrix);
643
644  cairo_pattern_set_filter (pattern, CAIRO_FILTER_BILINEAR);
645  cairo_set_source (cairo, pattern);
646  cairo_mask (cairo, maskPattern);
647
648  cairo_pattern_destroy (maskPattern);
649  cairo_surface_destroy (maskImage);
650  cairo_pattern_destroy (pattern);
651  cairo_surface_destroy (image);
652  free (buffer);
653  free (maskBuffer);
654  delete imgStr;
655}
656void CairoOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
657                                int width, int height,
658                                GfxImageColorMap *colorMap,
659                                int *maskColors, GBool inlineImg)
660{
661  unsigned char *buffer;
662  unsigned int *dest;
663  cairo_surface_t *image;
664  cairo_pattern_t *pattern;
665  int x, y;
666  ImageStream *imgStr;
667  Guchar *pix;
668  GfxRGB rgb;
669  int alpha, i;
670  double *ctm;
671  cairo_matrix_t matrix;
672  int is_identity_transform;
673 
674  buffer = (unsigned char *)gmalloc (width * height * 4);
675
676  /* TODO: Do we want to cache these? */
677  imgStr = new ImageStream(str, width,
678                           colorMap->getNumPixelComps(),
679                           colorMap->getBits());
680  imgStr->reset();
681 
682  /* ICCBased color space doesn't do any color correction
683   * so check its underlying color space as well */
684  is_identity_transform = colorMap->getColorSpace()->getMode() == csDeviceRGB ||
685                  colorMap->getColorSpace()->getMode() == csICCBased && 
686                  ((GfxICCBasedColorSpace*)colorMap->getColorSpace())->getAlt()->getMode() == csDeviceRGB;
687
688  if (maskColors) {
689    for (y = 0; y < height; y++) {
690      dest = (unsigned int *) (buffer + y * 4 * width);
691      pix = imgStr->getLine();
692      colorMap->getRGBLine (pix, dest, width);
693
694      for (x = 0; x < width; x++) {
695        for (i = 0; i < colorMap->getNumPixelComps(); ++i) {
696         
697          if (pix[i] < maskColors[2*i] * 255||
698              pix[i] > maskColors[2*i+1] * 255) {
699            *dest = *dest | 0xff000000;
700            break;
701          }
702        }
703        pix += colorMap->getNumPixelComps();
704        dest++;
705      }
706    }
707
708    image = cairo_image_surface_create_for_data (buffer, CAIRO_FORMAT_ARGB32,
709                                                 width, height, width * 4);
710  }
711  else {
712    for (y = 0; y < height; y++) {
713      dest = (unsigned int *) (buffer + y * 4 * width);
714      pix = imgStr->getLine();
715      colorMap->getRGBLine (pix, dest, width);
716    }
717
718    image = cairo_image_surface_create_for_data (buffer, CAIRO_FORMAT_RGB24,
719                                                 width, height, width * 4);
720  }
721
722  if (image == NULL)
723    return;
724  pattern = cairo_pattern_create_for_surface (image);
725  if (pattern == NULL)
726    return;
727
728  ctm = state->getCTM();
729  LOG (printf ("drawImageMask %dx%d, matrix: %f, %f, %f, %f, %f, %f\n",
730               width, height, ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]));
731  matrix.xx = ctm[0] / width;
732  matrix.xy = -ctm[2] / height;
733  matrix.yx = ctm[1] / width;
734  matrix.yy = -ctm[3] / height;
735  matrix.x0 = ctm[2] + ctm[4];
736  matrix.y0 = ctm[3] + ctm[5];
737
738  cairo_matrix_invert (&matrix);
739  cairo_pattern_set_matrix (pattern, &matrix);
740
741  cairo_pattern_set_filter (pattern, CAIRO_FILTER_BILINEAR);
742  cairo_set_source (cairo, pattern);
743  cairo_paint (cairo);
744
745  cairo_pattern_destroy (pattern);
746  cairo_surface_destroy (image);
747  free (buffer);
748  delete imgStr;
749}
Note: See TracBrowser for help on using the repository browser.