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

Last change on this file since 277 was 277, checked in by rbri, 11 years ago

PDF plugin: Poppler library updated to version 0.12.3

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