~ubuntu-branches/ubuntu/vivid/emscripten/vivid

« back to all changes in this revision

Viewing changes to tests/poppler/poppler/ArthurOutputDev.cc

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2013-05-02 13:11:51 UTC
  • Revision ID: package-import@ubuntu.com-20130502131151-q8dvteqr1ef2x7xz
Tags: upstream-1.4.1~20130504~adb56cb
ImportĀ upstreamĀ versionĀ 1.4.1~20130504~adb56cb

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
// Copyright (C) 2010 Matthias Fauconneau <matthias.fauconneau@gmail.com>
 
22
//
 
23
// To see a description of the changes please see the Changelog file that
 
24
// came with your tarball or type make ChangeLog if you are building from git
 
25
//
 
26
//========================================================================
 
27
 
 
28
#include <config.h>
 
29
 
 
30
#ifdef USE_GCC_PRAGMAS
 
31
#pragma implementation
 
32
#endif
 
33
 
 
34
#include <string.h>
 
35
#include <math.h>
 
36
 
 
37
#include "goo/gfile.h"
 
38
#include "GlobalParams.h"
 
39
#include "Error.h"
 
40
#include "Object.h"
 
41
#include "GfxState.h"
 
42
#include "GfxFont.h"
 
43
#include "Link.h"
 
44
#include "CharCodeToUnicode.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
 
 
65
class SplashOutFontFileID: public SplashFontFileID {
 
66
public:
 
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
 
 
77
private:
 
78
 
 
79
  Ref r;
 
80
};
 
81
 
 
82
#endif
 
83
 
 
84
//------------------------------------------------------------------------
 
85
// ArthurOutputDev
 
86
//------------------------------------------------------------------------
 
87
 
 
88
ArthurOutputDev::ArthurOutputDev(QPainter *painter):
 
89
  m_painter(painter)
 
90
{
 
91
  m_currentBrush = QBrush(Qt::SolidPattern);
 
92
  m_fontEngine = 0;
 
93
  m_font = 0;
 
94
}
 
95
 
 
96
ArthurOutputDev::~ArthurOutputDev()
 
97
{
 
98
#ifdef HAVE_SPLASH
 
99
  delete m_fontEngine;
 
100
#endif
 
101
}
 
102
 
 
103
void 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
 
 
119
void 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
 
 
133
void ArthurOutputDev::endPage() {
 
134
}
 
135
 
 
136
void ArthurOutputDev::drawLink(Link *link, Catalog *catalog)
 
137
{
 
138
}
 
139
 
 
140
void ArthurOutputDev::saveState(GfxState *state)
 
141
{
 
142
  m_painter->save();
 
143
}
 
144
 
 
145
void ArthurOutputDev::restoreState(GfxState *state)
 
146
{
 
147
  m_painter->restore();
 
148
}
 
149
 
 
150
void 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?
 
157
void 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
 
 
167
void 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
 
 
182
void ArthurOutputDev::updateFlatness(GfxState *state)
 
183
{
 
184
  // qDebug() << "updateFlatness";
 
185
}
 
186
 
 
187
void 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
 
 
203
void 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
 
 
219
void ArthurOutputDev::updateMiterLimit(GfxState *state)
 
220
{
 
221
  m_currentPen.setMiterLimit(state->getMiterLimit());
 
222
  m_painter->setPen(m_currentPen);
 
223
}
 
224
 
 
225
void ArthurOutputDev::updateLineWidth(GfxState *state)
 
226
{
 
227
  m_currentPen.setWidthF(state->getLineWidth());
 
228
  m_painter->setPen(m_currentPen);
 
229
}
 
230
 
 
231
void 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
 
 
240
void 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
 
 
250
void ArthurOutputDev::updateFillOpacity(GfxState *state)
 
251
{
 
252
  QColor brushColour= m_currentBrush.color();
 
253
  brushColour.setAlphaF(state->getFillOpacity());
 
254
  m_currentBrush.setColor(brushColour);
 
255
}
 
256
 
 
257
void 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
 
 
265
void ArthurOutputDev::updateFont(GfxState *state)
 
