SkPDF: move type1 font code into single file
Change-Id: I0e0bf4cdb298b161cabf74eacc4b3950d7240643 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/209172 Commit-Queue: Ben Wagner <bungeman@google.com> Reviewed-by: Ben Wagner <bungeman@google.com>
This commit is contained in:
parent
71713f6eaa
commit
2e904bc66b
@ -20,8 +20,6 @@ skia_pdf_sources = [
|
|||||||
"$_src/pdf/SkKeyedImage.h",
|
"$_src/pdf/SkKeyedImage.h",
|
||||||
"$_src/pdf/SkPDFBitmap.cpp",
|
"$_src/pdf/SkPDFBitmap.cpp",
|
||||||
"$_src/pdf/SkPDFBitmap.h",
|
"$_src/pdf/SkPDFBitmap.h",
|
||||||
"$_src/pdf/SkPDFConvertType1FontStream.cpp",
|
|
||||||
"$_src/pdf/SkPDFConvertType1FontStream.h",
|
|
||||||
"$_src/pdf/SkPDFDevice.cpp",
|
"$_src/pdf/SkPDFDevice.cpp",
|
||||||
"$_src/pdf/SkPDFDevice.h",
|
"$_src/pdf/SkPDFDevice.h",
|
||||||
"$_src/pdf/SkPDFDocument.cpp",
|
"$_src/pdf/SkPDFDocument.cpp",
|
||||||
@ -50,6 +48,8 @@ skia_pdf_sources = [
|
|||||||
"$_src/pdf/SkPDFSubsetFont.h",
|
"$_src/pdf/SkPDFSubsetFont.h",
|
||||||
"$_src/pdf/SkPDFTag.cpp",
|
"$_src/pdf/SkPDFTag.cpp",
|
||||||
"$_src/pdf/SkPDFTag.h",
|
"$_src/pdf/SkPDFTag.h",
|
||||||
|
"$_src/pdf/SkPDFType1Font.cpp",
|
||||||
|
"$_src/pdf/SkPDFType1Font.h",
|
||||||
"$_src/pdf/SkPDFTypes.cpp",
|
"$_src/pdf/SkPDFTypes.cpp",
|
||||||
"$_src/pdf/SkPDFTypes.h",
|
"$_src/pdf/SkPDFTypes.h",
|
||||||
"$_src/pdf/SkPDFUtils.cpp",
|
"$_src/pdf/SkPDFUtils.cpp",
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 Google Inc.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by a BSD-style license that can be
|
|
||||||
* found in the LICENSE file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SkPDFConvertType1FontStream_DEFINED
|
|
||||||
#define SkPDFConvertType1FontStream_DEFINED
|
|
||||||
|
|
||||||
#include "SkData.h"
|
|
||||||
#include "SkStream.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
"A standard Type 1 font program, as described in the Adobe Type 1
|
|
||||||
Font Format specification, consists of three parts: a clear-text
|
|
||||||
portion (written using PostScript syntax), an encrypted portion, and
|
|
||||||
a fixed-content portion. The fixed-content portion contains 512
|
|
||||||
ASCII zeros followed by a cleartomark operator, and perhaps followed
|
|
||||||
by additional data. Although the encrypted portion of a standard
|
|
||||||
Type 1 font may be in binary or ASCII hexadecimal format, PDF
|
|
||||||
supports only the binary format."
|
|
||||||
*/
|
|
||||||
sk_sp<SkData> SkPDFConvertType1FontStream(
|
|
||||||
std::unique_ptr<SkStreamAsset> srcStream, size_t* headerLen,
|
|
||||||
size_t* dataLen, size_t* trailerLen);
|
|
||||||
|
|
||||||
#endif // SkPDFConvertType1FontStream_DEFINED
|
|
@ -14,7 +14,6 @@
|
|||||||
#include "SkMakeUnique.h"
|
#include "SkMakeUnique.h"
|
||||||
#include "SkPDFBitmap.h"
|
#include "SkPDFBitmap.h"
|
||||||
#include "SkPDFDocument.h"
|
#include "SkPDFDocument.h"
|
||||||
#include "SkPDFConvertType1FontStream.h"
|
|
||||||
#include "SkPDFDevice.h"
|
#include "SkPDFDevice.h"
|
||||||
#include "SkPDFDocumentPriv.h"
|
#include "SkPDFDocumentPriv.h"
|
||||||
#include "SkPDFMakeCIDGlyphWidthsArray.h"
|
#include "SkPDFMakeCIDGlyphWidthsArray.h"
|
||||||
@ -49,6 +48,10 @@ SkExclusiveStrikePtr SkPDFFont::MakeVectorCache(SkTypeface* face, int* size) {
|
|||||||
font, SkPaint(), props, SkScalerContextFlags::kFakeGammaAndBoostContrast, SkMatrix::I());
|
font, SkPaint(), props, SkScalerContextFlags::kFakeGammaAndBoostContrast, SkMatrix::I());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SkPDFFont::GetType1GlyphNames(const SkTypeface& face, SkString* dst) {
|
||||||
|
face.getPostScriptGlyphNames(dst);
|
||||||
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
// PDF's notion of symbolic vs non-symbolic is related to the character set, not
|
// PDF's notion of symbolic vs non-symbolic is related to the character set, not
|
||||||
// symbols vs. characters. Rarely is a font the right character set to call it
|
// symbols vs. characters. Rarely is a font the right character set to call it
|
||||||
@ -57,15 +60,11 @@ static const int32_t kPdfSymbolic = 4;
|
|||||||
|
|
||||||
|
|
||||||
// scale from em-units to base-1000, returning as a SkScalar
|
// scale from em-units to base-1000, returning as a SkScalar
|
||||||
SkScalar from_font_units(SkScalar scaled, uint16_t emSize) {
|
inline SkScalar from_font_units(SkScalar scaled, uint16_t emSize) {
|
||||||
if (emSize == 1000) {
|
return emSize == 1000 ? scaled : scaled * 1000 / emSize;
|
||||||
return scaled;
|
|
||||||
} else {
|
|
||||||
return scaled * 1000 / emSize;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SkScalar scaleFromFontUnits(int16_t val, uint16_t emSize) {
|
inline SkScalar scaleFromFontUnits(int16_t val, uint16_t emSize) {
|
||||||
return from_font_units(SkIntToScalar(val), emSize);
|
return from_font_units(SkIntToScalar(val), emSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,7 +238,7 @@ SkPDFFont::SkPDFFont(sk_sp<SkTypeface> typeface,
|
|||||||
, fIndirectReference(indirectReference)
|
, fIndirectReference(indirectReference)
|
||||||
, fFontType(fontType) {}
|
, fFontType(fontType) {}
|
||||||
|
|
||||||
static void add_common_font_descriptor_entries(SkPDFDict* descriptor,
|
void SkPDFFont::PopulateCommonFontDescriptor(SkPDFDict* descriptor,
|
||||||
const SkAdvancedTypefaceMetrics& metrics,
|
const SkAdvancedTypefaceMetrics& metrics,
|
||||||
uint16_t emSize,
|
uint16_t emSize,
|
||||||
int16_t defaultWidth) {
|
int16_t defaultWidth) {
|
||||||
@ -296,7 +295,7 @@ static void emit_subset_type0(const SkPDFFont& font, SkPDFDocument* doc) {
|
|||||||
|
|
||||||
auto descriptor = SkPDFMakeDict("FontDescriptor");
|
auto descriptor = SkPDFMakeDict("FontDescriptor");
|
||||||
uint16_t emSize = SkToU16(font.typeface()->getUnitsPerEm());
|
uint16_t emSize = SkToU16(font.typeface()->getUnitsPerEm());
|
||||||
add_common_font_descriptor_entries(descriptor.get(), metrics, emSize , 0);
|
SkPDFFont::PopulateCommonFontDescriptor(descriptor.get(), metrics, emSize , 0);
|
||||||
|
|
||||||
int ttcIndex;
|
int ttcIndex;
|
||||||
std::unique_ptr<SkStreamAsset> fontAsset = face->openStream(&ttcIndex);
|
std::unique_ptr<SkStreamAsset> fontAsset = face->openStream(&ttcIndex);
|
||||||
@ -409,117 +408,6 @@ static void emit_subset_type0(const SkPDFFont& font, SkPDFDocument* doc) {
|
|||||||
doc->emit(fontDict, font.indirectReference());
|
doc->emit(fontDict, font.indirectReference());
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Type1Font
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
static SkPDFIndirectReference make_type1_font_descriptor(SkPDFDocument* doc,
|
|
||||||
const SkTypeface* typeface,
|
|
||||||
const SkAdvancedTypefaceMetrics* info) {
|
|
||||||
SkPDFDict descriptor("FontDescriptor");
|
|
||||||
uint16_t emSize = SkToU16(typeface->getUnitsPerEm());
|
|
||||||
if (info) {
|
|
||||||
add_common_font_descriptor_entries(&descriptor, *info, emSize, 0);
|
|
||||||
if (can_embed(*info)) {
|
|
||||||
int ttcIndex;
|
|
||||||
size_t header SK_INIT_TO_AVOID_WARNING;
|
|
||||||
size_t data SK_INIT_TO_AVOID_WARNING;
|
|
||||||
size_t trailer SK_INIT_TO_AVOID_WARNING;
|
|
||||||
std::unique_ptr<SkStreamAsset> rawFontData = typeface->openStream(&ttcIndex);
|
|
||||||
sk_sp<SkData> fontData = SkPDFConvertType1FontStream(std::move(rawFontData),
|
|
||||||
&header, &data, &trailer);
|
|
||||||
if (fontData) {
|
|
||||||
std::unique_ptr<SkPDFDict> dict = SkPDFMakeDict();
|
|
||||||
dict->insertInt("Length1", header);
|
|
||||||
dict->insertInt("Length2", data);
|
|
||||||
dict->insertInt("Length3", trailer);
|
|
||||||
auto fontStream = SkMemoryStream::Make(std::move(fontData));
|
|
||||||
descriptor.insertRef("FontFile", SkPDFStreamOut(std::move(dict),
|
|
||||||
std::move(fontStream), doc, true));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return doc->emit(descriptor);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static const std::vector<SkString>& type_1_glyphnames(SkPDFDocument* canon,
|
|
||||||
const SkTypeface* typeface) {
|
|
||||||
SkFontID fontID = typeface->uniqueID();
|
|
||||||
const std::vector<SkString>* glyphNames = canon->fType1GlyphNames.find(fontID);
|
|
||||||
if (!glyphNames) {
|
|
||||||
std::vector<SkString> names(typeface->countGlyphs());
|
|
||||||
SkPDFFont::GetType1GlyphNames(*typeface, names.data());
|
|
||||||
glyphNames = canon->fType1GlyphNames.set(fontID, std::move(names));
|
|
||||||
}
|
|
||||||
SkASSERT(glyphNames);
|
|
||||||
return *glyphNames;
|
|
||||||
}
|
|
||||||
|
|
||||||
static SkPDFIndirectReference type1_font_descriptor(SkPDFDocument* doc,
|
|
||||||
const SkTypeface* typeface) {
|
|
||||||
SkFontID fontID = typeface->uniqueID();
|
|
||||||
if (SkPDFIndirectReference* ptr = doc->fFontDescriptors.find(fontID)) {
|
|
||||||
return *ptr;
|
|
||||||
}
|
|
||||||
const SkAdvancedTypefaceMetrics* info = SkPDFFont::GetMetrics(typeface, doc);
|
|
||||||
auto fontDescriptor = make_type1_font_descriptor(doc, typeface, info);
|
|
||||||
doc->fFontDescriptors.set(fontID, fontDescriptor);
|
|
||||||
return fontDescriptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void emit_subset_type1(const SkPDFFont& pdfFont, SkPDFDocument* doc) {
|
|
||||||
SkTypeface* typeface = pdfFont.typeface();
|
|
||||||
const std::vector<SkString> glyphNames = type_1_glyphnames(doc, typeface);
|
|
||||||
SkGlyphID firstGlyphID = pdfFont.firstGlyphID();
|
|
||||||
SkGlyphID lastGlyphID = pdfFont.lastGlyphID();
|
|
||||||
|
|
||||||
SkPDFDict font("Font");
|
|
||||||
font.insertRef("FontDescriptor", type1_font_descriptor(doc, typeface));
|
|
||||||
font.insertName("Subtype", "Type1");
|
|
||||||
if (const SkAdvancedTypefaceMetrics* info = SkPDFFont::GetMetrics(typeface, doc)) {
|
|
||||||
font.insertName("BaseFont", info->fPostScriptName);
|
|
||||||
}
|
|
||||||
|
|
||||||
// glyphCount not including glyph 0
|
|
||||||
unsigned glyphCount = 1 + lastGlyphID - firstGlyphID;
|
|
||||||
SkASSERT(glyphCount > 0 && glyphCount <= 255);
|
|
||||||
font.insertInt("FirstChar", (size_t)0);
|
|
||||||
font.insertInt("LastChar", (size_t)glyphCount);
|
|
||||||
{
|
|
||||||
int emSize;
|
|
||||||
auto glyphCache = SkPDFFont::MakeVectorCache(typeface, &emSize);
|
|
||||||
auto widths = SkPDFMakeArray();
|
|
||||||
SkScalar advance = glyphCache->getGlyphIDAdvance(0).fAdvanceX;
|
|
||||||
widths->appendScalar(from_font_units(advance, SkToU16(emSize)));
|
|
||||||
for (unsigned gID = firstGlyphID; gID <= lastGlyphID; gID++) {
|
|
||||||
advance = glyphCache->getGlyphIDAdvance(gID).fAdvanceX;
|
|
||||||
widths->appendScalar(from_font_units(advance, SkToU16(emSize)));
|
|
||||||
}
|
|
||||||
font.insertObject("Widths", std::move(widths));
|
|
||||||
}
|
|
||||||
auto encDiffs = SkPDFMakeArray();
|
|
||||||
encDiffs->reserve(lastGlyphID - firstGlyphID + 3);
|
|
||||||
encDiffs->appendInt(0);
|
|
||||||
|
|
||||||
SkASSERT(glyphNames.size() > lastGlyphID);
|
|
||||||
const SkString unknown("UNKNOWN");
|
|
||||||
encDiffs->appendName(glyphNames[0].isEmpty() ? unknown : glyphNames[0]);
|
|
||||||
for (int gID = firstGlyphID; gID <= lastGlyphID; gID++) {
|
|
||||||
encDiffs->appendName(glyphNames[gID].isEmpty() ? unknown : glyphNames[gID]);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto encoding = SkPDFMakeDict("Encoding");
|
|
||||||
encoding->insertObject("Differences", std::move(encDiffs));
|
|
||||||
font.insertObject("Encoding", std::move(encoding));
|
|
||||||
|
|
||||||
doc->emit(font, pdfFont.indirectReference());
|
|
||||||
}
|
|
||||||
|
|
||||||
void SkPDFFont::GetType1GlyphNames(const SkTypeface& face, SkString* dst) {
|
|
||||||
face.getPostScriptGlyphNames(dst);
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// PDFType3Font
|
// PDFType3Font
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -759,15 +647,16 @@ static void emit_subset_type3(const SkPDFFont& pdfFont, SkPDFDocument* doc) {
|
|||||||
doc->emit(font, pdfFont.indirectReference());
|
doc->emit(font, pdfFont.indirectReference());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SkPDFFont::emitSubset(SkPDFDocument* doc) const {
|
void SkPDFFont::emitSubset(SkPDFDocument* doc) const {
|
||||||
SkASSERT(fFontType != SkPDFFont().fFontType); // not default value
|
SkASSERT(fFontType != SkPDFFont().fFontType); // not default value
|
||||||
switch (fFontType) {
|
switch (fFontType) {
|
||||||
case SkAdvancedTypefaceMetrics::kType1CID_Font:
|
case SkAdvancedTypefaceMetrics::kType1CID_Font:
|
||||||
case SkAdvancedTypefaceMetrics::kTrueType_Font:
|
case SkAdvancedTypefaceMetrics::kTrueType_Font:
|
||||||
return emit_subset_type0(*this, doc);
|
return emit_subset_type0(*this, doc);
|
||||||
|
#ifndef SK_PDF_DO_NOT_SUPPORT_TYPE_1_FONTS
|
||||||
case SkAdvancedTypefaceMetrics::kType1_Font:
|
case SkAdvancedTypefaceMetrics::kType1_Font:
|
||||||
return emit_subset_type1(*this, doc);
|
return SkPDFEmitType1Font(*this, doc);
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
return emit_subset_type3(*this, doc);
|
return emit_subset_type3(*this, doc);
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "SkAdvancedTypefaceMetrics.h"
|
#include "SkAdvancedTypefaceMetrics.h"
|
||||||
#include "SkPDFDocument.h"
|
#include "SkPDFDocument.h"
|
||||||
#include "SkPDFGlyphUse.h"
|
#include "SkPDFGlyphUse.h"
|
||||||
|
#include "SkPDFType1Font.h"
|
||||||
#include "SkPDFTypes.h"
|
#include "SkPDFTypes.h"
|
||||||
#include "SkStrikeCache.h"
|
#include "SkStrikeCache.h"
|
||||||
#include "SkTypeface.h"
|
#include "SkTypeface.h"
|
||||||
@ -98,6 +99,11 @@ public:
|
|||||||
static const std::vector<SkUnichar>& GetUnicodeMap(const SkTypeface* typeface,
|
static const std::vector<SkUnichar>& GetUnicodeMap(const SkTypeface* typeface,
|
||||||
SkPDFDocument* canon);
|
SkPDFDocument* canon);
|
||||||
|
|
||||||
|
static void PopulateCommonFontDescriptor(SkPDFDict* descriptor,
|
||||||
|
const SkAdvancedTypefaceMetrics&,
|
||||||
|
uint16_t emSize,
|
||||||
|
int16_t defaultWidth);
|
||||||
|
|
||||||
void emitSubset(SkPDFDocument*) const;
|
void emitSubset(SkPDFDocument*) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,17 +1,23 @@
|
|||||||
/*
|
// Copyright 2019 Google LLC.
|
||||||
* Copyright 2011 Google Inc.
|
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
|
||||||
*
|
|
||||||
* Use of this source code is governed by a BSD-style license that can be
|
|
||||||
* found in the LICENSE file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "SkPDFConvertType1FontStream.h"
|
#include "SkPDFType1Font.h"
|
||||||
|
|
||||||
#include "SkTemplates.h"
|
#include "SkTemplates.h"
|
||||||
#include "SkTo.h"
|
#include "SkTo.h"
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
"A standard Type 1 font program, as described in the Adobe Type 1
|
||||||
|
Font Format specification, consists of three parts: a clear-text
|
||||||
|
portion (written using PostScript syntax), an encrypted portion, and
|
||||||
|
a fixed-content portion. The fixed-content portion contains 512
|
||||||
|
ASCII zeros followed by a cleartomark operator, and perhaps followed
|
||||||
|
by additional data. Although the encrypted portion of a standard
|
||||||
|
Type 1 font may be in binary or ASCII hexadecimal format, PDF
|
||||||
|
supports only the binary format."
|
||||||
|
*/
|
||||||
static bool parsePFBSection(const uint8_t** src, size_t* len, int sectionType,
|
static bool parsePFBSection(const uint8_t** src, size_t* len, int sectionType,
|
||||||
size_t* size) {
|
size_t* size) {
|
||||||
// PFB sections have a two or six bytes header. 0x80 and a one byte
|
// PFB sections have a two or six bytes header. 0x80 and a one byte
|
||||||
@ -123,9 +129,10 @@ static int8_t hexToBin(uint8_t c) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sk_sp<SkData> SkPDFConvertType1FontStream(
|
static sk_sp<SkData> convert_type1_font_stream(std::unique_ptr<SkStreamAsset> srcStream,
|
||||||
std::unique_ptr<SkStreamAsset> srcStream, size_t* headerLen,
|
size_t* headerLen,
|
||||||
size_t* dataLen, size_t* trailerLen) {
|
size_t* dataLen,
|
||||||
|
size_t* trailerLen) {
|
||||||
size_t srcLen = srcStream ? srcStream->getLength() : 0;
|
size_t srcLen = srcStream ? srcStream->getLength() : 0;
|
||||||
SkASSERT(srcLen);
|
SkASSERT(srcLen);
|
||||||
if (!srcLen) {
|
if (!srcLen) {
|
||||||
@ -207,3 +214,115 @@ sk_sp<SkData> SkPDFConvertType1FontStream(
|
|||||||
memcpy(resultTrailer, src + *headerLen + hexDataLen, *trailerLen);
|
memcpy(resultTrailer, src + *headerLen + hexDataLen, *trailerLen);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline static bool can_embed(const SkAdvancedTypefaceMetrics& metrics) {
|
||||||
|
return !SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static SkScalar from_font_units(SkScalar scaled, uint16_t emSize) {
|
||||||
|
return emSize == 1000 ? scaled : scaled * 1000 / emSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SkPDFIndirectReference make_type1_font_descriptor(SkPDFDocument* doc,
|
||||||
|
const SkTypeface* typeface,
|
||||||
|
const SkAdvancedTypefaceMetrics* info) {
|
||||||
|
SkPDFDict descriptor("FontDescriptor");
|
||||||
|
uint16_t emSize = SkToU16(typeface->getUnitsPerEm());
|
||||||
|
if (info) {
|
||||||
|
SkPDFFont::PopulateCommonFontDescriptor(&descriptor, *info, emSize, 0);
|
||||||
|
if (can_embed(*info)) {
|
||||||
|
int ttcIndex;
|
||||||
|
size_t header SK_INIT_TO_AVOID_WARNING;
|
||||||
|
size_t data SK_INIT_TO_AVOID_WARNING;
|
||||||
|
size_t trailer SK_INIT_TO_AVOID_WARNING;
|
||||||
|
std::unique_ptr<SkStreamAsset> rawFontData = typeface->openStream(&ttcIndex);
|
||||||
|
sk_sp<SkData> fontData = convert_type1_font_stream(std::move(rawFontData),
|
||||||
|
&header, &data, &trailer);
|
||||||
|
if (fontData) {
|
||||||
|
std::unique_ptr<SkPDFDict> dict = SkPDFMakeDict();
|
||||||
|
dict->insertInt("Length1", header);
|
||||||
|
dict->insertInt("Length2", data);
|
||||||
|
dict->insertInt("Length3", trailer);
|
||||||
|
auto fontStream = SkMemoryStream::Make(std::move(fontData));
|
||||||
|
descriptor.insertRef("FontFile", SkPDFStreamOut(std::move(dict),
|
||||||
|
std::move(fontStream), doc, true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return doc->emit(descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const std::vector<SkString>& type_1_glyphnames(SkPDFDocument* canon,
|
||||||
|
const SkTypeface* typeface) {
|
||||||
|
SkFontID fontID = typeface->uniqueID();
|
||||||
|
const std::vector<SkString>* glyphNames = canon->fType1GlyphNames.find(fontID);
|
||||||
|
if (!glyphNames) {
|
||||||
|
std::vector<SkString> names(typeface->countGlyphs());
|
||||||
|
SkPDFFont::GetType1GlyphNames(*typeface, names.data());
|
||||||
|
glyphNames = canon->fType1GlyphNames.set(fontID, std::move(names));
|
||||||
|
}
|
||||||
|
SkASSERT(glyphNames);
|
||||||
|
return *glyphNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SkPDFIndirectReference type1_font_descriptor(SkPDFDocument* doc,
|
||||||
|
const SkTypeface* typeface) {
|
||||||
|
SkFontID fontID = typeface->uniqueID();
|
||||||
|
if (SkPDFIndirectReference* ptr = doc->fFontDescriptors.find(fontID)) {
|
||||||
|
return *ptr;
|
||||||
|
}
|
||||||
|
const SkAdvancedTypefaceMetrics* info = SkPDFFont::GetMetrics(typeface, doc);
|
||||||
|
auto fontDescriptor = make_type1_font_descriptor(doc, typeface, info);
|
||||||
|
doc->fFontDescriptors.set(fontID, fontDescriptor);
|
||||||
|
return fontDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SkPDFEmitType1Font(const SkPDFFont& pdfFont, SkPDFDocument* doc) {
|
||||||
|
SkTypeface* typeface = pdfFont.typeface();
|
||||||
|
const std::vector<SkString> glyphNames = type_1_glyphnames(doc, typeface);
|
||||||
|
SkGlyphID firstGlyphID = pdfFont.firstGlyphID();
|
||||||
|
SkGlyphID lastGlyphID = pdfFont.lastGlyphID();
|
||||||
|
|
||||||
|
SkPDFDict font("Font");
|
||||||
|
font.insertRef("FontDescriptor", type1_font_descriptor(doc, typeface));
|
||||||
|
font.insertName("Subtype", "Type1");
|
||||||
|
if (const SkAdvancedTypefaceMetrics* info = SkPDFFont::GetMetrics(typeface, doc)) {
|
||||||
|
font.insertName("BaseFont", info->fPostScriptName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// glyphCount not including glyph 0
|
||||||
|
unsigned glyphCount = 1 + lastGlyphID - firstGlyphID;
|
||||||
|
SkASSERT(glyphCount > 0 && glyphCount <= 255);
|
||||||
|
font.insertInt("FirstChar", (size_t)0);
|
||||||
|
font.insertInt("LastChar", (size_t)glyphCount);
|
||||||
|
{
|
||||||
|
int emSize;
|
||||||
|
auto glyphCache = SkPDFFont::MakeVectorCache(typeface, &emSize);
|
||||||
|
auto widths = SkPDFMakeArray();
|
||||||
|
SkScalar advance = glyphCache->getGlyphIDAdvance(0).fAdvanceX;
|
||||||
|
widths->appendScalar(from_font_units(advance, SkToU16(emSize)));
|
||||||
|
for (unsigned gID = firstGlyphID; gID <= lastGlyphID; gID++) {
|
||||||
|
advance = glyphCache->getGlyphIDAdvance(gID).fAdvanceX;
|
||||||
|
widths->appendScalar(from_font_units(advance, SkToU16(emSize)));
|
||||||
|
}
|
||||||
|
font.insertObject("Widths", std::move(widths));
|
||||||
|
}
|
||||||
|
auto encDiffs = SkPDFMakeArray();
|
||||||
|
encDiffs->reserve(lastGlyphID - firstGlyphID + 3);
|
||||||
|
encDiffs->appendInt(0);
|
||||||
|
|
||||||
|
SkASSERT(glyphNames.size() > lastGlyphID);
|
||||||
|
const SkString unknown("UNKNOWN");
|
||||||
|
encDiffs->appendName(glyphNames[0].isEmpty() ? unknown : glyphNames[0]);
|
||||||
|
for (int gID = firstGlyphID; gID <= lastGlyphID; gID++) {
|
||||||
|
encDiffs->appendName(glyphNames[gID].isEmpty() ? unknown : glyphNames[gID]);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto encoding = SkPDFMakeDict("Encoding");
|
||||||
|
encoding->insertObject("Differences", std::move(encDiffs));
|
||||||
|
font.insertObject("Encoding", std::move(encoding));
|
||||||
|
|
||||||
|
doc->emit(font, pdfFont.indirectReference());
|
||||||
|
}
|
11
src/pdf/SkPDFType1Font.h
Normal file
11
src/pdf/SkPDFType1Font.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
// Copyright 2019 Google LLC.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
|
||||||
|
#ifndef SkPDFType1Font_DEFINED
|
||||||
|
#define SkPDFType1Font_DEFINED
|
||||||
|
|
||||||
|
#include "SkPDFDocumentPriv.h"
|
||||||
|
#include "SkPDFFont.h"
|
||||||
|
|
||||||
|
void SkPDFEmitType1Font(const SkPDFFont&, SkPDFDocument*);
|
||||||
|
|
||||||
|
#endif // SkPDFType1Font_DEFINED
|
Loading…
Reference in New Issue
Block a user