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