Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "pdfioutdev_gpl.hxx"
21 : #include "pnghelper.hxx"
22 :
23 : #include <stdlib.h>
24 : #include <stdio.h>
25 : #include <assert.h>
26 : #include <math.h>
27 : #include <vector>
28 :
29 : #include <boost/shared_array.hpp>
30 :
31 : #if defined __SUNPRO_CC
32 : #pragma disable_warn
33 : #elif defined _MSC_VER
34 : #pragma warning(push, 1)
35 : #endif
36 :
37 : // sigh, UTF8.h was removed in poppler-0.21.0 and put back in 0.21.1
38 : // FIXME: we can't use #if POPPLER_CHECK_VERSION(0, 21, 0) && !POPPLER_CHECK_VERSION(0, 21, 1)
39 : // because the internal poppler does not provide poppler-version.h and the macro always returns 0
40 : #if POPPLER_CHECK_VERSION(0, 21, 1)
41 : #include "UTF8.h"
42 : #elif POPPLER_CHECK_VERSION(0, 21, 0)
43 : #include "UTF.h"
44 : #else
45 : #include "UTF8.h"
46 : #endif
47 :
48 : #if defined __SUNPRO_CC
49 : #pragma enable_warn
50 : #elif defined _MSC_VER
51 : #pragma warning(pop)
52 : #endif
53 :
54 : #ifdef WNT
55 : # define snprintf _snprintf
56 :
57 : #if defined __GNUC__
58 : #pragma GCC diagnostic warning "-Wformat"
59 : #pragma GCC diagnostic warning "-Wformat-extra-args"
60 : #endif
61 : #endif
62 :
63 : /* SYNC STREAMS
64 : ============
65 :
66 : We stream human-readble tokens to stdout, and binary data (fonts,
67 : bitmaps) to g_binary_out. Another process reads from those pipes, and
68 : there lies the rub: things can deadlock, if the two involved
69 : processes access the pipes in different order. At any point in
70 : time, both processes must access the same pipe. To ensure this,
71 : data must be flushed to the OS before writing to a different pipe,
72 : otherwise not-yet-written data will leave the reading process
73 : waiting on the wrong pipe.
74 : */
75 :
76 : namespace pdfi
77 : {
78 :
79 : /// cut off very small numbers & clamp value to zero
80 2991 : inline double normalize( double val )
81 : {
82 2991 : return fabs(val) < 0.0000001 ? 0.0 : val;
83 : }
84 :
85 : namespace
86 : {
87 :
88 : /** Escapes line-ending characters (\n and \r) in input string.
89 : */
90 348 : boost::shared_array<char> lcl_escapeLineFeeds(const char* const i_pStr)
91 : {
92 348 : size_t nLength(strlen(i_pStr));
93 348 : char* pBuffer = new char[2*nLength+1];
94 :
95 348 : const char* pRead = i_pStr;
96 348 : char* pWrite = pBuffer;
97 1584 : while( nLength-- )
98 : {
99 888 : if( *pRead == '\r' )
100 : {
101 0 : *pWrite++ = '\\';
102 0 : *pWrite++ = 'r';
103 : }
104 888 : else if( *pRead == '\n' )
105 : {
106 0 : *pWrite++ = '\\';
107 0 : *pWrite++ = 'n';
108 : }
109 888 : else if( *pRead == '\\' )
110 : {
111 0 : *pWrite++ = '\\';
112 0 : *pWrite++ = '\\';
113 : }
114 : else
115 888 : *pWrite++ = *pRead;
116 888 : pRead++;
117 : }
118 348 : *pWrite++ = 0;
119 :
120 348 : return boost::shared_array<char>(pBuffer);
121 : }
122 :
123 : }
124 :
125 : /// for the temp char buffer the header gets snprintfed in
126 : #define WRITE_BUFFER_SIZE 1024
127 :
128 : /// for the initial std::vector capacity when copying stream from xpdf
129 : #define WRITE_BUFFER_INITIAL_CAPACITY (1024*100)
130 :
131 3 : void initBuf(OutputBuffer& io_rBuffer)
132 : {
133 3 : io_rBuffer.reserve(WRITE_BUFFER_INITIAL_CAPACITY);
134 3 : }
135 :
136 6 : void writeBinaryBuffer( const OutputBuffer& rBuffer )
137 : {
138 : // ---sync point--- see SYNC STREAMS above
139 6 : fflush(stdout);
140 :
141 : // put buffer to stderr
142 6 : if( !rBuffer.empty() )
143 6 : if( fwrite(&rBuffer[0], sizeof(char),
144 6 : rBuffer.size(), g_binary_out) != (size_t)rBuffer.size() )
145 0 : exit(1); // error
146 :
147 : // ---sync point--- see SYNC STREAMS above
148 6 : fflush(g_binary_out);
149 6 : }
150 :
151 3 : void writeJpeg_( OutputBuffer& o_rOutputBuf, Stream* str, bool bWithLinefeed )
152 : {
153 : // dump JPEG file as-is
154 : #if POPPLER_CHECK_VERSION(0, 17, 3)
155 3 : str = str->getBaseStream();
156 : #else
157 : str = ((DCTStream *)str)->getRawStream();
158 : #endif
159 3 : str->reset();
160 :
161 : int c;
162 3 : o_rOutputBuf.clear();
163 132393 : while((c=str->getChar()) != EOF)
164 132387 : o_rOutputBuf.push_back(static_cast<char>(c));
165 :
166 3 : printf( " JPEG %d", (int)o_rOutputBuf.size() );
167 3 : if( bWithLinefeed )
168 3 : printf("\n");
169 :
170 3 : str->close();
171 3 : }
172 :
173 0 : void writePbm_(OutputBuffer& o_rOutputBuf, Stream* str, int width, int height, bool bWithLinefeed, bool bInvert )
174 : {
175 : // write as PBM (char by char, to avoid stdlib lineend messing)
176 0 : o_rOutputBuf.clear();
177 0 : o_rOutputBuf.resize(WRITE_BUFFER_SIZE);
178 0 : o_rOutputBuf[0] = 'P';
179 0 : o_rOutputBuf[1] = '4';
180 0 : o_rOutputBuf[2] = 0x0A;
181 0 : char *pAsCharPtr = reinterpret_cast<char *>(&o_rOutputBuf[3]);
182 0 : int nOutLen = snprintf(pAsCharPtr, WRITE_BUFFER_SIZE-10, "%d %d", width, height);
183 0 : if( nOutLen < 0 )
184 0 : nOutLen = WRITE_BUFFER_SIZE-10;
185 0 : o_rOutputBuf[3+nOutLen] =0x0A;
186 0 : o_rOutputBuf[3+nOutLen+1]=0;
187 :
188 0 : const int header_size = 3+nOutLen+1;
189 0 : const int size = height * ((width + 7) / 8);
190 :
191 0 : printf( " PBM %d", size + header_size );
192 0 : if( bWithLinefeed )
193 0 : printf("\n");
194 :
195 : // trim buffer to exact header length
196 0 : o_rOutputBuf.resize(header_size);
197 :
198 : // initialize stream
199 0 : str->reset();
200 :
201 : // copy the raw stream
202 0 : if( bInvert )
203 : {
204 0 : for( int i=0; i<size; ++i)
205 0 : o_rOutputBuf.push_back(static_cast<char>(str->getChar() ^ 0xff));
206 : }
207 : else
208 : {
209 0 : for( int i=0; i<size; ++i)
210 0 : o_rOutputBuf.push_back(static_cast<char>(str->getChar()));
211 : }
212 :
213 0 : str->close();
214 0 : }
215 :
216 0 : void writePpm_( OutputBuffer& o_rOutputBuf,
217 : Stream* str,
218 : int width,
219 : int height,
220 : GfxImageColorMap* colorMap,
221 : bool bWithLinefeed )
222 : {
223 : // write as PPM (char by char, to avoid stdlib lineend messing)
224 0 : o_rOutputBuf.clear();
225 0 : o_rOutputBuf.resize(WRITE_BUFFER_SIZE);
226 0 : o_rOutputBuf[0] = 'P';
227 0 : o_rOutputBuf[1] = '6';
228 0 : o_rOutputBuf[2] = '\n';
229 0 : char *pAsCharPtr = reinterpret_cast<char *>(&o_rOutputBuf[3]);
230 0 : int nOutLen = snprintf(pAsCharPtr, WRITE_BUFFER_SIZE-10, "%d %d", width, height);
231 0 : if( nOutLen < 0 )
232 0 : nOutLen = WRITE_BUFFER_SIZE-10;
233 0 : o_rOutputBuf[3+nOutLen] ='\n';
234 0 : o_rOutputBuf[3+nOutLen+1]='2';
235 0 : o_rOutputBuf[3+nOutLen+2]='5';
236 0 : o_rOutputBuf[3+nOutLen+3]='5';
237 0 : o_rOutputBuf[3+nOutLen+4]='\n';
238 0 : o_rOutputBuf[3+nOutLen+5]=0;
239 :
240 0 : const int header_size = 3+nOutLen+5;
241 0 : const int size = width*height*3 + header_size;
242 :
243 0 : printf( " PPM %d", size );
244 0 : if( bWithLinefeed )
245 0 : printf("\n");
246 :
247 : // trim buffer to exact header size
248 0 : o_rOutputBuf.resize(header_size);
249 :
250 : // initialize stream
251 : Guchar *p;
252 : GfxRGB rgb;
253 : ImageStream* imgStr =
254 : new ImageStream(str,
255 : width,
256 : colorMap->getNumPixelComps(),
257 0 : colorMap->getBits());
258 0 : imgStr->reset();
259 :
260 0 : for( int y=0; y<height; ++y)
261 : {
262 0 : p = imgStr->getLine();
263 0 : for( int x=0; x<width; ++x)
264 : {
265 0 : colorMap->getRGB(p, &rgb);
266 0 : o_rOutputBuf.push_back(colToByte(rgb.r));
267 0 : o_rOutputBuf.push_back(colToByte(rgb.g));
268 0 : o_rOutputBuf.push_back(colToByte(rgb.b));
269 :
270 0 : p +=colorMap->getNumPixelComps();
271 : }
272 : }
273 :
274 0 : delete imgStr;
275 :
276 0 : }
277 :
278 : // call this only for 1 bit image streams !
279 0 : void writePng_( OutputBuffer& o_rOutputBuf,
280 : Stream* str,
281 : int width,
282 : int height,
283 : GfxRGB& zeroColor,
284 : GfxRGB& oneColor,
285 : bool bIsMask,
286 : bool bWithLinefeed )
287 : {
288 0 : o_rOutputBuf.clear();
289 :
290 : // get png image
291 0 : PngHelper::createPng( o_rOutputBuf, str, width, height, zeroColor, oneColor, bIsMask );
292 :
293 0 : printf( " PNG %d", (int)o_rOutputBuf.size() );
294 0 : if( bWithLinefeed )
295 0 : printf("\n");
296 0 : }
297 :
298 0 : void writePng_( OutputBuffer& o_rOutputBuf,
299 : Stream* str,
300 : int width, int height, GfxImageColorMap* colorMap,
301 : Stream* maskStr,
302 : int maskWidth, int maskHeight, GfxImageColorMap* maskColorMap,
303 : bool bWithLinefeed )
304 : {
305 0 : o_rOutputBuf.clear();
306 :
307 : // get png image
308 0 : PngHelper::createPng( o_rOutputBuf, str, width, height, colorMap, maskStr, maskWidth, maskHeight, maskColorMap );
309 :
310 0 : printf( " PNG %d", (int)o_rOutputBuf.size() );
311 0 : if( bWithLinefeed )
312 0 : printf("\n");
313 0 : }
314 :
315 0 : void writePng_( OutputBuffer& o_rOutputBuf,
316 : Stream* str,
317 : int width, int height, GfxImageColorMap* colorMap,
318 : Stream* maskStr,
319 : int maskWidth, int maskHeight, bool maskInvert,
320 : bool bWithLinefeed )
321 : {
322 0 : o_rOutputBuf.clear();
323 :
324 : // get png image
325 0 : PngHelper::createPng( o_rOutputBuf, str, width, height, colorMap, maskStr, maskWidth, maskHeight, maskInvert );
326 :
327 0 : printf( " PNG %d", (int)o_rOutputBuf.size() );
328 0 : if( bWithLinefeed )
329 0 : printf("\n");
330 0 : }
331 :
332 : // stolen from ImageOutputDev.cc
333 0 : void writeMask_( OutputBuffer& o_rOutputBuf, Stream* str, int width, int height, bool bWithLinefeed, bool bInvert )
334 : {
335 0 : if( str->getKind() == strDCT )
336 0 : writeJpeg_(o_rOutputBuf, str, bWithLinefeed);
337 : else
338 0 : writePbm_(o_rOutputBuf, str, width, height, bWithLinefeed, bInvert );
339 0 : }
340 :
341 3 : void writeImage_( OutputBuffer& o_rOutputBuf,
342 : Stream* str,
343 : int width,
344 : int height,
345 : GfxImageColorMap* colorMap,
346 : bool bWithLinefeed )
347 : {
348 : // dump JPEG file
349 9 : if( str->getKind() == strDCT &&
350 6 : (colorMap->getNumPixelComps() == 1 ||
351 3 : colorMap->getNumPixelComps() == 3) )
352 : {
353 3 : writeJpeg_(o_rOutputBuf, str, bWithLinefeed);
354 : }
355 0 : else if (colorMap->getNumPixelComps() == 1 &&
356 0 : colorMap->getBits() == 1)
357 : {
358 : // this is a two color bitmap, write a png
359 : // provide default colors
360 0 : GfxRGB zeroColor = { 0, 0, 0 },
361 0 : oneColor = { byteToCol( 0xff ), byteToCol( 0xff ), byteToCol( 0xff ) };
362 0 : if( colorMap->getColorSpace()->getMode() == csIndexed || colorMap->getColorSpace()->getMode() == csDeviceGray )
363 : {
364 0 : Guchar nIndex = 0;
365 0 : colorMap->getRGB( &nIndex, &zeroColor );
366 0 : nIndex = 1;
367 0 : colorMap->getRGB( &nIndex, &oneColor );
368 : }
369 0 : writePng_( o_rOutputBuf, str, width, height, zeroColor, oneColor, false, bWithLinefeed );
370 : }
371 : else
372 0 : writePpm_( o_rOutputBuf, str, width, height, colorMap, bWithLinefeed );
373 3 : }
374 :
375 : // forwarders
376 : // ------------------------------------------------------------------
377 :
378 : inline void writeImage( OutputBuffer& o_rOutputBuf,
379 : Stream* str,
380 : int width,
381 : int height,
382 : GfxImageColorMap* colorMap ) { writeImage_(o_rOutputBuf,str,width,height,colorMap,false); }
383 3 : inline void writeImageLF( OutputBuffer& o_rOutputBuf,
384 : Stream* str,
385 : int width,
386 : int height,
387 3 : GfxImageColorMap* colorMap ) { writeImage_(o_rOutputBuf,str,width,height,colorMap,true); }
388 : inline void writeMask( OutputBuffer& o_rOutputBuf,
389 : Stream* str,
390 : int width,
391 : int height,
392 : bool bInvert ) { writeMask_(o_rOutputBuf,str,width,height,false,bInvert); }
393 0 : inline void writeMaskLF( OutputBuffer& o_rOutputBuf,
394 : Stream* str,
395 : int width,
396 : int height,
397 0 : bool bInvert ) { writeMask_(o_rOutputBuf,str,width,height,true,bInvert); }
398 :
399 : // ------------------------------------------------------------------
400 :
401 :
402 9 : int PDFOutDev::parseFont( long long nNewId, GfxFont* gfxFont, GfxState* state ) const
403 : {
404 9 : FontAttributes aNewFont;
405 9 : int nSize = 0;
406 :
407 9 : GooString* pFamily = gfxFont->getName();
408 9 : if( pFamily )
409 : {
410 9 : aNewFont.familyName.clear();
411 9 : aNewFont.familyName.append( gfxFont->getName() );
412 : }
413 : else
414 : {
415 0 : aNewFont.familyName.clear();
416 0 : aNewFont.familyName.append( "Arial" );
417 : }
418 :
419 9 : aNewFont.isBold = gfxFont->isBold();
420 9 : aNewFont.isItalic = gfxFont->isItalic();
421 9 : aNewFont.size = state->getTransformedFontSize();
422 9 : aNewFont.isUnderline = false;
423 :
424 9 : if( gfxFont->getType() == fontTrueType || gfxFont->getType() == fontType1 )
425 : {
426 : // TODO(P3): Unfortunately, need to read stream twice, since
427 : // we must write byte count to stdout before
428 9 : char* pBuf = gfxFont->readEmbFontFile( m_pDoc->getXRef(), &nSize );
429 9 : if( pBuf )
430 : {
431 9 : aNewFont.isEmbedded = true;
432 9 : gfree(pBuf);
433 : }
434 : }
435 :
436 9 : m_aFontMap[ nNewId ] = aNewFont;
437 9 : return nSize;
438 : }
439 :
440 9 : void PDFOutDev::writeFontFile( GfxFont* gfxFont ) const
441 : {
442 9 : if( gfxFont->getType() != fontTrueType && gfxFont->getType() != fontType1 )
443 0 : return;
444 :
445 9 : int nSize = 0;
446 9 : char* pBuf = gfxFont->readEmbFontFile( m_pDoc->getXRef(), &nSize );
447 9 : if( !pBuf )
448 0 : return;
449 :
450 : // ---sync point--- see SYNC STREAMS above
451 9 : fflush(stdout);
452 :
453 9 : if( fwrite(pBuf, sizeof(char), nSize, g_binary_out) != (size_t)nSize )
454 : {
455 0 : gfree(pBuf);
456 0 : exit(1); // error
457 : }
458 : // ---sync point--- see SYNC STREAMS above
459 9 : fflush(g_binary_out);
460 9 : gfree(pBuf);
461 : }
462 :
463 15 : void PDFOutDev::printPath( GfxPath* pPath ) const
464 : {
465 15 : int nSubPaths = pPath ? pPath->getNumSubpaths() : 0;
466 30 : for( int i=0; i<nSubPaths; i++ )
467 : {
468 15 : GfxSubpath* pSub = pPath->getSubpath( i );
469 15 : const int nPoints = pSub->getNumPoints();
470 :
471 15 : printf( " subpath %d", pSub->isClosed() );
472 :
473 96 : for( int n=0; n<nPoints; ++n )
474 : {
475 : printf( " %f %f %d",
476 : normalize(pSub->getX(n)),
477 : normalize(pSub->getY(n)),
478 81 : pSub->getCurve(n) );
479 : }
480 : }
481 15 : }
482 :
483 3 : PDFOutDev::PDFOutDev( PDFDoc* pDoc ) :
484 : m_pDoc( pDoc ),
485 : m_aFontMap(),
486 3 : m_pUtf8Map( new UnicodeMap((char*)"UTF-8", gTrue, &mapUTF8) )
487 : {
488 3 : }
489 0 : PDFOutDev::~PDFOutDev()
490 : {
491 0 : delete m_pUtf8Map;
492 0 : }
493 :
494 3 : void PDFOutDev::startPage(int /*pageNum*/, GfxState* state)
495 : {
496 : assert(state);
497 : printf("startPage %f %f\n",
498 : normalize(state->getPageWidth()),
499 3 : normalize(state->getPageHeight()));
500 3 : }
501 :
502 3 : void PDFOutDev::endPage()
503 : {
504 3 : printf("endPage\n");
505 3 : }
506 :
507 : #if POPPLER_CHECK_VERSION(0, 19, 0)
508 3 : void PDFOutDev::processLink(AnnotLink *link)
509 : #elif POPPLER_CHECK_VERSION(0, 17, 0)
510 : void PDFOutDev::processLink(AnnotLink *link, Catalog *)
511 : #else
512 : void PDFOutDev::processLink(Link* link, Catalog*)
513 : #endif
514 : {
515 : assert(link);
516 :
517 : double x1,x2,y1,y2;
518 3 : link->getRect( &x1, &y1, &x2, &y2 );
519 :
520 3 : LinkAction* pAction = link->getAction();
521 3 : if( pAction->getKind() == actionURI )
522 : {
523 3 : const char* pURI = static_cast<LinkURI*>(pAction)->getURI()->getCString();
524 :
525 3 : boost::shared_array<char> pEsc( lcl_escapeLineFeeds(pURI) );
526 :
527 : printf( "drawLink %f %f %f %f %s\n",
528 : normalize(x1),
529 : normalize(y1),
530 : normalize(x2),
531 : normalize(y2),
532 3 : pEsc.get() );
533 : }
534 3 : }
535 :
536 48 : void PDFOutDev::saveState(GfxState*)
537 : {
538 48 : printf( "saveState\n" );
539 48 : }
540 :
541 48 : void PDFOutDev::restoreState(GfxState*)
542 : {
543 48 : printf( "restoreState\n" );
544 48 : }
545 :
546 3 : void PDFOutDev::setDefaultCTM(double *pMat)
547 : {
548 : assert(pMat);
549 :
550 3 : OutputDev::setDefaultCTM(pMat);
551 :
552 : printf( "updateCtm %f %f %f %f %f %f\n",
553 : normalize(pMat[0]),
554 3 : normalize(pMat[2]),
555 3 : normalize(pMat[1]),
556 3 : normalize(pMat[3]),
557 3 : normalize(pMat[4]),
558 15 : normalize(pMat[5]) );
559 3 : }
560 :
561 3 : void PDFOutDev::updateCTM(GfxState* state,
562 : double, double,
563 : double, double,
564 : double, double)
565 : {
566 : assert(state);
567 :
568 3 : const double* const pMat = state->getCTM();
569 : assert(pMat);
570 :
571 : printf( "updateCtm %f %f %f %f %f %f\n",
572 : normalize(pMat[0]),
573 3 : normalize(pMat[2]),
574 3 : normalize(pMat[1]),
575 3 : normalize(pMat[3]),
576 3 : normalize(pMat[4]),
577 15 : normalize(pMat[5]) );
578 3 : }
579 :
580 6 : void PDFOutDev::updateLineDash(GfxState *state)
581 : {
582 : assert(state);
583 :
584 : double* dashArray; int arrayLen; double startOffset;
585 6 : state->getLineDash(&dashArray, &arrayLen, &startOffset);
586 :
587 6 : printf( "updateLineDash" );
588 6 : if( arrayLen && dashArray )
589 : {
590 3 : printf( " %f %d", normalize(startOffset), arrayLen );
591 15 : for( int i=0; i<arrayLen; ++i )
592 12 : printf( " %f", normalize(*dashArray++) );
593 : }
594 6 : printf( "\n" );
595 6 : }
596 :
597 3 : void PDFOutDev::updateFlatness(GfxState *state)
598 : {
599 : assert(state);
600 3 : printf( "updateFlatness %d\n", state->getFlatness() );
601 3 : }
602 :
603 9 : void PDFOutDev::updateLineJoin(GfxState *state)
604 : {
605 : assert(state);
606 9 : printf( "updateLineJoin %d\n", state->getLineJoin() );
607 9 : }
608 :
609 9 : void PDFOutDev::updateLineCap(GfxState *state)
610 : {
611 : assert(state);
612 9 : printf( "updateLineCap %d\n", state->getLineCap() );
613 9 : }
614 :
615 3 : void PDFOutDev::updateMiterLimit(GfxState *state)
616 : {
617 : assert(state);
618 3 : printf( "updateMiterLimit %f\n", normalize(state->getMiterLimit()) );
619 3 : }
620 :
621 12 : void PDFOutDev::updateLineWidth(GfxState *state)
622 : {
623 : assert(state);
624 12 : printf( "updateLineWidth %f\n", normalize(state->getLineWidth()) );
625 12 : }
626 :
627 42 : void PDFOutDev::updateFillColor(GfxState *state)
628 : {
629 : assert(state);
630 :
631 : GfxRGB aRGB;
632 42 : state->getFillRGB( &aRGB );
633 :
634 : printf( "updateFillColor %f %f %f %f\n",
635 : normalize(colToDbl(aRGB.r)),
636 : normalize(colToDbl(aRGB.g)),
637 : normalize(colToDbl(aRGB.b)),
638 42 : normalize(state->getFillOpacity()) );
639 42 : }
640 :
641 12 : void PDFOutDev::updateStrokeColor(GfxState *state)
642 : {
643 : assert(state);
644 :
645 : GfxRGB aRGB;
646 12 : state->getStrokeRGB( &aRGB );
647 :
648 : printf( "updateStrokeColor %f %f %f %f\n",
649 : normalize(colToDbl(aRGB.r)),
650 : normalize(colToDbl(aRGB.g)),
651 : normalize(colToDbl(aRGB.b)),
652 12 : normalize(state->getFillOpacity()) );
653 12 : }
654 :
655 3 : void PDFOutDev::updateFillOpacity(GfxState *state)
656 : {
657 3 : updateFillColor(state);
658 3 : }
659 :
660 3 : void PDFOutDev::updateStrokeOpacity(GfxState *state)
661 : {
662 3 : updateStrokeColor(state);
663 3 : }
664 :
665 3 : void PDFOutDev::updateBlendMode(GfxState*)
666 : {
667 3 : }
668 :
669 36 : void PDFOutDev::updateFont(GfxState *state)
670 : {
671 : assert(state);
672 :
673 36 : GfxFont *gfxFont = state->getFont();
674 36 : if( gfxFont )
675 : {
676 33 : FontAttributes aFont;
677 33 : int nEmbedSize=0;
678 :
679 33 : Ref* pID = gfxFont->getID();
680 : // TODO(Q3): Portability problem
681 33 : long long fontID = (long long)pID->gen << 32 | (long long)pID->num;
682 : boost::unordered_map< long long, FontAttributes >::const_iterator it =
683 33 : m_aFontMap.find( fontID );
684 33 : if( it == m_aFontMap.end() )
685 : {
686 9 : nEmbedSize = parseFont( fontID, gfxFont, state );
687 9 : it = m_aFontMap.find( fontID );
688 : }
689 :
690 33 : printf( "updateFont" );
691 33 : if( it != m_aFontMap.end() )
692 : {
693 : // conflating this with printf below crashes under Windoze
694 33 : printf( " %lld", fontID );
695 :
696 33 : aFont = it->second;
697 :
698 33 : boost::shared_array<char> pEsc( lcl_escapeLineFeeds(aFont.familyName.getCString()) );
699 : printf( " %d %d %d %d %f %d %s",
700 : aFont.isEmbedded,
701 : aFont.isBold,
702 : aFont.isItalic,
703 : aFont.isUnderline,
704 : normalize(state->getTransformedFontSize()),
705 : nEmbedSize,
706 33 : pEsc.get() );
707 : }
708 33 : printf( "\n" );
709 :
710 33 : if( nEmbedSize )
711 9 : writeFontFile(gfxFont);
712 : }
713 36 : }
714 :
715 0 : void PDFOutDev::updateRender(GfxState *state)
716 : {
717 : assert(state);
718 :
719 0 : printf( "setTextRenderMode %d\n", state->getRender() );
720 0 : }
721 :
722 6 : void PDFOutDev::stroke(GfxState *state)
723 : {
724 : assert(state);
725 :
726 6 : printf( "strokePath" );
727 6 : printPath( state->getPath() );
728 6 : printf( "\n" );
729 6 : }
730 :
731 0 : void PDFOutDev::fill(GfxState *state)
732 : {
733 : assert(state);
734 :
735 0 : printf( "fillPath" );
736 0 : printPath( state->getPath() );
737 0 : printf( "\n" );
738 0 : }
739 :
740 3 : void PDFOutDev::eoFill(GfxState *state)
741 : {
742 : assert(state);
743 :
744 3 : printf( "eoFillPath" );
745 3 : printPath( state->getPath() );
746 3 : printf( "\n" );
747 3 : }
748 :
749 3 : void PDFOutDev::clip(GfxState *state)
750 : {
751 : assert(state);
752 :
753 3 : printf( "clipPath" );
754 3 : printPath( state->getPath() );
755 3 : printf( "\n" );
756 3 : }
757 :
758 3 : void PDFOutDev::eoClip(GfxState *state)
759 : {
760 : assert(state);
761 :
762 3 : printf( "eoClipPath" );
763 3 : printPath( state->getPath() );
764 3 : printf( "\n" );
765 3 : }
766 :
767 : /** Output one glyph
768 :
769 :
770 : @param dx
771 : horizontal skip for character (already scaled with font size) +
772 : inter-char space: cursor is shifted by this amount for next char
773 :
774 : @param dy
775 : vertical skip for character (zero for horizontal writing mode):
776 : cursor is shifted by this amount for next char
777 :
778 : @param originX
779 : local offset of character (zero for horizontal writing mode). not
780 : taken into account for output pos updates. Used for vertical writing.
781 :
782 : @param originY
783 : local offset of character (zero for horizontal writing mode). not
784 : taken into account for output pos updates. Used for vertical writing.
785 : */
786 312 : void PDFOutDev::drawChar(GfxState *state, double x, double y,
787 : double dx, double dy,
788 : double originX, double originY,
789 : CharCode, int /*nBytes*/, Unicode *u, int uLen)
790 : {
791 : assert(state);
792 :
793 312 : if( u == NULL )
794 312 : return;
795 :
796 : // normalize coordinates: correct from baseline-relative to upper
797 : // left corner of glyphs
798 312 : double x2(0.0), y2(0.0);
799 : state->textTransformDelta( 0.0,
800 : state->getFont()->getAscent(),
801 312 : &x2, &y2 );
802 312 : const double fFontSize(state->getFontSize());
803 312 : x += x2*fFontSize;
804 312 : y += y2*fFontSize;
805 :
806 312 : const double aPositionX(x-originX);
807 312 : const double aPositionY(y-originY);
808 : // TODO(F2): use leading here, when set
809 312 : const double nWidth(dx != 0.0 ? dx : fFontSize);
810 312 : const double nHeight(dy != 0.0 ? dy : fFontSize);
811 :
812 312 : const double* pTextMat=state->getTextMat();
813 : printf( "drawChar %f %f %f %f %f %f %f %f ",
814 : normalize(aPositionX),
815 : normalize(aPositionY),
816 : normalize(aPositionX+nWidth),
817 : normalize(aPositionY-nHeight),
818 : normalize(pTextMat[0]),
819 312 : normalize(pTextMat[2]),
820 312 : normalize(pTextMat[1]),
821 936 : normalize(pTextMat[3]) );
822 :
823 : // silence spurious warning
824 : (void)&mapUCS2;
825 :
826 : char buf[9];
827 624 : for( int i=0; i<uLen; ++i )
828 : {
829 312 : buf[ m_pUtf8Map->mapUnicode(u[i], buf, sizeof(buf)-1) ] = 0;
830 312 : boost::shared_array<char> pEsc( lcl_escapeLineFeeds(buf) );
831 312 : printf( "%s", pEsc.get() );
832 312 : }
833 :
834 312 : printf( "\n" );
835 : }
836 :
837 0 : void PDFOutDev::drawString(GfxState*, GooString* /*s*/)
838 : {
839 : // TODO(F3): NYI
840 0 : }
841 :
842 33 : void PDFOutDev::endTextObject(GfxState*)
843 : {
844 33 : printf( "endTextObject\n" );
845 33 : }
846 :
847 0 : void PDFOutDev::drawImageMask(GfxState* pState, Object*, Stream* str,
848 : int width, int height, GBool invert,
849 : #if POPPLER_CHECK_VERSION(0, 12, 0)
850 : GBool /*interpolate*/,
851 : #endif
852 : GBool /*inlineImg*/ )
853 : {
854 0 : OutputBuffer aBuf; initBuf(aBuf);
855 :
856 0 : printf( "drawMask %d %d %d", width, height, invert );
857 :
858 0 : int bitsPerComponent = 1;
859 0 : StreamColorSpaceMode csMode = streamCSNone;
860 0 : str->getImageParams( &bitsPerComponent, &csMode );
861 0 : if( bitsPerComponent == 1 && (csMode == streamCSNone || csMode == streamCSDeviceGray) )
862 : {
863 0 : GfxRGB oneColor = { dblToCol( 1.0 ), dblToCol( 1.0 ), dblToCol( 1.0 ) };
864 0 : GfxRGB zeroColor = { dblToCol( 0.0 ), dblToCol( 0.0 ), dblToCol( 0.0 ) };
865 0 : pState->getFillColorSpace()->getRGB( pState->getFillColor(), &zeroColor );
866 0 : if( invert )
867 0 : writePng_( aBuf, str, width, height, oneColor, zeroColor, true, true );
868 : else
869 0 : writePng_( aBuf, str, width, height, zeroColor, oneColor, true, true );
870 : }
871 : else
872 0 : writeMaskLF(aBuf, str, width, height, invert != 0);
873 0 : writeBinaryBuffer(aBuf);
874 0 : }
875 :
876 3 : void PDFOutDev::drawImage(GfxState*, Object*, Stream* str,
877 : int width, int height, GfxImageColorMap* colorMap,
878 : #if POPPLER_CHECK_VERSION(0, 12, 0)
879 : GBool /*interpolate*/,
880 : #endif
881 : int* maskColors, GBool /*inlineImg*/ )
882 : {
883 3 : OutputBuffer aBuf; initBuf(aBuf);
884 6 : OutputBuffer aMaskBuf;
885 :
886 3 : printf( "drawImage %d %d", width, height );
887 :
888 3 : if( maskColors )
889 : {
890 : // write mask colors. nBytes must be even - first half is
891 : // lower bound values, second half upper bound values
892 0 : if( colorMap->getColorSpace()->getMode() == csIndexed )
893 : {
894 0 : aMaskBuf.push_back( (char)maskColors[0] );
895 0 : aMaskBuf.push_back( (char)maskColors[gfxColorMaxComps] );
896 : }
897 : else
898 : {
899 : GfxRGB aMinRGB;
900 0 : colorMap->getColorSpace()->getRGB(
901 : (GfxColor*)maskColors,
902 0 : &aMinRGB );
903 :
904 : GfxRGB aMaxRGB;
905 0 : colorMap->getColorSpace()->getRGB(
906 : (GfxColor*)maskColors+gfxColorMaxComps,
907 0 : &aMaxRGB );
908 :
909 0 : aMaskBuf.push_back( colToByte(aMinRGB.r) );
910 0 : aMaskBuf.push_back( colToByte(aMinRGB.g) );
911 0 : aMaskBuf.push_back( colToByte(aMinRGB.b) );
912 0 : aMaskBuf.push_back( colToByte(aMaxRGB.r) );
913 0 : aMaskBuf.push_back( colToByte(aMaxRGB.g) );
914 0 : aMaskBuf.push_back( colToByte(aMaxRGB.b) );
915 : }
916 : }
917 :
918 3 : printf( " %d", (int)aMaskBuf.size() );
919 3 : writeImageLF( aBuf, str, width, height, colorMap );
920 3 : writeBinaryBuffer(aBuf);
921 6 : writeBinaryBuffer(aMaskBuf);
922 3 : }
923 :
924 0 : void PDFOutDev::drawMaskedImage(GfxState*, Object*, Stream* str,
925 : int width, int height,
926 : GfxImageColorMap* colorMap,
927 : #if POPPLER_CHECK_VERSION(0, 12, 0)
928 : GBool /*interpolate*/,
929 : #endif
930 : Stream* maskStr,
931 : int maskWidth, int maskHeight,
932 : GBool maskInvert
933 : #if POPPLER_CHECK_VERSION(0, 12, 0)
934 : , GBool /*maskInterpolate*/
935 : #endif
936 : )
937 : {
938 0 : OutputBuffer aBuf; initBuf(aBuf);
939 0 : printf( "drawImage %d %d 0", width, height );
940 0 : writePng_( aBuf, str, width, height, colorMap, maskStr, maskWidth, maskHeight, maskInvert, true );
941 0 : writeBinaryBuffer( aBuf );
942 0 : }
943 :
944 0 : void PDFOutDev::drawSoftMaskedImage(GfxState*, Object*, Stream* str,
945 : int width, int height,
946 : GfxImageColorMap* colorMap,
947 : #if POPPLER_CHECK_VERSION(0, 12, 0)
948 : GBool /*interpolate*/,
949 : #endif
950 : Stream* maskStr,
951 : int maskWidth, int maskHeight,
952 : GfxImageColorMap* maskColorMap
953 : #if POPPLER_CHECK_VERSION(0, 12, 0)
954 : , GBool /*maskInterpolate*/
955 : #endif
956 : )
957 : {
958 0 : OutputBuffer aBuf; initBuf(aBuf);
959 0 : printf( "drawImage %d %d 0", width, height );
960 0 : writePng_( aBuf, str, width, height, colorMap, maskStr, maskWidth, maskHeight, maskColorMap, true );
961 0 : writeBinaryBuffer( aBuf );
962 0 : }
963 :
964 3 : void PDFOutDev::setPageNum( int nNumPages )
965 : {
966 : // TODO(F3): printf might format int locale-dependent!
967 3 : printf("setPageNum %d\n", nNumPages);
968 3 : }
969 :
970 : }
971 :
972 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|