root/middleware-offline/trunk/_src/eidmw/pteid-poppler/poppler/ArthurOutputDev.cc @ 226

Revision 226, 21.1 KB (checked in by vsilva, 8 years ago)

Improve PDF native Signature

Line 
1//========================================================================
2//
3// ArthurOutputDev.cc
4//
5// Copyright 2003 Glyph & Cog, LLC
6//
7//========================================================================
8
9//========================================================================
10//
11// Modified under the Poppler project - http://poppler.freedesktop.org
12//
13// All changes made under the Poppler project to this file are licensed
14// under GPL version 2 or later
15//
16// Copyright (C) 2005 Brad Hards <bradh@frogmouth.net>
17// Copyright (C) 2005-2009, 2011, 2012 Albert Astals Cid <aacid@kde.org>
18// Copyright (C) 2008, 2010 Pino Toscano <pino@kde.org>
19// Copyright (C) 2009, 2011 Carlos Garcia Campos <carlosgc@gnome.org>
20// Copyright (C) 2009 Petr Gajdos <pgajdos@novell.com>
21// Copyright (C) 2010 Matthias Fauconneau <matthias.fauconneau@gmail.com>
22// Copyright (C) 2011 Andreas Hartmetz <ahartmetz@gmail.com>
23//
24// To see a description of the changes please see the Changelog file that
25// came with your tarball or type make ChangeLog if you are building from git
26//
27//========================================================================
28
29#include <config.h>
30
31#ifdef USE_GCC_PRAGMAS
32#pragma implementation
33#endif
34
35#include <string.h>
36#include <math.h>
37
38#include "goo/gfile.h"
39#include "GlobalParams.h"
40#include "Error.h"
41#include "Object.h"
42#include "GfxState.h"
43#include "GfxFont.h"
44#include "Link.h"
45#include "FontEncodingTables.h"
46#include <fofi/FoFiTrueType.h>
47#include "ArthurOutputDev.h"
48
49#include <QtCore/QtDebug>
50#include <QtGui/QPainterPath>
51//------------------------------------------------------------------------
52
53#ifdef HAVE_SPLASH
54#include "splash/SplashFontFileID.h"
55#include "splash/SplashFontFile.h"
56#include "splash/SplashFontEngine.h"
57#include "splash/SplashFont.h"
58#include "splash/SplashMath.h"
59#include "splash/SplashPath.h"
60#include "splash/SplashGlyphBitmap.h"
61//------------------------------------------------------------------------
62// SplashOutFontFileID
63//------------------------------------------------------------------------
64
65class SplashOutFontFileID: public SplashFontFileID {
66public:
67
68  SplashOutFontFileID(Ref *rA) { r = *rA; }
69
70  ~SplashOutFontFileID() {}
71
72  GBool matches(SplashFontFileID *id) {
73    return ((SplashOutFontFileID *)id)->r.num == r.num &&
74           ((SplashOutFontFileID *)id)->r.gen == r.gen;
75  }
76
77private:
78
79  Ref r;
80};
81
82#endif
83
84//------------------------------------------------------------------------
85// ArthurOutputDev
86//------------------------------------------------------------------------
87
88ArthurOutputDev::ArthurOutputDev(QPainter *painter):
89  m_painter(painter),
90  m_fontHinting(NoHinting)
91{
92  m_currentBrush = QBrush(Qt::SolidPattern);
93  m_fontEngine = 0;
94  m_font = 0;
95}
96
97ArthurOutputDev::~ArthurOutputDev()
98{
99#ifdef HAVE_SPLASH
100  delete m_fontEngine;
101#endif
102}
103
104void ArthurOutputDev::startDoc(XRef *xrefA) {
105  xref = xrefA;
106#ifdef HAVE_SPLASH
107  delete m_fontEngine;
108
109  const bool isHintingEnabled = m_fontHinting != NoHinting;
110  const bool isSlightHinting = m_fontHinting == SlightHinting;
111
112  m_fontEngine = new SplashFontEngine(
113#if HAVE_T1LIB_H
114  globalParams->getEnableT1lib(),
115#endif
116#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
117  globalParams->getEnableFreeType(),
118  isHintingEnabled,
119  isSlightHinting,
120#endif
121  m_painter->testRenderHint(QPainter::TextAntialiasing));
122#endif
123}
124
125void ArthurOutputDev::startPage(int pageNum, GfxState *state)
126{
127  // fill page with white background.
128  int w = static_cast<int>(state->getPageWidth());
129  int h = static_cast<int>(state->getPageHeight());
130  QColor fillColour(Qt::white);
131  QBrush fill(fillColour);
132  m_painter->save();
133  m_painter->setPen(fillColour);
134  m_painter->setBrush(fill);
135  m_painter->drawRect(0, 0, w, h);
136  m_painter->restore();
137}
138
139void ArthurOutputDev::endPage() {
140}
141
142void ArthurOutputDev::saveState(GfxState *state)
143{
144  m_painter->save();
145}
146
147void ArthurOutputDev::restoreState(GfxState *state)
148{
149  m_painter->restore();
150}
151
152void ArthurOutputDev::updateAll(GfxState *state)
153{
154  OutputDev::updateAll(state);
155  m_needFontUpdate = gTrue;
156}
157
158// This looks wrong - why aren't adjusting the matrix?
159void ArthurOutputDev::updateCTM(GfxState *state, double m11, double m12,
160                                double m21, double m22,
161                                double m31, double m32)
162{
163  updateLineDash(state);
164  updateLineJoin(state);
165  updateLineCap(state);
166  updateLineWidth(state);
167}
168
169void ArthurOutputDev::updateLineDash(GfxState *state)
170{
171  double *dashPattern;
172  int dashLength;
173  double dashStart;
174  state->getLineDash(&dashPattern, &dashLength, &dashStart);
175  QVector<qreal> pattern(dashLength);
176  for (int i = 0; i < dashLength; ++i) {
177    pattern[i] = dashPattern[i];
178  }
179  m_currentPen.setDashPattern(pattern);
180  m_currentPen.setDashOffset(dashStart);
181  m_painter->setPen(m_currentPen);
182}
183
184void ArthurOutputDev::updateFlatness(GfxState *state)
185{
186  // qDebug() << "updateFlatness";
187}
188
189void ArthurOutputDev::updateLineJoin(GfxState *state)
190{
191  switch (state->getLineJoin()) {
192  case 0:
193    m_currentPen.setJoinStyle(Qt::MiterJoin);
194    break;
195  case 1:
196    m_currentPen.setJoinStyle(Qt::RoundJoin);
197    break;
198  case 2:
199    m_currentPen.setJoinStyle(Qt::BevelJoin);
200    break;
201  }
202  m_painter->setPen(m_currentPen);
203}
204
205void ArthurOutputDev::updateLineCap(GfxState *state)
206{
207  switch (state->getLineCap()) {
208  case 0:
209    m_currentPen.setCapStyle(Qt::FlatCap);
210    break;
211  case 1:
212    m_currentPen.setCapStyle(Qt::RoundCap);
213    break;
214  case 2:
215    m_currentPen.setCapStyle(Qt::SquareCap);
216    break;
217  }
218  m_painter->setPen(m_currentPen);
219}
220
221void ArthurOutputDev::updateMiterLimit(GfxState *state)
222{
223  m_currentPen.setMiterLimit(state->getMiterLimit());
224  m_painter->setPen(m_currentPen);
225}
226
227void ArthurOutputDev::updateLineWidth(GfxState *state)
228{
229  m_currentPen.setWidthF(state->getLineWidth());
230  m_painter->setPen(m_currentPen);
231}
232
233void ArthurOutputDev::updateFillColor(GfxState *state)
234{
235  GfxRGB rgb;
236  QColor brushColour = m_currentBrush.color();
237  state->getFillRGB(&rgb);
238  brushColour.setRgbF(colToDbl(rgb.r), colToDbl(rgb.g), colToDbl(rgb.b), brushColour.alphaF());
239  m_currentBrush.setColor(brushColour);
240}
241
242void ArthurOutputDev::updateStrokeColor(GfxState *state)
243{
244  GfxRGB rgb;
245  QColor penColour = m_currentPen.color();
246  state->getStrokeRGB(&rgb);
247  penColour.setRgbF(colToDbl(rgb.r), colToDbl(rgb.g), colToDbl(rgb.b), penColour.alphaF());
248  m_currentPen.setColor(penColour);
249  m_painter->setPen(m_currentPen);
250}
251
252void ArthurOutputDev::updateFillOpacity(GfxState *state)
253{
254  QColor brushColour= m_currentBrush.color();
255  brushColour.setAlphaF(state->getFillOpacity());
256  m_currentBrush.setColor(brushColour);
257}
258
259void ArthurOutputDev::updateStrokeOpacity(GfxState *state)
260{
261  QColor penColour= m_currentPen.color();
262  penColour.setAlphaF(state->getStrokeOpacity());
263  m_currentPen.setColor(penColour);
264  m_painter->setPen(m_currentPen);
265}
266
267void ArthurOutputDev::updateFont(GfxState *state)
268{
269#ifdef HAVE_SPLASH
270  GfxFont *gfxFont;
271  GfxFontLoc *fontLoc;
272  GfxFontType fontType;
273  SplashOutFontFileID *id;
274  SplashFontFile *fontFile;
275  SplashFontSrc *fontsrc = NULL;
276  FoFiTrueType *ff;
277  Object refObj, strObj;
278  GooString *fileName;
279  char *tmpBuf;
280  int tmpBufLen;
281  int *codeToGID;
282  double *textMat;
283  double m11, m12, m21, m22, fontSize;
284  SplashCoord mat[4];
285  int n;
286  int faceIndex = 0;
287  SplashCoord matrix[6];
288
289  m_needFontUpdate = false;
290  m_font = NULL;
291  fileName = NULL;
292  tmpBuf = NULL;
293  fontLoc = NULL;
294
295  if (!(gfxFont = state->getFont())) {
296    goto err1;
297  }
298  fontType = gfxFont->getType();
299  if (fontType == fontType3) {
300    goto err1;
301  }
302
303  // check the font file cache
304  id = new SplashOutFontFileID(gfxFont->getID());
305  if ((fontFile = m_fontEngine->getFontFile(id))) {
306    delete id;
307
308  } else {
309
310    if (!(fontLoc = gfxFont->locateFont(xref, gFalse))) {
311      error(errSyntaxError, -1, "Couldn't find a font for '{0:s}'",
312            gfxFont->getName() ? gfxFont->getName()->getCString()
313                               : "(unnamed)");
314      goto err2;
315    }
316
317    // embedded font
318    if (fontLoc->locType == gfxFontLocEmbedded) {
319      // if there is an embedded font, read it to memory
320      tmpBuf = gfxFont->readEmbFontFile(xref, &tmpBufLen);
321      if (! tmpBuf)
322        goto err2;
323
324    // external font
325    } else { // gfxFontLocExternal
326      fileName = fontLoc->path;
327      fontType = fontLoc->fontType;
328    }
329
330    fontsrc = new SplashFontSrc;
331    if (fileName)
332      fontsrc->setFile(fileName, gFalse);
333    else
334      fontsrc->setBuf(tmpBuf, tmpBufLen, gTrue);
335   
336    // load the font file
337    switch (fontType) {
338    case fontType1:
339      if (!(fontFile = m_fontEngine->loadType1Font(
340                           id,
341                           fontsrc,
342                           (const char **)((Gfx8BitFont *)gfxFont)->getEncoding()))) {
343        error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
344              gfxFont->getName() ? gfxFont->getName()->getCString()
345                                 : "(unnamed)");
346        goto err2;
347      }
348      break;
349    case fontType1C:
350      if (!(fontFile = m_fontEngine->loadType1CFont(
351                           id,
352                           fontsrc,
353                           (const char **)((Gfx8BitFont *)gfxFont)->getEncoding()))) {
354        error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
355              gfxFont->getName() ? gfxFont->getName()->getCString()
356                                 : "(unnamed)");
357        goto err2;
358      }
359      break;
360    case fontType1COT:
361      if (!(fontFile = m_fontEngine->loadOpenTypeT1CFont(
362                           id,
363                           fontsrc,
364                           (const char **)((Gfx8BitFont *)gfxFont)->getEncoding()))) {
365        error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
366              gfxFont->getName() ? gfxFont->getName()->getCString()
367                                 : "(unnamed)");
368        goto err2;
369      }
370      break;
371    case fontTrueType:
372    case fontTrueTypeOT:
373        if (fileName)
374         ff = FoFiTrueType::load(fileName->getCString());
375        else
376        ff = FoFiTrueType::make(tmpBuf, tmpBufLen);
377      if (ff) {
378        codeToGID = ((Gfx8BitFont *)gfxFont)->getCodeToGIDMap(ff);
379        n = 256;
380        delete ff;
381      } else {
382        codeToGID = NULL;
383        n = 0;
384      }
385      if (!(fontFile = m_fontEngine->loadTrueTypeFont(
386                           id,
387                           fontsrc,
388                           codeToGID, n))) {
389        error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
390              gfxFont->getName() ? gfxFont->getName()->getCString()
391                                 : "(unnamed)");
392        goto err2;
393      }
394      break;
395    case fontCIDType0:
396    case fontCIDType0C:
397      if (!(fontFile = m_fontEngine->loadCIDFont(
398                           id,
399                           fontsrc))) {
400        error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
401              gfxFont->getName() ? gfxFont->getName()->getCString()
402                                 : "(unnamed)");
403        goto err2;
404      }
405      break;
406    case fontCIDType0COT:
407      if (((GfxCIDFont *)gfxFont)->getCIDToGID()) {
408        n = ((GfxCIDFont *)gfxFont)->getCIDToGIDLen();
409        codeToGID = (int *)gmallocn(n, sizeof(int));
410        memcpy(codeToGID, ((GfxCIDFont *)gfxFont)->getCIDToGID(),
411               n * sizeof(int));
412      } else {
413        codeToGID = NULL;
414        n = 0;
415      }     
416      if (!(fontFile = m_fontEngine->loadOpenTypeCFFFont(
417                           id,
418                           fontsrc,
419                           codeToGID, n))) {
420        error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
421              gfxFont->getName() ? gfxFont->getName()->getCString()
422                                 : "(unnamed)");
423        goto err2;
424      }
425      break;
426    case fontCIDType2:
427    case fontCIDType2OT:
428      codeToGID = NULL;
429      n = 0;
430      if (((GfxCIDFont *)gfxFont)->getCIDToGID()) {
431        n = ((GfxCIDFont *)gfxFont)->getCIDToGIDLen();
432        if (n) {
433          codeToGID = (int *)gmallocn(n, sizeof(int));
434          memcpy(codeToGID, ((GfxCIDFont *)gfxFont)->getCIDToGID(),
435                  n * sizeof(Gushort));
436        }
437      } else {
438        if (fileName)
439          ff = FoFiTrueType::load(fileName->getCString());
440        else
441          ff = FoFiTrueType::make(tmpBuf, tmpBufLen);
442        if (! ff)
443          goto err2;
444        codeToGID = ((GfxCIDFont *)gfxFont)->getCodeToGIDMap(ff, &n);
445        delete ff;
446      }
447      if (!(fontFile = m_fontEngine->loadTrueTypeFont(
448                           id,
449                           fontsrc,
450                           codeToGID, n, faceIndex))) {
451        error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'",
452              gfxFont->getName() ? gfxFont->getName()->getCString()
453                                 : "(unnamed)");
454        goto err2;
455      }
456      break;
457    default:
458      // this shouldn't happen
459      goto err2;
460    }
461  }
462
463  // get the font matrix
464  textMat = state->getTextMat();
465  fontSize = state->getFontSize();
466  m11 = textMat[0] * fontSize * state->getHorizScaling();
467  m12 = textMat[1] * fontSize * state->getHorizScaling();
468  m21 = textMat[2] * fontSize;
469  m22 = textMat[3] * fontSize;
470
471  {
472  QMatrix painterMatrix = m_painter->worldMatrix();
473  matrix[0] = painterMatrix.m11();
474  matrix[1] = painterMatrix.m12();
475  matrix[2] = painterMatrix.m21();
476  matrix[3] = painterMatrix.m22();
477  matrix[4] = painterMatrix.dx();
478  matrix[5] = painterMatrix.dy();
479  }
480
481  // create the scaled font
482  mat[0] = m11;  mat[1] = -m12;
483  mat[2] = m21;  mat[3] = -m22;
484  m_font = m_fontEngine->getFont(fontFile, mat, matrix);
485
486  delete fontLoc;
487  if (fontsrc && !fontsrc->isFile)
488      fontsrc->unref();
489  return;
490
491 err2:
492  delete id;
493  delete fontLoc;
494 err1:
495  if (fontsrc && !fontsrc->isFile)
496      fontsrc->unref();
497  return;
498#endif
499}
500
501static QPainterPath convertPath(GfxState *state, GfxPath *path, Qt::FillRule fillRule)
502{
503  GfxSubpath *subpath;
504  double x1, y1, x2, y2, x3, y3;
505  int i, j;
506
507  QPainterPath qPath;
508  qPath.setFillRule(fillRule);
509  for (i = 0; i < path->getNumSubpaths(); ++i) {
510    subpath = path->getSubpath(i);
511    if (subpath->getNumPoints() > 0) {
512      state->transform(subpath->getX(0), subpath->getY(0), &x1, &y1);
513      qPath.moveTo(x1, y1);
514      j = 1;
515      while (j < subpath->getNumPoints()) {
516        if (subpath->getCurve(j)) {
517          state->transform(subpath->getX(j), subpath->getY(j), &x1, &y1);
518          state->transform(subpath->getX(j+1), subpath->getY(j+1), &x2, &y2);
519          state->transform(subpath->getX(j+2), subpath->getY(j+2), &x3, &y3);
520          qPath.cubicTo( x1, y1, x2, y2, x3, y3);
521          j += 3;
522        } else {
523          state->transform(subpath->getX(j), subpath->getY(j), &x1, &y1);
524          qPath.lineTo(x1, y1);
525          ++j;
526        }
527      }
528      if (subpath->isClosed()) {
529        qPath.closeSubpath();
530      }
531    }
532  }
533  return qPath;
534}
535
536void ArthurOutputDev::stroke(GfxState *state)
537{
538  m_painter->strokePath( convertPath( state, state->getPath(), Qt::OddEvenFill ), m_currentPen );
539}
540
541void ArthurOutputDev::fill(GfxState *state)
542{
543  m_painter->fillPath( convertPath( state, state->getPath(), Qt::WindingFill ), m_currentBrush );
544}
545
546void ArthurOutputDev::eoFill(GfxState *state)
547{
548  m_painter->fillPath( convertPath( state, state->getPath(), Qt::OddEvenFill ), m_currentBrush );
549}
550
551void ArthurOutputDev::clip(GfxState *state)
552{
553  m_painter->setClipPath(convertPath( state, state->getPath(), Qt::WindingFill ) );
554}
555
556void ArthurOutputDev::eoClip(GfxState *state)
557{
558  m_painter->setClipPath(convertPath( state, state->getPath(), Qt::OddEvenFill ) );
559}
560
561void ArthurOutputDev::drawChar(GfxState *state, double x, double y,
562                               double dx, double dy,
563                               double originX, double originY,
564                               CharCode code, int nBytes, Unicode *u, int uLen) {
565#ifdef HAVE_SPLASH
566  double x1, y1;
567  double x2, y2;
568//   SplashPath *path;
569  int render;
570
571  if (m_needFontUpdate) {
572    updateFont(state);
573  }
574  if (!m_font) {
575    return;
576  }
577
578  // check for invisible text -- this is used by Acrobat Capture
579  render = state->getRender();
580  if (render == 3) {
581    return;
582  }
583
584  x -= originX;
585  y -= originY;
586
587  // fill
588  if (!(render & 1)) {
589    SplashPath * fontPath;
590    fontPath = m_font->getGlyphPath(code);
591    if (fontPath) {
592      QPainterPath qPath;
593      qPath.setFillRule(Qt::WindingFill);
594      for (int i = 0; i < fontPath->length; ++i) {
595        if (fontPath->flags[i] & splashPathFirst) {
596            state->transform(fontPath->pts[i].x+x, -fontPath->pts[i].y+y, &x1, &y1);
597            qPath.moveTo(x1,y1);
598        } else if (fontPath->flags[i] & splashPathCurve) {
599            state->transform(fontPath->pts[i].x+x, -fontPath->pts[i].y+y, &x1, &y1);
600            state->transform(fontPath->pts[i+1].x+x, -fontPath->pts[i+1].y+y, &x2, &y2);
601            qPath.quadTo(x1,y1,x2,y2);
602            ++i;
603        }
604        // FIXME fix this
605        //      else if (fontPath->flags[i] & splashPathArcCW) {
606        //        qDebug() << "Need to implement arc";
607        //      }
608        else {
609            state->transform(fontPath->pts[i].x+x, -fontPath->pts[i].y+y, &x1, &y1);
610            qPath.lineTo(x1,y1);
611        }
612        if (fontPath->flags[i] & splashPathLast) {
613            qPath.closeSubpath();
614        }
615      }
616      GfxRGB rgb;
617      QColor brushColour = m_currentBrush.color();
618      state->getFillRGB(&rgb);
619      brushColour.setRgbF(colToDbl(rgb.r), colToDbl(rgb.g), colToDbl(rgb.b), state->getFillOpacity());
620      m_painter->setBrush(brushColour);
621      QColor penColour = m_currentPen.color();
622      state->getStrokeRGB(&rgb);
623      penColour.setRgbF(colToDbl(rgb.r), colToDbl(rgb.g), colToDbl(rgb.b), state->getStrokeOpacity());
624      m_painter->setPen(penColour);
625      m_painter->drawPath( qPath );
626      delete fontPath;
627    }
628  }
629
630  // stroke
631  if ((render & 3) == 1 || (render & 3) == 2) {
632    qDebug() << "no stroke";
633    /*
634    if ((path = m_font->getGlyphPath(code))) {
635      path->offset((SplashCoord)x1, (SplashCoord)y1);
636      splash->stroke(path);
637      delete path;
638    }
639    */
640  }
641
642  // clip
643  if (render & 4) {
644    qDebug() << "no clip";
645    /*
646    path = m_font->getGlyphPath(code);
647    path->offset((SplashCoord)x1, (SplashCoord)y1);
648    if (textClipPath) {
649      textClipPath->append(path);
650      delete path;
651    } else {
652      textClipPath = path;
653    }
654    */
655  }
656#endif
657}
658
659GBool ArthurOutputDev::beginType3Char(GfxState *state, double x, double y,
660                                      double dx, double dy,
661                                      CharCode code, Unicode *u, int uLen)
662{
663  return gFalse;
664}
665
666void ArthurOutputDev::endType3Char(GfxState *state)
667{
668}
669
670void ArthurOutputDev::type3D0(GfxState *state, double wx, double wy)
671{
672}
673
674void ArthurOutputDev::type3D1(GfxState *state, double wx, double wy,
675                              double llx, double lly, double urx, double ury)
676{
677}
678
679void ArthurOutputDev::endTextObject(GfxState *state)
680{
681}
682
683
684void ArthurOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
685                                    int width, int height, GBool invert,
686                                    GBool interpolate, GBool inlineImg)
687{
688  qDebug() << "drawImageMask";
689#if 0
690  unsigned char *buffer;
691  unsigned char *dest;
692  cairo_surface_t *image;
693  cairo_pattern_t *pattern;
694  int x, y;
695  ImageStream *imgStr;
696  Guchar *pix;
697  double *ctm;
698  cairo_matrix_t matrix;
699  int invert_bit;
700  int row_stride;
701
702  row_stride = (width + 3) & ~3;
703  buffer = (unsigned char *) malloc (height * row_stride);
704  if (buffer == NULL) {
705    error(-1, "Unable to allocate memory for image.");
706    return;
707  }
708
709  /* TODO: Do we want to cache these? */
710  imgStr = new ImageStream(str, width, 1, 1);
711  imgStr->reset();
712
713  invert_bit = invert ? 1 : 0;
714
715  for (y = 0; y < height; y++) {
716    pix = imgStr->getLine();
717    dest = buffer + y * row_stride;
718    for (x = 0; x < width; x++) {
719
720      if (pix[x] ^ invert_bit)
721        *dest++ = 0;
722      else
723        *dest++ = 255;
724    }
725  }
726
727  image = cairo_image_surface_create_for_data (buffer, CAIRO_FORMAT_A8,
728                                          width, height, row_stride);
729  if (image == NULL)
730    return;
731  pattern = cairo_pattern_create_for_surface (image);
732  if (pattern == NULL)
733    return;
734
735  ctm = state->getCTM();
736  LOG (printf ("drawImageMask %dx%d, matrix: %f, %f, %f, %f, %f, %f\n",
737               width, height, ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]));
738  matrix.xx = ctm[0] / width;
739  matrix.xy = -ctm[2] / height;
740  matrix.yx = ctm[1] / width;
741  matrix.yy = -ctm[3] / height;
742  matrix.x0 = ctm[2] + ctm[4];
743  matrix.y0 = ctm[3] + ctm[5];
744  cairo_matrix_invert (&matrix);
745  cairo_pattern_set_matrix (pattern, &matrix);
746
747  cairo_pattern_set_filter (pattern, CAIRO_FILTER_BEST);
748  /* FIXME: Doesn't the image mask support any colorspace? */
749  cairo_set_source_rgb (cairo, fill_color.r, fill_color.g, fill_color.b);
750  cairo_mask (cairo, pattern);
751
752  cairo_pattern_destroy (pattern);
753  cairo_surface_destroy (image);
754  free (buffer);
755  imgStr->close ();
756  delete imgStr;
757#endif
758}
759
760//TODO: lots more work here.
761void ArthurOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
762                                int width, int height,
763                                GfxImageColorMap *colorMap,
764                                GBool interpolate, int *maskColors, GBool inlineImg)
765{
766  unsigned int *data;
767  unsigned int *line;
768  int x, y;
769  ImageStream *imgStr;
770  Guchar *pix;
771  int i;
772  double *ctm;
773  QMatrix matrix;
774  QImage image;
775  int stride;
776 
777  /* TODO: Do we want to cache these? */
778  imgStr = new ImageStream(str, width,
779                           colorMap->getNumPixelComps(),
780                           colorMap->getBits());
781  imgStr->reset();
782 
783  image = QImage(width, height, QImage::Format_ARGB32);
784  data = (unsigned int *)image.bits();
785  stride = image.bytesPerLine()/4;
786  for (y = 0; y < height; y++) {
787    pix = imgStr->getLine();
788    line = data+y*stride;
789    colorMap->getRGBLine(pix, line, width);
790
791    if (maskColors) {
792      for (x = 0; x < width; x++) {
793        for (i = 0; i < colorMap->getNumPixelComps(); ++i) {
794            if (pix[i] < maskColors[2*i] * 255||
795                pix[i] > maskColors[2*i+1] * 255) {
796                *line = *line | 0xff000000;
797                break;
798            }
799        }
800        pix += colorMap->getNumPixelComps();
801        line++;
802      }
803    } else {
804      for (x = 0; x < width; x++) { *line = *line | 0xff000000; line++; }
805    }
806  }
807
808  ctm = state->getCTM();
809  matrix.setMatrix(ctm[0] / width, ctm[1] / width, -ctm[2] / height, -ctm[3] / height, ctm[2] + ctm[4], ctm[3] + ctm[5]);
810
811  m_painter->setMatrix(matrix, true);
812  m_painter->drawImage( QPoint(0,0), image );
813  delete imgStr;
814
815}
Note: See TracBrowser for help on using the browser.