From a4dd7fdd4936db6c982323d7eacf279eda5629d6 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Sun, 22 Oct 2017 09:37:01 +1030 Subject: [PATCH 1/2] cairo: support embedding CCITT image data Bug 103399 --- poppler/CairoOutputDev.cc | 46 +++++++++++++++++++++++++++++++++++++++++++--- poppler/CairoOutputDev.h | 5 ++++- poppler/Stream.cc | 14 ++++++++++---- poppler/Stream.h | 6 +++++- 4 files changed, 62 insertions(+), 9 deletions(-) diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc index 43c604f0..8beef9fa 100644 --- a/poppler/CairoOutputDev.cc +++ b/poppler/CairoOutputDev.cc @@ -2761,7 +2761,7 @@ void CairoOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *s cairo_surface_mark_dirty (image); - setMimeData(state, str, ref, colorMap, image); + setMimeData(state, str, ref, colorMap, image, height); pattern = cairo_pattern_create_for_surface (image); cairo_surface_destroy (image); @@ -2935,8 +2935,38 @@ GBool CairoOutputDev::setMimeDataForJBIG2Globals(Stream *str, } #endif +#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 15, 9) +GBool CairoOutputDev::setMimeDataForCCITTParams(Stream *str, + cairo_surface_t *image, int height) +{ + CCITTFaxStream *ccittStr = static_cast(str); + + GooString params; + params.appendf("Columns={0:d}", ccittStr->getColumns()); + params.appendf(" Rows={0:d}", height); + params.appendf(" K={0:d}", ccittStr->getEncoding()); + params.appendf(" EndOfLine={0:d}", ccittStr->getEndOfLine() ? 1 : 0); + params.appendf(" EncodedByteAlign={0:d}", ccittStr->getEncodedByteAlign() ? 1 : 0); + params.appendf(" EndOfBlock={0:d}", ccittStr->getEndOfBlock() ? 1 : 0); + params.appendf(" BlackIs1={0:d}", ccittStr->getBlackIs1() ? 1 : 0); + params.appendf(" DamagedRowsBeforeError={0:d}", ccittStr->getDamagedRowsBeforeError()); + + char *p = strdup(params.getCString()); + if (cairo_surface_set_mime_data (image, CAIRO_MIME_TYPE_CCITT_FAX_PARAMS, + (const unsigned char*)p, + params.getLength(), + gfree, (void*)p)) + { + gfree (p); + return gFalse; + } + + return gTrue; +} +#endif + void CairoOutputDev::setMimeData(GfxState *state, Stream *str, Object *ref, - GfxImageColorMap *colorMap, cairo_surface_t *image) + GfxImageColorMap *colorMap, cairo_surface_t *image, int height) { char *strBuffer; int len; @@ -2960,6 +2990,11 @@ void CairoOutputDev::setMimeData(GfxState *state, Stream *str, Object *ref, mime_type = CAIRO_MIME_TYPE_JBIG2; break; #endif +#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 15, 9) + case strCCITTFax: + mime_type = CAIRO_MIME_TYPE_CCITT_FAX; + break; +#endif default: return; } @@ -3002,6 +3037,11 @@ void CairoOutputDev::setMimeData(GfxState *state, Stream *str, Object *ref, return; #endif +#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 15, 9) + if (strKind == strCCITTFax && !setMimeDataForCCITTParams(str, image, height)) + return; +#endif + if (getStreamData (str->getNextStream(), &strBuffer, &len)) { cairo_status_t status = CAIRO_STATUS_SUCCESS; @@ -3216,7 +3256,7 @@ void CairoOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, filter = getFilterForSurface (image, interpolate); if (!inlineImg) /* don't read stream twice if it is an inline image */ - setMimeData(state, str, ref, colorMap, image); + setMimeData(state, str, ref, colorMap, image, heightA); pattern = cairo_pattern_create_for_surface (image); cairo_surface_destroy (image); diff --git a/poppler/CairoOutputDev.h b/poppler/CairoOutputDev.h index 1fee8121..cddce1ee 100644 --- a/poppler/CairoOutputDev.h +++ b/poppler/CairoOutputDev.h @@ -283,12 +283,15 @@ protected: GBool interpolate); GBool getStreamData (Stream *str, char **buffer, int *length); void setMimeData(GfxState *state, Stream *str, Object *ref, - GfxImageColorMap *colorMap, cairo_surface_t *image); + GfxImageColorMap *colorMap, cairo_surface_t *image, int height); void fillToStrokePathClip(GfxState *state); void alignStrokeCoords(GfxSubpath *subpath, int i, double *x, double *y); #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 14, 0) GBool setMimeDataForJBIG2Globals (Stream *str, cairo_surface_t *image); #endif +#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 15, 9) + GBool setMimeDataForCCITTParams(Stream *str, cairo_surface_t *image, int height); +#endif static void setContextAntialias(cairo_t *cr, cairo_antialias_t antialias); GfxRGB fill_color, stroke_color; diff --git a/poppler/Stream.cc b/poppler/Stream.cc index b541356d..92fe9eea 100644 --- a/poppler/Stream.cc +++ b/poppler/Stream.cc @@ -213,7 +213,7 @@ Stream *Stream::makeFilter(char *name, Stream *str, Object *params, int recursio int bits; int early; int encoding; - GBool endOfLine, byteAlign, endOfBlock, black; + GBool endOfLine, byteAlign, endOfBlock, black, damagedRowsBeforeError; int columns, rows; Object globals, obj; @@ -255,7 +255,8 @@ Stream *Stream::makeFilter(char *name, Stream *str, Object *params, int recursio rows = 0; endOfBlock = gTrue; black = gFalse; - if (params->isDict()) { + damagedRowsBeforeError = 0; + if (params->isDict()) { obj = params->dictLookup("K", recursion); if (obj.isInt()) { encoding = obj.getInt(); @@ -284,9 +285,13 @@ Stream *Stream::makeFilter(char *name, Stream *str, Object *params, int recursio if (obj.isBool()) { black = obj.getBool(); } + obj = params->dictLookup("DamagedRowsBeforeError", recursion); + if (obj.isInt()) { + damagedRowsBeforeError = obj.getInt(); + } } str = new CCITTFaxStream(str, encoding, endOfLine, byteAlign, - columns, rows, endOfBlock, black); + columns, rows, endOfBlock, black, damagedRowsBeforeError); } else if (!strcmp(name, "DCTDecode") || !strcmp(name, "DCT")) { #ifdef HAVE_DCT_DECODER int colorXform = -1; @@ -1643,12 +1648,13 @@ GBool RunLengthStream::fillBuf() { CCITTFaxStream::CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA, GBool byteAlignA, int columnsA, int rowsA, - GBool endOfBlockA, GBool blackA): + GBool endOfBlockA, GBool blackA, int damagedRowsBeforeErrorA): FilterStream(strA) { encoding = encodingA; endOfLine = endOfLineA; byteAlign = byteAlignA; columns = columnsA; + damagedRowsBeforeError = damagedRowsBeforeErrorA; if (columns < 1) { columns = 1; } else if (columns > INT_MAX - 2) { diff --git a/poppler/Stream.h b/poppler/Stream.h index 152dbb0f..36988ccc 100644 --- a/poppler/Stream.h +++ b/poppler/Stream.h @@ -794,7 +794,7 @@ public: CCITTFaxStream(Stream *strA, int encodingA, GBool endOfLineA, GBool byteAlignA, int columnsA, int rowsA, - GBool endOfBlockA, GBool blackA); + GBool endOfBlockA, GBool blackA, int damagedRowsBeforeErrorA); ~CCITTFaxStream(); StreamKind getKind() override { return strCCITTFax; } void reset() override; @@ -808,8 +808,11 @@ public: int getEncoding() { return encoding; } GBool getEndOfLine() { return endOfLine; } + GBool getEncodedByteAlign() { return byteAlign; } + GBool getEndOfBlock() { return endOfBlock; } int getColumns() { return columns; } GBool getBlackIs1() { return black; } + int getDamagedRowsBeforeError() { return damagedRowsBeforeError; } private: @@ -821,6 +824,7 @@ private: int rows; // 'Rows' parameter GBool endOfBlock; // 'EndOfBlock' parameter GBool black; // 'BlackIs1' parameter + int damagedRowsBeforeError; // 'DamagedRowsBeforeError' parameter GBool eof; // true if at eof GBool nextLine2D; // true if next line uses 2D encoding int row; // current row -- 2.11.0