diff --git a/src/pdf/SkPDFBitmap.cpp b/src/pdf/SkPDFBitmap.cpp index 4e66a8ad8a..7fc9c4ef9a 100644 --- a/src/pdf/SkPDFBitmap.cpp +++ b/src/pdf/SkPDFBitmap.cpp @@ -123,7 +123,7 @@ static SkPDFIndirectReference do_deflated_alpha(const SkPixmap& pm, SkPDFDocumen deflateWStream.finalize(); #ifdef SK_PDF_BASE85_BINARY - SkPDFUtils::Base85Encode(&buffer); + SkPDFUtils::Base85Encode(buffer.detachAsStream(), &buffer); #endif SkWStream* stream = doc->beginObject(ref); emit_dict(stream, pm.info().dimensions(), "DeviceGray", nullptr, buffer.bytesWritten()); @@ -181,7 +181,7 @@ static void do_deflated_image(const SkPixmap& pm, } deflateWStream.finalize(); #ifdef SK_PDF_BASE85_BINARY - SkPDFUtils::Base85Encode(&buffer); + SkPDFUtils::Base85Encode(buffer.detachAsStream(), &buffer); #endif SkWStream* stream = doc->beginObject(ref); emit_dict(stream, pm.info().dimensions(), colorSpace, @@ -214,7 +214,13 @@ static bool do_jpeg(const SkData& data, SkPDFDocument* doc, SkISize size, gJpegImageObjects.fetch_add(1); #endif - SkWStream* stream = doc->beginObject(ref); + #ifdef SK_PDF_BASE85_BINARY + SkDynamicMemoryWStream buffer; + SkPDFUtils::Base85Encode(SkMemoryStream::MakeDirect(data.data(), data.size()), &buffer); + int length = SkToInt(buffer.bytesWritten()); + #else + int length = SkToInt(data.size()); + #endif SkPDFDict pdfDict("XObject"); pdfDict.insertName("Subtype", "Image"); pdfDict.insertInt("Width", jpegSize.width()); @@ -225,12 +231,25 @@ static bool do_jpeg(const SkData& data, SkPDFDocument* doc, SkISize size, pdfDict.insertName("ColorSpace", "DeviceGray"); } pdfDict.insertInt("BitsPerComponent", 8); + #ifdef SK_PDF_BASE85_BINARY + auto filters = SkPDFMakeArray(); + filters->appendName("ASCII85Decode"); + filters->appendName("DCTDecode"); + pdfDict.insertObject("Filter", std::move(filters)); + #else pdfDict.insertName("Filter", "DCTDecode"); + #endif pdfDict.insertInt("ColorTransform", 0); - pdfDict.insertInt("Length", SkToInt(data.size())); + pdfDict.insertInt("Length", length); + + SkWStream* stream = doc->beginObject(ref); pdfDict.emitObject(stream); stream->writeText(" stream\n"); + #ifdef SK_PDF_BASE85_BINARY + buffer.writeToAndReset(stream); + #else stream->write(data.data(), data.size()); + #endif stream->writeText("\nendstream"); doc->endObject(); return true; diff --git a/src/pdf/SkPDFTypes.cpp b/src/pdf/SkPDFTypes.cpp index e45d7ed215..0b98fca7a4 100644 --- a/src/pdf/SkPDFTypes.cpp +++ b/src/pdf/SkPDFTypes.cpp @@ -440,7 +440,7 @@ static void serialize_stream(const SkPDFDict* origDict, deflateWStream.finalize(); #ifdef SK_PDF_BASE85_BINARY { - SkPDFUtils::Base85Encode(&compressedData); + SkPDFUtils::Base85Encode(compressedData.detachAsStream(), &compressedData); tmp = compressedData.detachAsStream(); stream = tmp.get(); auto filters = SkPDFMakeArray(); diff --git a/src/pdf/SkPDFUtils.cpp b/src/pdf/SkPDFUtils.cpp index b15bd9a387..e53accf5d9 100644 --- a/src/pdf/SkPDFUtils.cpp +++ b/src/pdf/SkPDFUtils.cpp @@ -337,52 +337,38 @@ bool SkPDFUtils::ToBitmap(const SkImage* img, SkBitmap* dst) { } #ifdef SK_PDF_BASE85_BINARY -static void base85_fourbytes(uint32_t v, char dst[5]) { - for (int n = 4; n > 0; --n) { - dst[n] = (v % 85) + '!'; - v /= 85; - } - dst[0] = v + '!'; -} - -static uint32_t big_end(const uint8_t s[4]) { - return ((uint32_t)s[0] << 24) | ((uint32_t)s[1] << 16) | ((uint32_t)s[2] << 8) | s[3]; -} - -void SkPDFUtils::Base85Encode(SkDynamicMemoryWStream* dst) { +void SkPDFUtils::Base85Encode(std::unique_ptr stream, SkDynamicMemoryWStream* dst) { SkASSERT(dst); - std::unique_ptr stream = dst->detachAsStream(); - SkASSERT(src); - size_t remaining = stream->getLength(); + SkASSERT(stream); dst->writeText("\n"); - int line = 0; - while (remaining > 3) { - uint8_t src[4]; - (void)stream->read(src, 4); - remaining -= 4; - uint32_t v = big_end(src); - if (v != 0) { - char buffer[5]; - base85_fourbytes(v, buffer); - dst->write(buffer, 5); - line += 5; - } else { - dst->writeText("z"); - line += 1; - } - if (line > 74) { - dst->writeText("\n"); - line = 0; - } - } - if (remaining > 0) { - SkASSERT(remaining < 4); + int column = 0; + while (true) { uint8_t src[4] = {0, 0, 0, 0}; - (void)stream->read(src, remaining); - char buffer[5]; - base85_fourbytes(big_end(src), buffer); - dst->write(buffer, remaining + 1); + size_t count = stream->read(src, 4); + SkASSERT(count < 5); + if (0 == count) { + dst->writeText("~>\n"); + return; + } + uint32_t v = ((uint32_t)src[0] << 24) | ((uint32_t)src[1] << 16) | + ((uint32_t)src[2] << 8) | src[3]; + if (v == 0 && count == 4) { + dst->writeText("z"); + column += 1; + } else { + char buffer[5]; + for (int n = 4; n > 0; --n) { + buffer[n] = (v % 85) + '!'; + v /= 85; + } + buffer[0] = v + '!'; + dst->write(buffer, count + 1); + column += count + 1; + } + if (column > 74) { + dst->writeText("\n"); + column = 0; + } } - dst->writeText("~>\n"); } #endif // SK_PDF_BASE85_BINARY diff --git a/src/pdf/SkPDFUtils.h b/src/pdf/SkPDFUtils.h index 7c655eae37..0624c9a989 100644 --- a/src/pdf/SkPDFUtils.h +++ b/src/pdf/SkPDFUtils.h @@ -127,7 +127,7 @@ void PopulateTilingPatternDict(SkPDFDict* pattern, bool ToBitmap(const SkImage* img, SkBitmap* dst); #ifdef SK_PDF_BASE85_BINARY -void Base85Encode(SkDynamicMemoryWStream*); +void Base85Encode(std::unique_ptr src, SkDynamicMemoryWStream* dst); #endif // SK_PDF_BASE85_BINARY } // namespace SkPDFUtils diff --git a/tests/PDFJpegEmbedTest.cpp b/tests/PDFJpegEmbedTest.cpp index ccac4f3ecf..e1ae59bfed 100644 --- a/tests/PDFJpegEmbedTest.cpp +++ b/tests/PDFJpegEmbedTest.cpp @@ -71,7 +71,9 @@ DEF_TEST(SkPDF_JpegEmbedTest, r) { sk_sp pdfData = pdf.detachAsData(); SkASSERT(pdfData); + #ifndef SK_PDF_BASE85_BINARY REPORTER_ASSERT(r, is_subset_of(mandrillData.get(), pdfData.get())); + #endif // This JPEG uses a nonstandard colorspace - it can not be // embedded into the PDF directly.