266
{
 
267
#ifdef HAVE_SPLASH
 
268
  GfxFont *gfxFont;
 
269
  GfxFontType fontType;
 
270
  SplashOutFontFileID *id;
 
271
  SplashFontFile *fontFile;
 
272
  SplashFontSrc *fontsrc = NULL;
 
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, gTrue);
 
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
  if (fontsrc && !fontsrc->isFile)
 
488
      fontsrc->unref();
 
489
  return;
 
490
 
 
491
 err2:
 
492
  delete id;
 
493
 err1:
 
494
  if (fontsrc && !fontsrc->isFile)
 
495
      fontsrc->unref();
 
496
  return;
 
497
#endif
 
498
}
 
499
 
 
500
static QPainterPath convertPath(GfxState *state, GfxPath *path, Qt::FillRule fillRule)
 
501
{
 
502
  GfxSubpath *subpath;
 
503
  double x1, y1, x2, y2, x3, y3;
 
504
  int i, j;
 
505
 
 
506
  QPainterPath qPath;
 
507
  qPath.setFillRule(fillRule);
 
508
  for (i = 0; i < path->getNumSubpaths(); ++i) {
 
509
    subpath = path->getSubpath(i);
 
510
    if (subpath->getNumPoints() > 0) {
 
511
      state->transform(subpath->getX(0), subpath->getY(0), &x1, &y1);
 
512
      qPath.moveTo(x1, y1);
 
513
      j = 1;
 
514
      while (j < subpath->getNumPoints()) {
 
515
        if (subpath->getCurve(j)) {
 
516
          state->transform(subpath->getX(j), subpath->getY(j), &x1, &y1);
 
517
          state->transform(subpath->getX(j+1), subpath->getY(j+1), &x2, &y2);
 
518
          state->transform(subpath->getX(j+2), subpath->getY(j+2), &x3, &y3);
 
519
          qPath.cubicTo( x1, y1, x2, y2, x3, y3);
 
520
          j += 3;
 
521
        } else {
 
522
          state->transform(subpath->getX(j), subpath->getY(j), &x1, &y1);
 
523
          qPath.lineTo(x1, y1);
 
524
          ++j;
 
525
        }
 
526
      }
 
527
      if (subpath->isClosed()) {
 
528
        qPath.closeSubpath();
 
529
      }
 
530
    }
 
531
  }
 
532
  return qPath;
 
533
}
 
534
 
 
535
void ArthurOutputDev::stroke(GfxState *state)
 
536
{
 
537
  m_painter->strokePath( convertPath( state, state->getPath(), Qt::OddEvenFill ), m_currentPen );
 
538
}
 
539
 
 
540
void ArthurOutputDev::fill(GfxState *state)
 
541
{
 
542
  m_painter->fillPath( convertPath( state, state->getPath(), Qt::WindingFill ), m_currentBrush );
 
543
}
 
544
 
 
545
void ArthurOutputDev::eoFill(GfxState *state)
 
546
{
 
547
  m_painter->fillPath( convertPath( state, state->getPath(), Qt::OddEvenFill ), m_currentBrush );
 
548
}
 
549
 
 
550
void ArthurOutputDev::clip(GfxState *state)
 
551
{
 
552
  m_painter->setClipPath(convertPath( state, state->getPath(), Qt::WindingFill ) );
 
553
}
 
554
 
 
555
void ArthurOutputDev::eoClip(GfxState *state)
 
556
{
 
557
  m_painter->setClipPath(convertPath( state, state->getPath(), Qt::OddEvenFill ) );
 
558
}
 
