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