SkPDF: Stop using kHAdvance_PerGlyphInfo

SkPDFFont:
- never request kHAdvance_PerGlyphInfo from typeface.
- set_glyph_widths() fn uses a glyph cache to get advances.
- stop expecting vertical advances that are never requested.
- composeAdvanceData() now non-templated
- appendAdvance() one-line function removed

SkPDFDevice:
- use a glyph cache for getting repeated advances.
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2219733004

Review-Url: https://codereview.chromium.org/2219733004
This commit is contained in:
halcanary 2016-08-05 13:51:46 -07:00 committed by Commit bot
parent ae2964452b
commit 462d0148a5
3 changed files with 83 additions and 114 deletions

View File

@ -182,7 +182,6 @@ void SkAdvancedTypefaceMetrics::setGlyphWidths(
}
}
if (curRange.fStartId == lastIndex) {
SkASSERT(prevRange);
if (!prevRange) {
fGlyphWidths.reset();
return; // https://crbug.com/567031

View File

@ -1270,6 +1270,7 @@ void SkPDFDevice::drawPosText(const SkDraw& d, const void* text, size_t len,
const uint16_t* glyphIDs = nullptr;
size_t numGlyphs = force_glyph_encoding(paint, text, len, &storage, &glyphIDs);
textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
SkAutoGlyphCache autoGlyphCache(textPaint, nullptr, nullptr);
content.entry()->fContent.writeText("BT\n");
this->updateFont(textPaint, glyphIDs[0], content.entry());
@ -1280,6 +1281,7 @@ void SkPDFDevice::drawPosText(const SkDraw& d, const void* text, size_t len,
for (size_t i = 0; i < numGlyphs; i++) {
SkPDFFont* font = content.entry()->fState.fFont;
uint16_t encodedValue = glyphIDs[i];
SkScalar advanceWidth = autoGlyphCache->getGlyphIDAdvance(encodedValue).fAdvanceX;
if (font->glyphsToPDFFontEncoding(&encodedValue, 1) != 1) {
// The current pdf font cannot encode the current glyph.
// Try to get a pdf font which can encode the current glyph.
@ -1292,13 +1294,11 @@ void SkPDFDevice::drawPosText(const SkDraw& d, const void* text, size_t len,
continue;
}
}
fontGlyphUsage->noteGlyphUsage(font, &encodedValue, 1);
SkScalar x = offset.x() + pos[i * scalarsPerPos];
SkScalar y = offset.y() + (2 == scalarsPerPos ? pos[i * scalarsPerPos + 1] : 0);
align_text(textPaint, glyphIDs + i, 1, &x, &y);
SkScalar advanceWidth = textPaint.measureText(&encodedValue, sizeof(uint16_t));
glyphPositioner.writeGlyph(x, y, advanceWidth, encodedValue);
}
glyphPositioner.flush(); // Must flush before ending text object.

View File

@ -301,51 +301,33 @@ static sk_sp<SkPDFArray> makeFontBBox(SkIRect glyphBBox, uint16_t emSize) {
return bbox;
}
static void appendWidth(const int16_t& width, uint16_t emSize,
SkPDFArray* array) {
array->appendScalar(scaleFromFontUnits(width, emSize));
}
static void appendVerticalAdvance(
const SkAdvancedTypefaceMetrics::VerticalMetric& advance,
uint16_t emSize, SkPDFArray* array) {
appendWidth(advance.fVerticalAdvance, emSize, array);
appendWidth(advance.fOriginXDisp, emSize, array);
appendWidth(advance.fOriginYDisp, emSize, array);
}
template <typename Data>
SkPDFArray* composeAdvanceData(
const SkSinglyLinkedList<
SkAdvancedTypefaceMetrics::AdvanceMetric<Data>>& advanceInfo,
sk_sp<SkPDFArray> composeAdvanceData(
const SkSinglyLinkedList<SkAdvancedTypefaceMetrics::WidthRange>& advanceInfo,
uint16_t emSize,
void (*appendAdvance)(const Data& advance,
uint16_t emSize,
SkPDFArray* array),
Data* defaultAdvance) {
SkPDFArray* result = new SkPDFArray();
for (const SkAdvancedTypefaceMetrics::AdvanceMetric<Data>& range :
advanceInfo) {
int16_t* defaultAdvance) {
auto result = sk_make_sp<SkPDFArray>();
for (const SkAdvancedTypefaceMetrics::WidthRange& range : advanceInfo) {
switch (range.fType) {
case SkAdvancedTypefaceMetrics::AdvanceMetric<Data>::kDefault: {
case SkAdvancedTypefaceMetrics::WidthRange::kDefault: {
SkASSERT(range.fAdvance.count() == 1);
*defaultAdvance = range.fAdvance[0];
break;
}
case SkAdvancedTypefaceMetrics::AdvanceMetric<Data>::kRange: {
case SkAdvancedTypefaceMetrics::WidthRange::kRange: {
auto advanceArray = sk_make_sp<SkPDFArray>();
for (int j = 0; j < range.fAdvance.count(); j++)
appendAdvance(range.fAdvance[j], emSize,
advanceArray.get());
advanceArray->appendScalar(
scaleFromFontUnits(range.fAdvance[j], emSize));
result->appendInt(range.fStartId);
result->appendObject(std::move(advanceArray));
break;
}
case SkAdvancedTypefaceMetrics::AdvanceMetric<Data>::kRun: {
case SkAdvancedTypefaceMetrics::WidthRange::kRun: {
SkASSERT(range.fAdvance.count() == 1);
result->appendInt(range.fStartId);
result->appendInt(range.fEndId);
appendAdvance(range.fAdvance[0], emSize, result);
result->appendScalar(
scaleFromFontUnits(range.fAdvance[0], emSize));
break;
}
}
@ -493,7 +475,7 @@ static void append_bfrange_section(const SkTDArray<BFRange>& bfrange,
// one of them), the possible savings by aggressive optimization is 416KB
// pre-compressed and does not provide enough motivation for implementation.
// FIXME: this should be in a header so that it is separately testable
// TODO(halcanary): this should be in a header so that it is separately testable
// ( see caller in tests/ToUnicode.cpp )
void append_cmap_sections(const SkTDArray<SkUnichar>& glyphToUnicode,
const SkPDFGlyphSet* subset,
@ -733,26 +715,11 @@ SkPDFFont* SkPDFFont::GetFontResource(SkPDFCanon* canon,
return SkRef(relatedFont);
}
} else {
SkTypeface::PerGlyphInfo info;
info = SkTypeface::kGlyphNames_PerGlyphInfo;
info = SkTBitOr<SkTypeface::PerGlyphInfo>(
info, SkTypeface::kToUnicode_PerGlyphInfo);
#if !defined (SK_SFNTLY_SUBSETTER)
info = SkTBitOr<SkTypeface::PerGlyphInfo>(
info, SkTypeface::kHAdvance_PerGlyphInfo);
#endif
SkTypeface::PerGlyphInfo info =
SkTBitOr(SkTypeface::kGlyphNames_PerGlyphInfo,
SkTypeface::kToUnicode_PerGlyphInfo);
fontMetrics.reset(
typeface->getAdvancedTypefaceMetrics(info, nullptr, 0));
#if defined (SK_SFNTLY_SUBSETTER)
if (fontMetrics.get() &&
fontMetrics->fType != SkAdvancedTypefaceMetrics::kTrueType_Font) {
// Font does not support subsetting, get new info with advance.
info = SkTBitOr<SkTypeface::PerGlyphInfo>(
info, SkTypeface::kHAdvance_PerGlyphInfo);
fontMetrics.reset(
typeface->getAdvancedTypefaceMetrics(info, nullptr, 0));
}
#endif
}
SkPDFFont* font = SkPDFFont::Create(canon, fontMetrics.get(), typeface,
@ -1073,23 +1040,41 @@ bool SkPDFCIDFont::addFontDescriptor(int16_t defaultWidth,
return true;
}
void set_glyph_widths(SkTypeface* tf,
const SkTDArray<uint32_t>* glyphIDs,
SkAdvancedTypefaceMetrics* dst) {
SkPaint tmpPaint;
tmpPaint.setHinting(SkPaint::kNo_Hinting);
tmpPaint.setTypeface(sk_ref_sp(tf));
tmpPaint.setTextSize((SkScalar)tf->getUnitsPerEm());
SkAutoGlyphCache autoGlyphCache(tmpPaint, nullptr, nullptr);
SkGlyphCache* glyphCache = autoGlyphCache.get();
SkAdvancedTypefaceMetrics::GetAdvance advanceFn =
[glyphCache](int gid, int16_t* advance) {
*advance = (int16_t)glyphCache->getGlyphIDAdvance(gid).fAdvanceX;
return true;
};
if (!glyphIDs || glyphIDs->isEmpty()) {
dst->setGlyphWidths(tf->countGlyphs(), nullptr, 0, advanceFn);
} else {
dst->setGlyphWidths(tf->countGlyphs(),
glyphIDs->begin(),
glyphIDs->count(), advanceFn);
}
}
bool SkPDFCIDFont::populate(const SkPDFGlyphSet* subset) {
// Generate new font metrics with advance info for true type fonts.
if (fontInfo()->fType == SkAdvancedTypefaceMetrics::kTrueType_Font) {
// Generate glyph id array.
SkTDArray<uint32_t> glyphIDs;
if (subset) {
// Always include glyph 0.
if (!subset->has(0)) {
glyphIDs.push(0);
}
subset->exportTo(&glyphIDs);
// Generate glyph id array.
SkTDArray<uint32_t> glyphIDs;
if (subset) {
if (!subset->has(0)) {
glyphIDs.push(0); // Always include glyph 0.
}
SkTypeface::PerGlyphInfo info;
info = SkTypeface::kGlyphNames_PerGlyphInfo;
info = SkTBitOr<SkTypeface::PerGlyphInfo>(
info, SkTypeface::kHAdvance_PerGlyphInfo);
subset->exportTo(&glyphIDs);
}
if (fontInfo()->fType == SkAdvancedTypefaceMetrics::kTrueType_Font) {
SkTypeface::PerGlyphInfo info = SkTypeface::kGlyphNames_PerGlyphInfo;
uint32_t* glyphs = (glyphIDs.count() == 0) ? nullptr : glyphIDs.begin();
uint32_t glyphsCount = glyphs ? glyphIDs.count() : 0;
sk_sp<const SkAdvancedTypefaceMetrics> fontMetrics(
@ -1118,38 +1103,18 @@ bool SkPDFCIDFont::populate(const SkPDFGlyphSet* subset) {
sysInfo->insertInt("Supplement", 0);
this->insertObject("CIDSystemInfo", std::move(sysInfo));
if (!fontInfo()->fGlyphWidths.empty()) {
int16_t defaultWidth = 0;
sk_sp<SkPDFArray> widths(composeAdvanceData(
fontInfo()->fGlyphWidths, fontInfo()->fEmSize, &appendWidth,
&defaultWidth));
if (widths->size()) {
this->insertObject("W", std::move(widths));
}
this->insertScalar(
"DW", scaleFromFontUnits(defaultWidth, fontInfo()->fEmSize));
}
if (!fontInfo()->fVerticalMetrics.empty()) {
struct SkAdvancedTypefaceMetrics::VerticalMetric defaultAdvance;
defaultAdvance.fVerticalAdvance = 0;
defaultAdvance.fOriginXDisp = 0;
defaultAdvance.fOriginYDisp = 0;
sk_sp<SkPDFArray> advances(composeAdvanceData(
fontInfo()->fVerticalMetrics, fontInfo()->fEmSize,
&appendVerticalAdvance, &defaultAdvance));
if (advances->size())
this->insertObject("W2", std::move(advances));
if (defaultAdvance.fVerticalAdvance ||
defaultAdvance.fOriginXDisp ||
defaultAdvance.fOriginYDisp) {
auto array = sk_make_sp<SkPDFArray>();
appendVerticalAdvance(defaultAdvance,
fontInfo()->fEmSize,
array.get());
this->insertObject("DW2", std::move(array));
}
SkAdvancedTypefaceMetrics tmpMetrics;
set_glyph_widths(this->typeface(), &glyphIDs, &tmpMetrics);
int16_t defaultWidth = 0;
uint16_t emSize = (uint16_t)this->fontInfo()->fEmSize;
sk_sp<SkPDFArray> widths = composeAdvanceData(
tmpMetrics.fGlyphWidths, emSize, &defaultWidth);
if (widths->size()) {
this->insertObject("W", std::move(widths));
}
this->insertScalar(
"DW", scaleFromFontUnits(defaultWidth, emSize));
return true;
}
@ -1205,24 +1170,28 @@ bool SkPDFType1Font::addFontDescriptor(int16_t defaultWidth) {
bool SkPDFType1Font::populate(int16_t glyphID) {
SkASSERT(fontInfo()->fVerticalMetrics.empty());
SkASSERT(!fontInfo()->fGlyphWidths.empty());
SkASSERT(fontInfo()->fGlyphWidths.empty());
adjustGlyphRangeForSingleByteEncoding(glyphID);
int16_t defaultWidth = 0;
const SkAdvancedTypefaceMetrics::WidthRange* widthRangeEntry = nullptr;
for (const auto& widthEntry : fontInfo()->fGlyphWidths) {
switch (widthEntry.fType) {
case SkAdvancedTypefaceMetrics::WidthRange::kDefault:
defaultWidth = widthEntry.fAdvance[0];
break;
case SkAdvancedTypefaceMetrics::WidthRange::kRun:
SkASSERT(false);
break;
case SkAdvancedTypefaceMetrics::WidthRange::kRange:
SkASSERT(widthRangeEntry == nullptr);
widthRangeEntry = &widthEntry;
break;
{
SkAdvancedTypefaceMetrics tmpMetrics;
set_glyph_widths(this->typeface(), nullptr, &tmpMetrics);
for (const auto& widthEntry : tmpMetrics.fGlyphWidths) {
switch (widthEntry.fType) {
case SkAdvancedTypefaceMetrics::WidthRange::kDefault:
defaultWidth = widthEntry.fAdvance[0];
break;
case SkAdvancedTypefaceMetrics::WidthRange::kRun:
SkASSERT(false);
break;
case SkAdvancedTypefaceMetrics::WidthRange::kRange:
SkASSERT(widthRangeEntry == nullptr);
widthRangeEntry = &widthEntry;
break;
}
}
}
@ -1234,8 +1203,6 @@ bool SkPDFType1Font::populate(int16_t glyphID) {
insertName("BaseFont", fontInfo()->fFontName);
addWidthInfoFromRange(defaultWidth, widthRangeEntry);
auto encDiffs = sk_make_sp<SkPDFArray>();
encDiffs->reserve(lastGlyphID() - firstGlyphID() + 2);
encDiffs->appendInt(1);
@ -1263,15 +1230,18 @@ void SkPDFType1Font::addWidthInfoFromRange(
if (endIndex > widthRangeEntry->fAdvance.count())
endIndex = widthRangeEntry->fAdvance.count();
if (widthRangeEntry->fStartId == 0) {
appendWidth(widthRangeEntry->fAdvance[0], emSize, widthArray.get());
widthArray->appendScalar(
scaleFromFontUnits(widthRangeEntry->fAdvance[0], emSize));
} else {
firstChar = startIndex + widthRangeEntry->fStartId;
}
for (int i = startIndex; i < endIndex; i++) {
appendWidth(widthRangeEntry->fAdvance[i], emSize, widthArray.get());
widthArray->appendScalar(
scaleFromFontUnits(widthRangeEntry->fAdvance[i], emSize));
}
} else {
appendWidth(defaultWidth, 1000, widthArray.get());
widthArray->appendScalar(
scaleFromFontUnits(defaultWidth, 1000));
}
this->insertInt("FirstChar", firstChar);
this->insertInt("LastChar", firstChar + widthArray->size() - 1);