559
 
 
560
void ArthurOutputDev::drawChar(GfxState *state, double x, double y,
 
561
                               double dx, double dy,
 
562
                               double originX, double originY,
 
563
                               CharCode code, int nBytes, Unicode *u, int uLen) {
 
564
#ifdef HAVE_SPLASH
 
565
  double x1, y1;
 
566
  double x2, y2;
 
567
//   SplashPath *path;
 
568
  int render;
 
569
 
 
570
  if (m_needFontUpdate) {
 
571
    updateFont(state);
 
572
  }
 
573
  if (!m_font) {
 
574
    return;
 
575
  }
 
576
 
 
577
  // check for invisible text -- this is used by Acrobat Capture
 
578
  render = state->getRender();
 
579
  if (render == 3) {
 
580
    return;
 
581
  }
 
582
 
 
583
  x -= originX;
 
584
  y -= originY;
 
585
 
 
586
  // fill
 
587
  if (!(render & 1)) {
 
588
    SplashPath * fontPath;
 
589
    fontPath = m_font->getGlyphPath(code);
 
590
    if (fontPath) {
 
591
      QPainterPath qPath;
 
592
      qPath.setFillRule(Qt::WindingFill);
 
593
      for (int i = 0; i < fontPath->length; ++i) {
 
594
        if (fontPath->flags[i] & splashPathFirst) {
 
595
            state->transform(fontPath->pts[i].x+x, -fontPath->pts[i].y+y, &x1, &y1);
 
596
            qPath.moveTo(x1,y1);
 
597
        } else if (fontPath->flags[i] & splashPathCurve) {
 
598
            state->transform(fontPath->pts[i].x+x, -fontPath->pts[i].y+y, &x1, &y1);
 
599
            state->transform(fontPath->pts[i+1].x+x, -fontPath->pts[i+1].y+y, &x2, &y2);
 
600
            qPath.quadTo(x1,y1,x2,y2);
 
601
            ++i;
 
602
        }
 
603
        // FIXME fix this
 
604
        //      else if (fontPath->flags[i] & splashPathArcCW) {
 
605
        //        qDebug() << "Need to implement arc";
 
606
        //      }
 
607
        else {
 
608
            state->transform(fontPath->pts[i].x+x, -fontPath->pts[i].y+y, &x1, &y1);
 
609
            qPath.lineTo(x1,y1);
 
610
        }
 
611
        if (fontPath->flags[i] & splashPathLast) {
 
612
            qPath.closeSubpath();
 
613
        }
 
614
      }
 
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
      delete fontPath;
 
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
 
 
658
GBool 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
 
 
665
void ArthurOutputDev::endType3Char(GfxState *state)
 
666
{
 
667
}
 
668
 
 
669
void ArthurOutputDev::type3D0(GfxState *state, double wx, double wy)
 
670
{
 
671
}
 
672
 
 
673
void ArthurOutputDev::type3D1(GfxState *state, double wx, double wy,
 
674
                              double llx, double lly, double urx, double ury)
 
675
{
 
676
}
 
677
 
 
678
void ArthurOutputDev::endTextObject(GfxState *state)
 
679
{
 
680
}
 
681
 
 
682
 
 
683
void 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.
 
760
void 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 int *data;
 
766
  unsigned int *line;
 
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
  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
  /* 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
  image = QImage(width, height, QImage::Format_ARGB32);
 
790
  data = (unsigned int *)image.bits();
 
791
  stride = image.bytesPerLine()/4;
 
792
  for (y = 0; y < height; y++) {
 
793
    pix = imgStr->getLine();
 
794
    line = data+y*stride;
 
795
    colorMap->getRGBLine(pix, line, width);
 
796
 
 
797
    if (maskColors) {
 
798
      for (x = 0; x < width; x++) {
 
799
        for (i = 0; i < colorMap->getNumPixelComps(); ++i) {
 
800
            if (pix[i] < maskColors[2*i] * 255||
 
801
                pix[i] > maskColors[2*i+1] * 255) {
 
802
                *line = *line | 0xff000000;
 
803
                break;
 
804
            }
 
805
        }
 
806
        pix += colorMap->getNumPixelComps();
 
807
        line++;
 
808
      }
 
809
    } else {
 
810
      for (x = 0; x < width; x++) { *line = *line | 0xff000000; line++; }
 
811
    }
 
812
  }
 
813
 
 
814
  ctm = state->getCTM();
 
815
  matrix.setMatrix(ctm[0] / width, ctm[1] / width, -ctm[2] / height, -ctm[3] / height, ctm[2] + ctm[4], ctm[3] + ctm[5]);
 
816
 
 
817
  m_painter->setMatrix(matrix, true);
 
818
  m_painter->drawImage( QPoint(0,0), image );
 
819
  delete imgStr;
 
820
 
 
821
}