aboutsummaryrefslogtreecommitdiff
path: root/src/pdf
diff options
context:
space:
mode:
Diffstat (limited to 'src/pdf')
-rw-r--r--src/pdf/BUILD.bazel14
-rw-r--r--src/pdf/SkJpegInfo.h18
-rw-r--r--src/pdf/SkJpegInfo_libjpegturbo.cpp59
-rw-r--r--src/pdf/SkJpegInfo_none.cpp120
-rw-r--r--src/pdf/SkPDFBitmap.cpp139
-rw-r--r--src/pdf/SkPDFBitmap.h24
-rw-r--r--src/pdf/SkPDFDocumentPriv.h4
-rw-r--r--src/pdf/SkPDFTypes.cpp4
-rw-r--r--src/pdf/SkPDFTypes.h1
9 files changed, 143 insertions, 240 deletions
diff --git a/src/pdf/BUILD.bazel b/src/pdf/BUILD.bazel
index b41f5aac18..38f6f081cb 100644
--- a/src/pdf/BUILD.bazel
+++ b/src/pdf/BUILD.bazel
@@ -38,7 +38,6 @@ PDF_FILES = [
"SkPDFMetadata.h",
"SkPDFResourceDict.cpp",
"SkPDFResourceDict.h",
- "SkJpegInfo.h",
"SkPDFShader.cpp",
"SkPDFShader.h",
"SkPDFSubsetFont.cpp",
@@ -60,11 +59,13 @@ split_srcs_and_hdrs(
files = PDF_FILES,
)
+#TODO: remove after Chromium no longer references this.
skia_filegroup(
name = "jpeg_info_libjpeg",
srcs = ["SkJpegInfo_libjpegturbo.cpp"],
)
+#TODO: remove after Chromium no longer references this.
skia_filegroup(
name = "jpeg_info_none",
srcs = ["SkJpegInfo_none.cpp"],
@@ -74,10 +75,7 @@ skia_filegroup(
name = "srcs",
srcs = [
":pdf_srcs",
- ] + select({
- "//src/codec:jpeg_decode_codec": [":jpeg_info_libjpeg"],
- "//conditions:default": [":jpeg_info_none"],
- }),
+ ],
visibility = ["//src:__pkg__"],
)
@@ -113,7 +111,11 @@ selects.config_setting_group(
skia_cc_deps(
name = "deps",
visibility = ["//src:__pkg__"],
- deps = ["@zlib_skia//:zlib"] + select({
+ deps = [
+ "@zlib_skia//:zlib",
+ #"//src/codec:jpeg_decode",
+ #"//src/encode:jpeg_encode",
+ ] + select({
":uses_harfbuzz": ["@harfbuzz"],
"//conditions:default": [],
}),
diff --git a/src/pdf/SkJpegInfo.h b/src/pdf/SkJpegInfo.h
index 736575d42f..17155e4830 100644
--- a/src/pdf/SkJpegInfo.h
+++ b/src/pdf/SkJpegInfo.h
@@ -7,22 +7,4 @@
#ifndef SkJpegInfo_DEFINED
#define SkJpegInfo_DEFINED
-#include "include/codec/SkEncodedOrigin.h"
-#include "include/private/SkEncodedInfo.h"
-
-#include <cstddef>
-
-struct SkISize;
-
-/** Returns true if the data seems to be a valid JPEG image with a known colorType.
-
- @param [out] size Image size in pixels
- @param [out] colorType Encoded color type (kGray_Color, kYUV_Color, several others).
- @param [out] orientation EXIF Orientation of the image.
-*/
-bool SkGetJpegInfo(const void* data, size_t len,
- SkISize* size,
- SkEncodedInfo::Color* colorType,
- SkEncodedOrigin* orientation);
-
#endif // SkJpegInfo_DEFINED
diff --git a/src/pdf/SkJpegInfo_libjpegturbo.cpp b/src/pdf/SkJpegInfo_libjpegturbo.cpp
index 41e73757df..020c041a5a 100644
--- a/src/pdf/SkJpegInfo_libjpegturbo.cpp
+++ b/src/pdf/SkJpegInfo_libjpegturbo.cpp
@@ -7,62 +7,3 @@
* This file can parse information from a JPEG using libjpeg (which must be compiled in).
*/
-#include "src/pdf/SkJpegInfo.h"
-
-#include "include/codec/SkEncodedOrigin.h"
-#include "include/core/SkSize.h"
-#include "include/core/SkStream.h"
-#include "include/core/SkTypes.h"
-#include "include/private/SkEncodedInfo.h"
-#include "include/private/base/SkTo.h"
-#include "src/codec/SkJpegCodec.h"
-#include "src/codec/SkJpegConstants.h"
-#include "src/codec/SkJpegDecoderMgr.h"
-#include "src/codec/SkJpegPriv.h"
-
-#include <cstddef>
-#include <csetjmp>
-
-extern "C" {
- #include "jpeglib.h" // NO_G3_REWRITE
-}
-
-bool SkGetJpegInfo(const void* data, size_t len,
- SkISize* size,
- SkEncodedInfo::Color* colorType,
- SkEncodedOrigin* orientation) {
- if (!SkJpegCodec::IsJpeg(data, len)) {
- return false;
- }
-
- SkMemoryStream stream(data, len);
- JpegDecoderMgr decoderMgr(&stream);
- // libjpeg errors will be caught and reported here
- skjpeg_error_mgr::AutoPushJmpBuf jmp(decoderMgr.errorMgr());
- if (setjmp(jmp)) {
- return false;
- }
- decoderMgr.init();
- jpeg_decompress_struct* dinfo = decoderMgr.dinfo();
- jpeg_save_markers(dinfo, kExifMarker, 0xFFFF);
- jpeg_save_markers(dinfo, kICCMarker, 0xFFFF);
- jpeg_save_markers(dinfo, kMpfMarker, 0xFFFF);
- jpeg_save_markers(dinfo, kGainmapMarker, 0xFFFF);
- if (JPEG_HEADER_OK != jpeg_read_header(dinfo, true)) {
- return false;
- }
- SkEncodedInfo::Color encodedColorType;
- if (!decoderMgr.getEncodedColor(&encodedColorType)) {
- return false; // Unable to interpret the color channels as colors.
- }
- if (colorType) {
- *colorType = encodedColorType;
- }
- if (orientation) {
- *orientation = SkJpegPriv::get_exif_orientation(dinfo);
- }
- if (size) {
- *size = {SkToS32(dinfo->image_width), SkToS32(dinfo->image_height)};
- }
- return true;
-}
diff --git a/src/pdf/SkJpegInfo_none.cpp b/src/pdf/SkJpegInfo_none.cpp
index b0e3cba263..78e44cd483 100644
--- a/src/pdf/SkJpegInfo_none.cpp
+++ b/src/pdf/SkJpegInfo_none.cpp
@@ -8,123 +8,3 @@
* it. This does not need Skia to be built with a JPEG library.
*/
-#include "src/pdf/SkJpegInfo.h"
-
-#include "include/codec/SkEncodedOrigin.h"
-#include "include/core/SkSize.h"
-#include "include/private/base/SkTo.h"
-
-namespace {
-class JpegSegment {
-public:
- JpegSegment(const void* data, size_t size)
- : fData(static_cast<const char*>(data))
- , fSize(size)
- , fOffset(0)
- , fLength(0) {}
- bool read() {
- if (!this->readBigendianUint16(&fMarker)) {
- return false;
- }
- if (JpegSegment::StandAloneMarker(fMarker)) {
- fLength = 0;
- fBuffer = nullptr;
- return true;
- }
- if (!this->readBigendianUint16(&fLength) || fLength < 2) {
- return false;
- }
- fLength -= 2; // Length includes itself for some reason.
- if (fOffset + fLength > fSize) {
- return false; // Segment too long.
- }
- fBuffer = &fData[fOffset];
- fOffset += fLength;
- return true;
- }
-
- bool isSOF() {
- return (fMarker & 0xFFF0) == 0xFFC0 && fMarker != 0xFFC4 &&
- fMarker != 0xFFC8 && fMarker != 0xFFCC;
- }
- uint16_t marker() { return fMarker; }
- uint16_t length() { return fLength; }
- const char* data() { return fBuffer; }
-
- static uint16_t GetBigendianUint16(const char* ptr) {
- // "the most significant byte shall come first"
- return (static_cast<uint8_t>(ptr[0]) << 8) |
- static_cast<uint8_t>(ptr[1]);
- }
-
-private:
- const char* const fData;
- const size_t fSize;
- size_t fOffset;
- const char* fBuffer;
- uint16_t fMarker;
- uint16_t fLength;
-
- bool readBigendianUint16(uint16_t* value) {
- if (fOffset + 2 > fSize) {
- return false;
- }
- *value = JpegSegment::GetBigendianUint16(&fData[fOffset]);
- fOffset += 2;
- return true;
- }
- static bool StandAloneMarker(uint16_t marker) {
- // RST[m] markers or SOI, EOI, TEM
- return (marker & 0xFFF8) == 0xFFD0 || marker == 0xFFD8 ||
- marker == 0xFFD9 || marker == 0xFF01;
- }
-};
-} // namespace
-
-bool SkGetJpegInfo(const void* data, size_t len,
- SkISize* size,
- SkEncodedInfo::Color* colorType,
- SkEncodedOrigin* orientation) {
- static const uint16_t kSOI = 0xFFD8;
- static const uint16_t kAPP0 = 0xFFE0;
- JpegSegment segment(data, len);
- if (!segment.read() || segment.marker() != kSOI) {
- return false; // not a JPEG
- }
- if (!segment.read() || segment.marker() != kAPP0) {
- return false; // not an APP0 segment
- }
- static const char kJfif[] = {'J', 'F', 'I', 'F', '\0'};
- SkASSERT(segment.data());
- if (SkToSizeT(segment.length()) < sizeof(kJfif) ||
- 0 != memcmp(segment.data(), kJfif, sizeof(kJfif))) {
- return false; // Not JFIF JPEG
- }
- do {
- if (!segment.read()) {
- return false; // malformed JPEG
- }
- } while (!segment.isSOF());
- if (segment.length() < 6) {
- return false; // SOF segment is short
- }
- if (8 != segment.data()[0]) {
- return false; // Only support 8-bit precision
- }
- int numberOfComponents = segment.data()[5];
- if (numberOfComponents != 1 && numberOfComponents != 3) {
- return false; // Invalid JFIF
- }
- if (size) {
- *size = {JpegSegment::GetBigendianUint16(&segment.data()[3]),
- JpegSegment::GetBigendianUint16(&segment.data()[1])};
- }
- if (colorType) {
- *colorType = numberOfComponents == 3 ? SkEncodedInfo::kYUV_Color
- : SkEncodedInfo::kGray_Color;
- }
- if (orientation) {
- *orientation = kTopLeft_SkEncodedOrigin;
- }
- return true;
-}
diff --git a/src/pdf/SkPDFBitmap.cpp b/src/pdf/SkPDFBitmap.cpp
index 8806150ce0..a3f4632e25 100644
--- a/src/pdf/SkPDFBitmap.cpp
+++ b/src/pdf/SkPDFBitmap.cpp
@@ -7,26 +7,34 @@
#include "src/pdf/SkPDFBitmap.h"
+#include "include/codec/SkCodec.h"
#include "include/codec/SkEncodedImageFormat.h"
+#include "include/codec/SkJpegDecoder.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkData.h"
#include "include/core/SkExecutor.h"
#include "include/core/SkImage.h"
#include "include/core/SkStream.h"
+#include "include/encode/SkICC.h"
#include "include/encode/SkJpegEncoder.h"
#include "include/private/SkColorData.h"
#include "include/private/base/SkTo.h"
#include "src/core/SkImageInfoPriv.h"
#include "src/pdf/SkDeflate.h"
-#include "src/pdf/SkJpegInfo.h"
#include "src/pdf/SkPDFDocumentPriv.h"
#include "src/pdf/SkPDFTypes.h"
+#include "src/pdf/SkPDFUnion.h"
#include "src/pdf/SkPDFUtils.h"
-////////////////////////////////////////////////////////////////////////////////
+
+/*static*/ const SkEncodedInfo& SkPDFBitmap::GetEncodedInfo(SkCodec& codec) {
+ return codec.getEncodedInfo();
+}
+
+namespace {
// write a single byte to a stream n times.
-static void fill_stream(SkWStream* out, char value, size_t n) {
+void fill_stream(SkWStream* out, char value, size_t n) {
char buffer[4096];
memset(buffer, value, sizeof(buffer));
for (size_t i = 0; i < n / sizeof(buffer); ++i) {
@@ -44,7 +52,7 @@ static void fill_stream(SkWStream* out, char value, size_t n) {
channel goes to black, and the should-be-transparent pixels are
rendered as grey because of the separate soft mask and color
resizing. e.g.: gm/bitmappremul.cpp */
-static SkColor get_neighbor_avg_color(const SkPixmap& bm, int xOrig, int yOrig) {
+SkColor get_neighbor_avg_color(const SkPixmap& bm, int xOrig, int yOrig) {
SkASSERT(kBGRA_8888_SkColorType == bm.colorType());
unsigned r = 0, g = 0, b = 0, n = 0;
// Clamp the range to the edge of the bitmap.
@@ -68,24 +76,22 @@ static SkColor get_neighbor_avg_color(const SkPixmap& bm, int xOrig, int yOrig)
: SK_ColorTRANSPARENT;
}
-namespace {
enum class SkPDFStreamFormat { DCT, Flate, Uncompressed };
-}
template <typename T>
-static void emit_image_stream(SkPDFDocument* doc,
- SkPDFIndirectReference ref,
- T writeStream,
- SkISize size,
- const char* colorSpace,
- SkPDFIndirectReference sMask,
- int length,
- SkPDFStreamFormat format) {
+void emit_image_stream(SkPDFDocument* doc,
+ SkPDFIndirectReference ref,
+ T writeStream,
+ SkISize size,
+ SkPDFUnion&& colorSpace,
+ SkPDFIndirectReference sMask,
+ int length,
+ SkPDFStreamFormat format) {
SkPDFDict pdfDict("XObject");
pdfDict.insertName("Subtype", "Image");
pdfDict.insertInt("Width", size.width());
pdfDict.insertInt("Height", size.height());
- pdfDict.insertName("ColorSpace", colorSpace);
+ pdfDict.insertUnion("ColorSpace", std::move(colorSpace));
if (sMask) {
pdfDict.insertRef("SMask", sMask);
}
@@ -113,7 +119,7 @@ static void emit_image_stream(SkPDFDocument* doc,
doc->emitStream(pdfDict, std::move(writeStream), ref);
}
-static void do_deflated_alpha(const SkPixmap& pm, SkPDFDocument* doc, SkPDFIndirectReference ref) {
+void do_deflated_alpha(const SkPixmap& pm, SkPDFDocument* doc, SkPDFIndirectReference ref) {
SkPDF::Metadata::CompressionLevel compressionLevel = doc->metadata().fCompressionLevel;
SkPDFStreamFormat format = compressionLevel == SkPDF::Metadata::CompressionLevel::None
? SkPDFStreamFormat::Uncompressed
@@ -156,14 +162,37 @@ static void do_deflated_alpha(const SkPixmap& pm, SkPDFDocument* doc, SkPDFIndir
#endif
int length = SkToInt(buffer.bytesWritten());
emit_image_stream(doc, ref, [&buffer](SkWStream* stream) { buffer.writeToAndReset(stream); },
- pm.info().dimensions(), "DeviceGray", SkPDFIndirectReference(),
- length, format);
+ pm.info().dimensions(), SkPDFUnion::Name("DeviceGray"),
+ SkPDFIndirectReference(), length, format);
}
-static void do_deflated_image(const SkPixmap& pm,
- SkPDFDocument* doc,
- bool isOpaque,
- SkPDFIndirectReference ref) {
+SkPDFUnion write_icc_profile(SkPDFDocument* doc, sk_sp<SkData>&& icc, int channels) {
+ SkPDFIndirectReference iccStreamRef;
+ {
+ static SkMutex iccProfileMapMutex;
+ SkAutoMutexExclusive lock(iccProfileMapMutex);
+
+ SkPDFIndirectReference* ref = doc->fICCProfileMap.find(SkPDFIccProfileKey{icc});
+ if (ref) {
+ iccStreamRef = *ref;
+ } else {
+ std::unique_ptr<SkPDFDict> iccStreamDict = SkPDFMakeDict();
+ iccStreamDict->insertInt("N", channels);
+ iccStreamRef = SkPDFStreamOut(std::move(iccStreamDict), SkMemoryStream::Make(icc), doc);
+ doc->fICCProfileMap.set(SkPDFIccProfileKey{icc}, iccStreamRef);
+ }
+ }
+
+ std::unique_ptr<SkPDFArray> iccPDF = SkPDFMakeArray();
+ iccPDF->appendName("ICCBased");
+ iccPDF->appendRef(iccStreamRef);
+ return SkPDFUnion::Object(std::move(iccPDF));
+}
+
+void do_deflated_image(const SkPixmap& pm,
+ SkPDFDocument* doc,
+ bool isOpaque,
+ SkPDFIndirectReference ref) {
SkPDFIndirectReference sMask;
if (!isOpaque) {
sMask = doc->reserveRef();
@@ -179,18 +208,22 @@ static void do_deflated_image(const SkPixmap& pm,
deflateWStream.emplace(&buffer, SkToInt(compressionLevel));
stream = &*deflateWStream;
}
- const char* colorSpace = "DeviceGray";
+ SkPDFUnion colorSpace = SkPDFUnion::Name("DeviceGray");
+ int channels;
switch (pm.colorType()) {
case kAlpha_8_SkColorType:
+ channels = 1;
fill_stream(stream, '\x00', pm.width() * pm.height());
break;
case kGray_8_SkColorType:
+ channels = 1;
SkASSERT(sMask.fValue = -1);
SkASSERT(pm.rowBytes() == (size_t)pm.width());
stream->write(pm.addr8(), pm.width() * pm.height());
break;
default:
- colorSpace = "DeviceRGB";
+ colorSpace = SkPDFUnion::Name("DeviceRGB");
+ channels = 3;
SkASSERT(pm.alphaType() == kUnpremul_SkAlphaType);
SkASSERT(pm.colorType() == kBGRA_8888_SkColorType);
SkASSERT(pm.rowBytes() == (size_t)pm.width() * 4);
@@ -219,26 +252,40 @@ static void do_deflated_image(const SkPixmap& pm,
if (deflateWStream) {
deflateWStream->finalize();
}
+
+ if (pm.colorSpace()) {
+ skcms_ICCProfile iccProfile;
+ pm.colorSpace()->toProfile(&iccProfile);
+ sk_sp<SkData> iccData = SkWriteICCProfile(&iccProfile, "");
+ colorSpace = write_icc_profile(doc, std::move(iccData), channels);
+ }
+
#ifdef SK_PDF_BASE85_BINARY
SkPDFUtils::Base85Encode(buffer.detachAsStream(), &buffer);
#endif
int length = SkToInt(buffer.bytesWritten());
emit_image_stream(doc, ref, [&buffer](SkWStream* stream) { buffer.writeToAndReset(stream); },
- pm.info().dimensions(), colorSpace, sMask, length, format);
+ pm.info().dimensions(), std::move(colorSpace), sMask, length, format);
if (!isOpaque) {
do_deflated_alpha(pm, doc, sMask);
}
}
-static bool do_jpeg(sk_sp<SkData> data, SkPDFDocument* doc, SkISize size,
- SkPDFIndirectReference ref) {
- SkISize jpegSize;
- SkEncodedInfo::Color jpegColorType;
- SkEncodedOrigin exifOrientation;
- if (!SkGetJpegInfo(data->data(), data->size(), &jpegSize,
- &jpegColorType, &exifOrientation)) {
+bool do_jpeg(sk_sp<SkData> data, SkColorSpace* imageColorSpace, SkPDFDocument* doc, SkISize size,
+ SkPDFIndirectReference ref) {
+ static constexpr const SkCodecs::Decoder decoders[] = {
+ SkJpegDecoder::Decoder(),
+ };
+ std::unique_ptr<SkCodec> codec = SkCodec::MakeFromData(data, decoders);
+ if (!codec) {
return false;
}
+
+ SkISize jpegSize = codec->dimensions();
+ const SkEncodedInfo& encodedInfo = SkPDFBitmap::GetEncodedInfo(*codec);
+ SkEncodedInfo::Color jpegColorType = encodedInfo.color();
+ SkEncodedOrigin exifOrientation = codec->getOrigin();
+
bool yuv = jpegColorType == SkEncodedInfo::kYUV_Color;
bool goodColorType = yuv || jpegColorType == SkEncodedInfo::kGray_Color;
if (jpegSize != size // Safety check.
@@ -252,14 +299,28 @@ static bool do_jpeg(sk_sp<SkData> data, SkPDFDocument* doc, SkISize size,
data = buffer.detachAsData();
#endif
+ int channels = yuv ? 3 : 1;
+ SkPDFUnion colorSpace = yuv ? SkPDFUnion::Name("DeviceRGB") : SkPDFUnion::Name("DeviceGray");
+ if (sk_sp<SkData> encodedIccProfileData = encodedInfo.profileData()) {
+ colorSpace = write_icc_profile(doc, std::move(encodedIccProfileData), channels);
+ } else if (const skcms_ICCProfile* codecIccProfile = codec->getICCProfile()) {
+ sk_sp<SkData> codecIccData = SkWriteICCProfile(codecIccProfile, "");
+ colorSpace = write_icc_profile(doc, std::move(codecIccData), channels);
+ } else if (imageColorSpace) {
+ skcms_ICCProfile imageIccProfile;
+ imageColorSpace->toProfile(&imageIccProfile);
+ sk_sp<SkData> imageIccData = SkWriteICCProfile(&imageIccProfile, "");
+ colorSpace = write_icc_profile(doc, std::move(imageIccData), channels);
+ }
+
emit_image_stream(doc, ref,
[&data](SkWStream* dst) { dst->write(data->data(), data->size()); },
- jpegSize, yuv ? "DeviceRGB" : "DeviceGray",
+ jpegSize, std::move(colorSpace),
SkPDFIndirectReference(), SkToInt(data->size()), SkPDFStreamFormat::DCT);
return true;
}
-static SkBitmap to_pixels(const SkImage* image) {
+SkBitmap to_pixels(const SkImage* image) {
SkBitmap bm;
int w = image->width(),
h = image->height();
@@ -273,7 +334,8 @@ static SkBitmap to_pixels(const SkImage* image) {
default: {
// TODO: makeColorSpace(sRGB) or actually tag the images
SkAlphaType at = bm.isOpaque() ? kOpaque_SkAlphaType : kUnpremul_SkAlphaType;
- bm.allocPixels(SkImageInfo::Make(w, h, kBGRA_8888_SkColorType, at));
+ bm.allocPixels(
+ SkImageInfo::Make(w, h, kBGRA_8888_SkColorType, at, image->refColorSpace()));
}
}
// TODO: support GPU images in PDFs
@@ -291,8 +353,9 @@ void serialize_image(const SkImage* img,
SkASSERT(doc);
SkASSERT(encodingQuality >= 0);
SkISize dimensions = img->dimensions();
+
if (sk_sp<SkData> data = img->refEncodedData()) {
- if (do_jpeg(std::move(data), doc, dimensions, ref)) {
+ if (do_jpeg(std::move(data), img->colorSpace(), doc, dimensions, ref)) {
return;
}
}
@@ -304,7 +367,7 @@ void serialize_image(const SkImage* img,
jOpts.fQuality = encodingQuality;
SkDynamicMemoryWStream stream;
if (SkJpegEncoder::Encode(&stream, pm, jOpts)) {
- if (do_jpeg(stream.detachAsData(), doc, dimensions, ref)) {
+ if (do_jpeg(stream.detachAsData(), pm.colorSpace(), doc, dimensions, ref)) {
return;
}
}
@@ -312,6 +375,8 @@ void serialize_image(const SkImage* img,
do_deflated_image(pm, doc, isOpaque, ref);
}
+} // namespace
+
SkPDFIndirectReference SkPDFSerializeImage(const SkImage* img,
SkPDFDocument* doc,
int encodingQuality) {
diff --git a/src/pdf/SkPDFBitmap.h b/src/pdf/SkPDFBitmap.h
index bc2c57bd3b..d310d7b6a6 100644
--- a/src/pdf/SkPDFBitmap.h
+++ b/src/pdf/SkPDFBitmap.h
@@ -7,8 +7,13 @@
#ifndef SkPDFBitmap_DEFINED
#define SkPDFBitmap_DEFINED
+#include "include/core/SkData.h"
+#include "src/core/SkChecksum.h"
+
+class SkCodec;
class SkImage;
class SkPDFDocument;
+struct SkEncodedInfo;
struct SkPDFIndirectReference;
/**
@@ -19,4 +24,23 @@ SkPDFIndirectReference SkPDFSerializeImage(const SkImage* img,
SkPDFDocument* doc,
int encodingQuality = 101);
+class SkPDFBitmap {
+public:
+ static const SkEncodedInfo& GetEncodedInfo(SkCodec&);
+};
+
+struct SkPDFIccProfileKey {
+ sk_sp<SkData> fData;
+ bool operator==(const SkPDFIccProfileKey& that) const {
+ return fData->equals(that.fData.get());
+ }
+ bool operator!=(const SkPDFIccProfileKey& rhs) const { return !(*this == rhs); }
+
+ struct Hash {
+ uint32_t operator()(const SkPDFIccProfileKey& k) const {
+ return SkChecksum::Hash32(k.fData->data(), k.fData->size());
+ }
+ };
+};
+
#endif // SkPDFBitmap_DEFINED
diff --git a/src/pdf/SkPDFDocumentPriv.h b/src/pdf/SkPDFDocumentPriv.h
index dffc239c3e..4d8e5eb892 100644
--- a/src/pdf/SkPDFDocumentPriv.h
+++ b/src/pdf/SkPDFDocumentPriv.h
@@ -12,6 +12,7 @@
#include "include/docs/SkPDFDocument.h"
#include "include/private/base/SkMutex.h"
#include "src/core/SkTHash.h"
+#include "src/pdf/SkPDFBitmap.h"
#include "src/pdf/SkPDFGraphicState.h"
#include "src/pdf/SkPDFMetadata.h"
#include "src/pdf/SkPDFShader.h"
@@ -149,6 +150,9 @@ public:
SkPDFIndirectReference,
SkPDFGradientShader::KeyHash> fGradientPatternMap;
skia_private::THashMap<SkBitmapKey, SkPDFIndirectReference> fPDFBitmapMap;
+ skia_private::THashMap<SkPDFIccProfileKey,
+ SkPDFIndirectReference,
+ SkPDFIccProfileKey::Hash> fICCProfileMap;
skia_private::THashMap<uint32_t, std::unique_ptr<SkAdvancedTypefaceMetrics>> fTypefaceMetrics;
skia_private::THashMap<uint32_t, std::vector<SkString>> fType1GlyphNames;
skia_private::THashMap<uint32_t, std::vector<SkUnichar>> fToUnicodeMap;
diff --git a/src/pdf/SkPDFTypes.cpp b/src/pdf/SkPDFTypes.cpp
index 79c402a9ad..d9b6d854b8 100644
--- a/src/pdf/SkPDFTypes.cpp
+++ b/src/pdf/SkPDFTypes.cpp
@@ -527,6 +527,10 @@ void SkPDFDict::insertTextString(const char key[], SkString value) {
fRecords.emplace_back(SkPDFUnion::Name(key), SkPDFUnion::TextString(std::move(value)));
}
+void SkPDFDict::insertUnion(const char key[], SkPDFUnion&& value) {
+ fRecords.emplace_back(SkPDFUnion::Name(key), std::move(value));
+}
+
////////////////////////////////////////////////////////////////////////////////
diff --git a/src/pdf/SkPDFTypes.h b/src/pdf/SkPDFTypes.h
index 370c94878f..579434ba8e 100644
--- a/src/pdf/SkPDFTypes.h
+++ b/src/pdf/SkPDFTypes.h
@@ -186,6 +186,7 @@ public:
void insertTextString(const char key[], const char value[]);
void insertByteString(const char key[], SkString value);
void insertTextString(const char key[], SkString value);
+ void insertUnion(const char key[], SkPDFUnion&&);
private:
std::vector<std::pair<SkPDFUnion, SkPDFUnion>> fRecords;