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