source: trunk/poppler/mypoppler/poppler/ArthurOutputDev.cc @ 461

Last change on this file since 461 was 461, checked in by Silvan Scherrer, 11 years ago

poppler update to 0.14.2

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