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

Last change on this file since 257 was 257, checked in by Eugene Romanenko, 13 years ago

PDF plugin: Poppler library updated to version 0.10.0

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