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