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