fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sdext / source / pdfimport / xpdfwrapper / pdfioutdev_gpl.cxx
blobb7c47d88fe59280742981d0786214b08bf357cc1
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "pdfioutdev_gpl.hxx"
21 #include "pnghelper.hxx"
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <assert.h>
26 #include <math.h>
28 #include <boost/shared_array.hpp>
30 #if defined _MSC_VER
31 #pragma warning(push, 1)
32 #endif
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
45 #if defined _MSC_VER
46 #pragma warning(pop)
47 #endif
49 #ifdef WNT
50 # define snprintf _snprintf
52 #if defined __GNUC__
53 #pragma GCC diagnostic warning "-Wformat"
54 #pragma GCC diagnostic warning "-Wformat-extra-args"
55 #endif
56 #endif
58 /* SYNC STREAMS
59 ============
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.
71 namespace pdfi
74 /// cut off very small numbers & clamp value to zero
75 inline double normalize( double val )
77 return fabs(val) < 0.0000001 ? 0.0 : val;
80 namespace
83 /** Escapes line-ending characters (\n and \r) in input string.
85 boost::shared_array<char> lcl_escapeLineFeeds(const char* const i_pStr)
87 size_t nLength(strlen(i_pStr));
88 char* pBuffer = new char[2*nLength+1];
90 const char* pRead = i_pStr;
91 char* pWrite = pBuffer;
92 while( nLength-- )
94 if( *pRead == '\r' )
96 *pWrite++ = '\\';
97 *pWrite++ = 'r';
99 else if( *pRead == '\n' )
101 *pWrite++ = '\\';
102 *pWrite++ = 'n';
104 else if( *pRead == '\\' )
106 *pWrite++ = '\\';
107 *pWrite++ = '\\';
109 else
110 *pWrite++ = *pRead;
111 pRead++;
113 *pWrite++ = 0;
115 return boost::shared_array<char>(pBuffer);
120 /// for the temp char buffer the header gets snprintfed in
121 #define WRITE_BUFFER_SIZE 1024
123 /// for the initial std::vector capacity when copying stream from xpdf
124 #define WRITE_BUFFER_INITIAL_CAPACITY (1024*100)
126 void initBuf(OutputBuffer& io_rBuffer)
128 io_rBuffer.reserve(WRITE_BUFFER_INITIAL_CAPACITY);
131 void writeBinaryBuffer( const OutputBuffer& rBuffer )
133 // ---sync point--- see SYNC STREAMS above
134 fflush(stdout);
136 // put buffer to stderr
137 if( !rBuffer.empty() )
138 if( fwrite(&rBuffer[0], sizeof(char),
139 rBuffer.size(), g_binary_out) != (size_t)rBuffer.size() )
140 exit(1); // error
142 // ---sync point--- see SYNC STREAMS above
143 fflush(g_binary_out);
146 bool ExtractJpegData(Stream* str, OutputBuffer& outBuf)
148 int bytesToMarker = 0;
149 int bytesToLen = -1;
150 bool collectBytes = false;
151 int startOfScan = 0;
152 int b1 = -1;
153 for (; ; )
155 const int b2 = b1;
156 b1 = str->getChar();
158 if (b1 == -1)
159 return false;
161 if (collectBytes)
163 outBuf.push_back((Output_t)b1);
165 bytesToMarker--;
166 bytesToLen--;
169 if (bytesToMarker == 0)
171 if (startOfScan == 1)
173 bytesToMarker = -1;
174 startOfScan = 2;
176 else if (b2 == 0xFF)
178 if (b1 == 0xD8)
180 collectBytes = true;
181 bytesToMarker = 2;
183 outBuf.push_back((Output_t)0xFF);
184 outBuf.push_back((Output_t)0xD8);
186 else
188 bytesToLen = 2;
190 if (b1 == 0xDA)
192 startOfScan = 1;
195 else if (collectBytes)
197 return false;
201 if (bytesToLen == 0)
203 bytesToMarker = b2 * 256 + b1;
206 if (startOfScan == 2)
207 if ((b2 == 0xFF) && (b1 == 0xD9))
208 return true;
212 void writeJpeg_( OutputBuffer& o_rOutputBuf, Stream* str, bool bWithLinefeed )
214 // dump JPEG file as-is
215 #if POPPLER_CHECK_VERSION(0, 17, 3)
216 str = str->getNextStream();
217 #else
218 str = ((DCTStream *)str)->getRawStream();
219 #endif
220 str->reset();
222 o_rOutputBuf.clear();
223 ExtractJpegData(str, o_rOutputBuf);
225 printf( " JPEG %d", (int)o_rOutputBuf.size() );
226 if( bWithLinefeed )
227 printf("\n");
229 str->close();
232 void writePbm_(OutputBuffer& o_rOutputBuf, Stream* str, int width, int height, bool bWithLinefeed, bool bInvert )
234 // write as PBM (char by char, to avoid stdlib lineend messing)
235 o_rOutputBuf.clear();
236 o_rOutputBuf.resize(WRITE_BUFFER_SIZE);
237 o_rOutputBuf[0] = 'P';
238 o_rOutputBuf[1] = '4';
239 o_rOutputBuf[2] = 0x0A;
240 char *pAsCharPtr = reinterpret_cast<char *>(&o_rOutputBuf[3]);
241 int nOutLen = snprintf(pAsCharPtr, WRITE_BUFFER_SIZE-10, "%d %d", width, height);
242 if( nOutLen < 0 )
243 nOutLen = WRITE_BUFFER_SIZE-10;
244 o_rOutputBuf[3+nOutLen] =0x0A;
245 o_rOutputBuf[3+nOutLen+1]=0;
247 const int header_size = 3+nOutLen+1;
248 const int size = height * ((width + 7) / 8);
250 printf( " PBM %d", size + header_size );
251 if( bWithLinefeed )
252 printf("\n");
254 // trim buffer to exact header length
255 o_rOutputBuf.resize(header_size);
257 // initialize stream
258 str->reset();
260 // copy the raw stream
261 if( bInvert )
263 for( int i=0; i<size; ++i)
264 o_rOutputBuf.push_back(static_cast<char>(str->getChar() ^ 0xff));
266 else
268 for( int i=0; i<size; ++i)
269 o_rOutputBuf.push_back(static_cast<char>(str->getChar()));
272 str->close();
275 void writePpm_( OutputBuffer& o_rOutputBuf,
276 Stream* str,
277 int width,
278 int height,
279 GfxImageColorMap* colorMap,
280 bool bWithLinefeed )
282 // write as PPM (char by char, to avoid stdlib lineend messing)
283 o_rOutputBuf.clear();
284 o_rOutputBuf.resize(WRITE_BUFFER_SIZE);
285 o_rOutputBuf[0] = 'P';
286 o_rOutputBuf[1] = '6';
287 o_rOutputBuf[2] = '\n';
288 char *pAsCharPtr = reinterpret_cast<char *>(&o_rOutputBuf[3]);
289 int nOutLen = snprintf(pAsCharPtr, WRITE_BUFFER_SIZE-10, "%d %d", width, height);
290 if( nOutLen < 0 )
291 nOutLen = WRITE_BUFFER_SIZE-10;
292 o_rOutputBuf[3+nOutLen] ='\n';
293 o_rOutputBuf[3+nOutLen+1]='2';
294 o_rOutputBuf[3+nOutLen+2]='5';
295 o_rOutputBuf[3+nOutLen+3]='5';
296 o_rOutputBuf[3+nOutLen+4]='\n';
297 o_rOutputBuf[3+nOutLen+5]=0;
299 const int header_size = 3+nOutLen+5;
300 const int size = width*height*3 + header_size;
302 printf( " PPM %d", size );
303 if( bWithLinefeed )
304 printf("\n");
306 // trim buffer to exact header size
307 o_rOutputBuf.resize(header_size);
309 // initialize stream
310 Guchar *p;
311 GfxRGB rgb;
312 ImageStream* imgStr =
313 new ImageStream(str,
314 width,
315 colorMap->getNumPixelComps(),
316 colorMap->getBits());
317 imgStr->reset();
319 for( int y=0; y<height; ++y)
321 p = imgStr->getLine();
322 for( int x=0; x<width; ++x)
324 colorMap->getRGB(p, &rgb);
325 o_rOutputBuf.push_back(colToByte(rgb.r));
326 o_rOutputBuf.push_back(colToByte(rgb.g));
327 o_rOutputBuf.push_back(colToByte(rgb.b));
329 p +=colorMap->getNumPixelComps();
333 delete imgStr;
337 // call this only for 1 bit image streams !
338 void writePng_( OutputBuffer& o_rOutputBuf,
339 Stream* str,
340 int width,
341 int height,
342 GfxRGB& zeroColor,
343 GfxRGB& oneColor,
344 bool bIsMask,
345 bool bWithLinefeed )
347 o_rOutputBuf.clear();
349 // get png image
350 PngHelper::createPng( o_rOutputBuf, str, width, height, zeroColor, oneColor, bIsMask );
352 printf( " PNG %d", (int)o_rOutputBuf.size() );
353 if( bWithLinefeed )
354 printf("\n");
357 void writePng_( OutputBuffer& o_rOutputBuf,
358 Stream* str,
359 int width, int height, GfxImageColorMap* colorMap,
360 Stream* maskStr,
361 int maskWidth, int maskHeight, GfxImageColorMap* maskColorMap,
362 bool bWithLinefeed )
364 o_rOutputBuf.clear();
366 // get png image
367 PngHelper::createPng( o_rOutputBuf, str, width, height, colorMap, maskStr, maskWidth, maskHeight, maskColorMap );
369 printf( " PNG %d", (int)o_rOutputBuf.size() );
370 if( bWithLinefeed )
371 printf("\n");
374 void writePng_( OutputBuffer& o_rOutputBuf,
375 Stream* str,
376 int width, int height, GfxImageColorMap* colorMap,
377 Stream* maskStr,
378 int maskWidth, int maskHeight, bool maskInvert,
379 bool bWithLinefeed )
381 o_rOutputBuf.clear();
383 // get png image
384 PngHelper::createPng( o_rOutputBuf, str, width, height, colorMap, maskStr, maskWidth, maskHeight, maskInvert );
386 printf( " PNG %d", (int)o_rOutputBuf.size() );
387 if( bWithLinefeed )
388 printf("\n");
391 // stolen from ImageOutputDev.cc
392 void writeMask_( OutputBuffer& o_rOutputBuf, Stream* str, int width, int height, bool bWithLinefeed, bool bInvert )
394 if( str->getKind() == strDCT )
395 writeJpeg_(o_rOutputBuf, str, bWithLinefeed);
396 else
397 writePbm_(o_rOutputBuf, str, width, height, bWithLinefeed, bInvert );
400 void writeImage_( OutputBuffer& o_rOutputBuf,
401 Stream* str,
402 int width,
403 int height,
404 GfxImageColorMap* colorMap,
405 bool bWithLinefeed )
407 // dump JPEG file
408 if( str->getKind() == strDCT &&
409 (colorMap->getNumPixelComps() == 1 ||
410 colorMap->getNumPixelComps() == 3) )
412 writeJpeg_(o_rOutputBuf, str, bWithLinefeed);
414 else if (colorMap->getNumPixelComps() == 1 &&
415 colorMap->getBits() == 1)
417 // this is a two color bitmap, write a png
418 // provide default colors
419 GfxRGB zeroColor = { 0, 0, 0 },
420 oneColor = { byteToCol( 0xff ), byteToCol( 0xff ), byteToCol( 0xff ) };
421 if( colorMap->getColorSpace()->getMode() == csIndexed || colorMap->getColorSpace()->getMode() == csDeviceGray )
423 Guchar nIndex = 0;
424 colorMap->getRGB( &nIndex, &zeroColor );
425 nIndex = 1;
426 colorMap->getRGB( &nIndex, &oneColor );
428 writePng_( o_rOutputBuf, str, width, height, zeroColor, oneColor, false, bWithLinefeed );
430 else
431 writePpm_( o_rOutputBuf, str, width, height, colorMap, bWithLinefeed );
434 // forwarders
437 inline void writeImageLF( OutputBuffer& o_rOutputBuf,
438 Stream* str,
439 int width,
440 int height,
441 GfxImageColorMap* colorMap ) { writeImage_(o_rOutputBuf,str,width,height,colorMap,true); }
442 inline void writeMaskLF( OutputBuffer& o_rOutputBuf,
443 Stream* str,
444 int width,
445 int height,
446 bool bInvert ) { writeMask_(o_rOutputBuf,str,width,height,true,bInvert); }
451 int PDFOutDev::parseFont( long long nNewId, GfxFont* gfxFont, GfxState* state ) const
453 FontAttributes aNewFont;
454 int nSize = 0;
456 GooString* pFamily = gfxFont->getName();
457 if( pFamily )
459 aNewFont.familyName.clear();
460 aNewFont.familyName.append( gfxFont->getName() );
462 else
464 aNewFont.familyName.clear();
465 aNewFont.familyName.append( "Arial" );
468 aNewFont.isBold = gfxFont->isBold();
469 aNewFont.isItalic = gfxFont->isItalic();
470 aNewFont.size = state->getTransformedFontSize();
471 aNewFont.isUnderline = false;
473 if( gfxFont->getType() == fontTrueType || gfxFont->getType() == fontType1 )
475 // TODO(P3): Unfortunately, need to read stream twice, since
476 // we must write byte count to stdout before
477 char* pBuf = gfxFont->readEmbFontFile( m_pDoc->getXRef(), &nSize );
478 if( pBuf )
480 aNewFont.isEmbedded = true;
481 gfree(pBuf);
485 m_aFontMap[ nNewId ] = aNewFont;
486 return nSize;
489 void PDFOutDev::writeFontFile( GfxFont* gfxFont ) const
491 if( gfxFont->getType() != fontTrueType && gfxFont->getType() != fontType1 )
492 return;
494 int nSize = 0;
495 char* pBuf = gfxFont->readEmbFontFile( m_pDoc->getXRef(), &nSize );
496 if( !pBuf )
497 return;
499 // ---sync point--- see SYNC STREAMS above
500 fflush(stdout);
502 if( fwrite(pBuf, sizeof(char), nSize, g_binary_out) != (size_t)nSize )
504 gfree(pBuf);
505 exit(1); // error
507 // ---sync point--- see SYNC STREAMS above
508 fflush(g_binary_out);
509 gfree(pBuf);
512 void PDFOutDev::printPath( GfxPath* pPath )
514 int nSubPaths = pPath ? pPath->getNumSubpaths() : 0;
515 for( int i=0; i<nSubPaths; i++ )
517 GfxSubpath* pSub = pPath->getSubpath( i );
518 const int nPoints = pSub->getNumPoints();
520 printf( " subpath %d", pSub->isClosed() );
522 for( int n=0; n<nPoints; ++n )
524 printf( " %f %f %d",
525 normalize(pSub->getX(n)),
526 normalize(pSub->getY(n)),
527 pSub->getCurve(n) );
532 PDFOutDev::PDFOutDev( PDFDoc* pDoc ) :
533 m_pDoc( pDoc ),
534 m_aFontMap(),
535 m_pUtf8Map( new UnicodeMap("UTF-8", gTrue, &mapUTF8) ),
536 m_bSkipImages(false)
539 PDFOutDev::~PDFOutDev()
541 delete m_pUtf8Map;
544 void PDFOutDev::startPage(int /*pageNum*/, GfxState* state
545 #if POPPLER_CHECK_VERSION(0, 23, 0) || POPPLER_CHECK_VERSION(0, 24, 0)
546 , XRef* /*xref*/
547 #endif
550 assert(state);
551 printf("startPage %f %f\n",
552 normalize(state->getPageWidth()),
553 normalize(state->getPageHeight()));
556 void PDFOutDev::endPage()
558 printf("endPage\n");
561 #if POPPLER_CHECK_VERSION(0, 19, 0)
562 void PDFOutDev::processLink(AnnotLink *link)
563 #elif POPPLER_CHECK_VERSION(0, 17, 0)
564 void PDFOutDev::processLink(AnnotLink *link, Catalog *)
565 #else
566 void PDFOutDev::processLink(Link* link, Catalog*)
567 #endif
569 assert(link);
571 double x1,x2,y1,y2;
572 link->getRect( &x1, &y1, &x2, &y2 );
574 LinkAction* pAction = link->getAction();
575 if (pAction && pAction->getKind() == actionURI)
577 const char* pURI = static_cast<LinkURI*>(pAction)->getURI()->getCString();
579 boost::shared_array<char> pEsc( lcl_escapeLineFeeds(pURI) );
581 printf( "drawLink %f %f %f %f %s\n",
582 normalize(x1),
583 normalize(y1),
584 normalize(x2),
585 normalize(y2),
586 pEsc.get() );
590 void PDFOutDev::saveState(GfxState*)
592 printf( "saveState\n" );
595 void PDFOutDev::restoreState(GfxState*)
597 printf( "restoreState\n" );
600 void PDFOutDev::setDefaultCTM(double *pMat)
602 assert(pMat);
604 OutputDev::setDefaultCTM(pMat);
606 printf( "updateCtm %f %f %f %f %f %f\n",
607 normalize(pMat[0]),
608 normalize(pMat[1]),
609 normalize(pMat[2]),
610 normalize(pMat[3]),
611 normalize(pMat[4]),
612 normalize(pMat[5]) );
615 void PDFOutDev::updateCTM(GfxState* state,
616 double, double,
617 double, double,
618 double, double)
620 assert(state);
622 const double* const pMat = state->getCTM();
623 assert(pMat);
625 printf( "updateCtm %f %f %f %f %f %f\n",
626 normalize(pMat[0]),
627 normalize(pMat[1]),
628 normalize(pMat[2]),
629 normalize(pMat[3]),
630 normalize(pMat[4]),
631 normalize(pMat[5]) );
634 void PDFOutDev::updateLineDash(GfxState *state)
636 if (m_bSkipImages)
637 return;
638 assert(state);
640 double* dashArray; int arrayLen; double startOffset;
641 state->getLineDash(&dashArray, &arrayLen, &startOffset);
643 printf( "updateLineDash" );
644 if( arrayLen && dashArray )
646 printf( " %f %d", normalize(startOffset), arrayLen );
647 for( int i=0; i<arrayLen; ++i )
648 printf( " %f", normalize(*dashArray++) );
650 printf( "\n" );
653 void PDFOutDev::updateFlatness(GfxState *state)
655 if (m_bSkipImages)
656 return;
657 assert(state);
658 printf( "updateFlatness %d\n", state->getFlatness() );
661 void PDFOutDev::updateLineJoin(GfxState *state)
663 if (m_bSkipImages)
664 return;
665 assert(state);
666 printf( "updateLineJoin %d\n", state->getLineJoin() );
669 void PDFOutDev::updateLineCap(GfxState *state)
671 if (m_bSkipImages)
672 return;
673 assert(state);
674 printf( "updateLineCap %d\n", state->getLineCap() );
677 void PDFOutDev::updateMiterLimit(GfxState *state)
679 if (m_bSkipImages)
680 return;
681 assert(state);
682 printf( "updateMiterLimit %f\n", normalize(state->getMiterLimit()) );
685 void PDFOutDev::updateLineWidth(GfxState *state)
687 if (m_bSkipImages)
688 return;
689 assert(state);
690 printf( "updateLineWidth %f\n", normalize(state->getLineWidth()) );
693 void PDFOutDev::updateFillColor(GfxState *state)
695 if (m_bSkipImages)
696 return;
697 assert(state);
699 GfxRGB aRGB;
700 state->getFillRGB( &aRGB );
702 printf( "updateFillColor %f %f %f %f\n",
703 normalize(colToDbl(aRGB.r)),
704 normalize(colToDbl(aRGB.g)),
705 normalize(colToDbl(aRGB.b)),
706 normalize(state->getFillOpacity()) );
709 void PDFOutDev::updateStrokeColor(GfxState *state)
711 if (m_bSkipImages)
712 return;
713 assert(state);
715 GfxRGB aRGB;
716 state->getStrokeRGB( &aRGB );
718 printf( "updateStrokeColor %f %f %f %f\n",
719 normalize(colToDbl(aRGB.r)),
720 normalize(colToDbl(aRGB.g)),
721 normalize(colToDbl(aRGB.b)),
722 normalize(state->getFillOpacity()) );
725 void PDFOutDev::updateFillOpacity(GfxState *state)
727 if (m_bSkipImages)
728 return;
729 updateFillColor(state);
732 void PDFOutDev::updateStrokeOpacity(GfxState *state)
734 if (m_bSkipImages)
735 return;
736 updateStrokeColor(state);
739 void PDFOutDev::updateBlendMode(GfxState*)
743 void PDFOutDev::updateFont(GfxState *state)
745 assert(state);
747 GfxFont *gfxFont = state->getFont();
748 if( gfxFont )
750 FontAttributes aFont;
751 int nEmbedSize=0;
753 Ref* pID = gfxFont->getID();
754 // TODO(Q3): Portability problem
755 long long fontID = (long long)pID->gen << 32 | (long long)pID->num;
756 std::unordered_map< long long, FontAttributes >::const_iterator it =
757 m_aFontMap.find( fontID );
758 if( it == m_aFontMap.end() )
760 nEmbedSize = parseFont( fontID, gfxFont, state );
761 it = m_aFontMap.find( fontID );
764 printf( "updateFont" );
765 if( it != m_aFontMap.end() )
767 // conflating this with printf below crashes under Windoze
768 printf( " %lld", fontID );
770 aFont = it->second;
772 boost::shared_array<char> pEsc( lcl_escapeLineFeeds(aFont.familyName.getCString()) );
773 printf( " %d %d %d %d %f %d %s",
774 aFont.isEmbedded,
775 aFont.isBold,
776 aFont.isItalic,
777 aFont.isUnderline,
778 normalize(state->getTransformedFontSize()),
779 nEmbedSize,
780 pEsc.get() );
782 printf( "\n" );
784 if( nEmbedSize )
785 writeFontFile(gfxFont);
789 void PDFOutDev::updateRender(GfxState *state)
791 assert(state);
793 printf( "setTextRenderMode %d\n", state->getRender() );
796 void PDFOutDev::stroke(GfxState *state)
798 if (m_bSkipImages)
799 return;
800 assert(state);
802 printf( "strokePath" );
803 printPath( state->getPath() );
804 printf( "\n" );
807 void PDFOutDev::fill(GfxState *state)
809 if (m_bSkipImages)
810 return;
811 assert(state);
813 printf( "fillPath" );
814 printPath( state->getPath() );
815 printf( "\n" );
818 void PDFOutDev::eoFill(GfxState *state)
820 if (m_bSkipImages)
821 return;
822 assert(state);
824 printf( "eoFillPath" );
825 printPath( state->getPath() );
826 printf( "\n" );
829 void PDFOutDev::clip(GfxState *state)
831 if (m_bSkipImages)
832 return;
833 assert(state);
835 printf( "clipPath" );
836 printPath( state->getPath() );
837 printf( "\n" );
840 void PDFOutDev::eoClip(GfxState *state)
842 if (m_bSkipImages)
843 return;
844 assert(state);
846 printf( "eoClipPath" );
847 printPath( state->getPath() );
848 printf( "\n" );
851 /** Output one glyph
854 @param dx
855 horizontal skip for character (already scaled with font size) +
856 inter-char space: cursor is shifted by this amount for next char
858 @param dy
859 vertical skip for character (zero for horizontal writing mode):
860 cursor is shifted by this amount for next char
862 @param originX
863 local offset of character (zero for horizontal writing mode). not
864 taken into account for output pos updates. Used for vertical writing.
866 @param originY
867 local offset of character (zero for horizontal writing mode). not
868 taken into account for output pos updates. Used for vertical writing.
870 void PDFOutDev::drawChar(GfxState *state, double x, double y,
871 double dx, double dy,
872 double originX, double originY,
873 CharCode, int /*nBytes*/, Unicode *u, int uLen)
875 assert(state);
877 if( u == NULL )
878 return;
880 double csdx = 0.0;
881 double csdy = 0.0;
882 if (state->getFont()->getWMode())
884 csdy = state->getCharSpace();
885 if (*u == ' ')
886 csdy += state->getWordSpace();
888 else
890 csdx = state->getCharSpace();
891 if (*u == ' ')
892 csdx += state->getWordSpace();
893 csdx *= state->getHorizScaling();
896 double cstdx = 0.0;
897 double cstdy = 0.0;
898 state->textTransformDelta(csdx, csdy, &cstdx, &cstdy);
900 const double fontSize = state->getFontSize();
902 const double aPositionX(x-originX);
903 const double aPositionY(y-originY);
905 const double* pTextMat=state->getTextMat();
906 printf( "drawChar %f %f %f %f %f %f %f %f %f ",
907 normalize(aPositionX),
908 normalize(aPositionY),
909 normalize(aPositionX + dx - cstdx),
910 normalize(aPositionY + dy - cstdy),
911 normalize(pTextMat[0]),
912 normalize(pTextMat[2]),
913 normalize(pTextMat[1]),
914 normalize(pTextMat[3]),
915 normalize(fontSize)
918 // silence spurious warning
919 (void)&mapUCS2;
921 char buf[9];
922 for( int i=0; i<uLen; ++i )
924 buf[ m_pUtf8Map->mapUnicode(u[i], buf, sizeof(buf)-1) ] = 0;
925 boost::shared_array<char> pEsc( lcl_escapeLineFeeds(buf) );
926 printf( "%s", pEsc.get() );
929 printf( "\n" );
932 void PDFOutDev::drawString(GfxState*, GooString* /*s*/)
934 // TODO(F3): NYI
937 void PDFOutDev::endTextObject(GfxState*)
939 printf( "endTextObject\n" );
942 void PDFOutDev::drawImageMask(GfxState* pState, Object*, Stream* str,
943 int width, int height, GBool invert,
944 #if POPPLER_CHECK_VERSION(0, 12, 0)
945 GBool /*interpolate*/,
946 #endif
947 GBool /*inlineImg*/ )
949 if (m_bSkipImages)
950 return;
951 OutputBuffer aBuf; initBuf(aBuf);
953 printf( "drawMask %d %d %d", width, height, invert );
955 int bitsPerComponent = 1;
956 StreamColorSpaceMode csMode = streamCSNone;
957 str->getImageParams( &bitsPerComponent, &csMode );
958 if( bitsPerComponent == 1 && (csMode == streamCSNone || csMode == streamCSDeviceGray) )
960 GfxRGB oneColor = { dblToCol( 1.0 ), dblToCol( 1.0 ), dblToCol( 1.0 ) };
961 GfxRGB zeroColor = { dblToCol( 0.0 ), dblToCol( 0.0 ), dblToCol( 0.0 ) };
962 pState->getFillColorSpace()->getRGB( pState->getFillColor(), &zeroColor );
963 if( invert )
964 writePng_( aBuf, str, width, height, oneColor, zeroColor, true, true );
965 else
966 writePng_( aBuf, str, width, height, zeroColor, oneColor, true, true );
968 else
969 writeMaskLF(aBuf, str, width, height, invert);
970 writeBinaryBuffer(aBuf);
973 void PDFOutDev::drawImage(GfxState*, Object*, Stream* str,
974 int width, int height, GfxImageColorMap* colorMap,
975 #if POPPLER_CHECK_VERSION(0, 12, 0)
976 GBool /*interpolate*/,
977 #endif
978 int* maskColors, GBool /*inlineImg*/ )
980 if (m_bSkipImages)
981 return;
982 OutputBuffer aBuf; initBuf(aBuf);
983 OutputBuffer aMaskBuf;
985 printf( "drawImage %d %d", width, height );
987 if( maskColors )
989 // write mask colors. nBytes must be even - first half is
990 // lower bound values, second half upper bound values
991 if( colorMap->getColorSpace()->getMode() == csIndexed )
993 aMaskBuf.push_back( (char)maskColors[0] );
994 aMaskBuf.push_back( (char)maskColors[gfxColorMaxComps] );
996 else
998 GfxRGB aMinRGB;
999 colorMap->getColorSpace()->getRGB(
1000 reinterpret_cast<GfxColor*>(maskColors),
1001 &aMinRGB );
1003 GfxRGB aMaxRGB;
1004 colorMap->getColorSpace()->getRGB(
1005 reinterpret_cast<GfxColor*>(maskColors)+gfxColorMaxComps,
1006 &aMaxRGB );
1008 aMaskBuf.push_back( colToByte(aMinRGB.r) );
1009 aMaskBuf.push_back( colToByte(aMinRGB.g) );
1010 aMaskBuf.push_back( colToByte(aMinRGB.b) );
1011 aMaskBuf.push_back( colToByte(aMaxRGB.r) );
1012 aMaskBuf.push_back( colToByte(aMaxRGB.g) );
1013 aMaskBuf.push_back( colToByte(aMaxRGB.b) );
1017 printf( " %d", (int)aMaskBuf.size() );
1018 writeImageLF( aBuf, str, width, height, colorMap );
1019 writeBinaryBuffer(aBuf);
1020 writeBinaryBuffer(aMaskBuf);
1023 void PDFOutDev::drawMaskedImage(GfxState*, Object*, Stream* str,
1024 int width, int height,
1025 GfxImageColorMap* colorMap,
1026 #if POPPLER_CHECK_VERSION(0, 12, 0)
1027 GBool /*interpolate*/,
1028 #endif
1029 Stream* maskStr,
1030 int maskWidth, int maskHeight,
1031 GBool maskInvert
1032 #if POPPLER_CHECK_VERSION(0, 12, 0)
1033 , GBool /*maskInterpolate*/
1034 #endif
1037 if (m_bSkipImages)
1038 return;
1039 OutputBuffer aBuf; initBuf(aBuf);
1040 printf( "drawImage %d %d 0", width, height );
1041 writePng_( aBuf, str, width, height, colorMap, maskStr, maskWidth, maskHeight, maskInvert, true );
1042 writeBinaryBuffer( aBuf );
1045 void PDFOutDev::drawSoftMaskedImage(GfxState*, Object*, Stream* str,
1046 int width, int height,
1047 GfxImageColorMap* colorMap,
1048 #if POPPLER_CHECK_VERSION(0, 12, 0)
1049 GBool /*interpolate*/,
1050 #endif
1051 Stream* maskStr,
1052 int maskWidth, int maskHeight,
1053 GfxImageColorMap* maskColorMap
1054 #if POPPLER_CHECK_VERSION(0, 12, 0)
1055 , GBool /*maskInterpolate*/
1056 #endif
1059 if (m_bSkipImages)
1060 return;
1061 OutputBuffer aBuf; initBuf(aBuf);
1062 printf( "drawImage %d %d 0", width, height );
1063 writePng_( aBuf, str, width, height, colorMap, maskStr, maskWidth, maskHeight, maskColorMap, true );
1064 writeBinaryBuffer( aBuf );
1067 void PDFOutDev::setPageNum( int nNumPages )
1069 // TODO(F3): printf might format int locale-dependent!
1070 printf("setPageNum %d\n", nNumPages);
1073 void PDFOutDev::setSkipImages( bool bSkipImages )
1075 m_bSkipImages = bSkipImages;
1080 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */