SkPDF/SkAdvancedTypefaceMetrics: simplify ATM, PDF takes over
No public API changes.
TBR=reed@google.com
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2222523003
Review-Url: https://codereview.chromium.org/2222523003
diff --git a/gyp/core.gypi b/gyp/core.gypi
index 76ed86b..13b7ef6 100644
--- a/gyp/core.gypi
+++ b/gyp/core.gypi
@@ -18,7 +18,6 @@
'<(skia_src_path)/core/Sk4px.h',
'<(skia_src_path)/core/SkAAClip.cpp',
'<(skia_src_path)/core/SkAnnotation.cpp',
- '<(skia_src_path)/core/SkAdvancedTypefaceMetrics.cpp',
'<(skia_src_path)/core/SkAdvancedTypefaceMetrics.h',
'<(skia_src_path)/core/SkAlphaRuns.cpp',
'<(skia_src_path)/core/SkAntiRun.h',
diff --git a/include/core/SkTypeface.h b/include/core/SkTypeface.h
index 83008d3..30a0903 100644
--- a/include/core/SkTypeface.h
+++ b/include/core/SkTypeface.h
@@ -332,11 +332,9 @@
// The type of advance data wanted.
enum PerGlyphInfo {
kNo_PerGlyphInfo = 0x0, // Don't populate any per glyph info.
- kHAdvance_PerGlyphInfo = 0x1, // Populate horizontal advance data.
- kVAdvance_PerGlyphInfo = 0x2, // Populate vertical advance data.
- kGlyphNames_PerGlyphInfo = 0x4, // Populate glyph names (Type 1 only).
- kToUnicode_PerGlyphInfo = 0x8 // Populate ToUnicode table, ignored
- // for Type 1 fonts
+ kGlyphNames_PerGlyphInfo = 0x1, // Populate glyph names (Type 1 only).
+ kToUnicode_PerGlyphInfo = 0x2 // Populate ToUnicode table, ignored
+ // for Type 1 fonts
};
/** uniqueID must be unique and non-zero
diff --git a/src/core/SkAdvancedTypefaceMetrics.cpp b/src/core/SkAdvancedTypefaceMetrics.cpp
deleted file mode 100644
index bddd912..0000000
--- a/src/core/SkAdvancedTypefaceMetrics.cpp
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-
-#include "SkAdvancedTypefaceMetrics.h"
-#include "SkTypes.h"
-
-SkAdvancedTypefaceMetrics::~SkAdvancedTypefaceMetrics() {}
-
-const int16_t kInvalidAdvance = SK_MinS16;
-const int16_t kDontCareAdvance = SK_MinS16 + 1;
-
-static void stripUninterestingTrailingAdvancesFromRange(
- SkAdvancedTypefaceMetrics::WidthRange* range) {
- SkASSERT(range);
-
- int expectedAdvanceCount = range->fEndId - range->fStartId + 1;
- if (range->fAdvance.count() < expectedAdvanceCount) {
- return;
- }
-
- for (int i = expectedAdvanceCount - 1; i >= 0; --i) {
- if (range->fAdvance[i] != kDontCareAdvance &&
- range->fAdvance[i] != kInvalidAdvance &&
- range->fAdvance[i] != 0) {
- range->fEndId = range->fStartId + i;
- break;
- }
- }
-}
-
-static void zeroWildcardsInRange(SkAdvancedTypefaceMetrics::WidthRange* range) {
- SkASSERT(range);
- if (range->fType != SkAdvancedTypefaceMetrics::WidthRange::kRange) {
- return;
- }
- SkASSERT(range->fAdvance.count() == range->fEndId - range->fStartId + 1);
-
- // Zero out wildcards.
- for (int i = 0; i < range->fAdvance.count(); ++i) {
- if (range->fAdvance[i] == kDontCareAdvance) {
- range->fAdvance[i] = 0;
- }
- }
-}
-
-void SkAdvancedTypefaceMetrics::FinishRange(
- SkAdvancedTypefaceMetrics::WidthRange* range,
- int endId,
- SkAdvancedTypefaceMetrics::WidthRange::MetricType type) {
- range->fEndId = endId;
- range->fType = type;
- stripUninterestingTrailingAdvancesFromRange(range);
- int newLength;
- if (type == SkAdvancedTypefaceMetrics::WidthRange::kRange) {
- newLength = range->fEndId - range->fStartId + 1;
- } else {
- if (range->fEndId == range->fStartId) {
- range->fType = SkAdvancedTypefaceMetrics::WidthRange::kRange;
- }
- newLength = 1;
- }
- SkASSERT(range->fAdvance.count() >= newLength);
- range->fAdvance.setCount(newLength);
- zeroWildcardsInRange(range);
-}
-
-void SkAdvancedTypefaceMetrics::setGlyphWidths(
- int num_glyphs,
- const uint32_t* subsetGlyphIDs,
- uint32_t subsetGlyphIDsLength,
- SkAdvancedTypefaceMetrics::GetAdvance getAdvance) {
- // Assuming that on average, the ASCII representation of an advance plus
- // a space is 8 characters and the ASCII representation of a glyph id is 3
- // characters, then the following cut offs for using different range types
- // apply:
- // The cost of stopping and starting the range is 7 characers
- // a. Removing 4 0's or don't care's is a win
- // The cost of stopping and starting the range plus a run is 22
- // characters
- // b. Removing 3 repeating advances is a win
- // c. Removing 2 repeating advances and 3 don't cares is a win
- // When not currently in a range the cost of a run over a range is 16
- // characaters, so:
- // d. Removing a leading 0/don't cares is a win because it is omitted
- // e. Removing 2 repeating advances is a win
-
- WidthRange* prevRange = nullptr;
- int16_t lastAdvance = kInvalidAdvance;
- int repeatedAdvances = 0;
- int wildCardsInRun = 0;
- int trailingWildCards = 0;
- uint32_t subsetIndex = 0;
-
- // Limit the loop count to glyph id ranges provided.
- int firstIndex = 0;
- int lastIndex = num_glyphs;
- if (subsetGlyphIDs) {
- firstIndex = static_cast<int>(subsetGlyphIDs[0]);
- lastIndex =
- static_cast<int>(subsetGlyphIDs[subsetGlyphIDsLength - 1]) + 1;
- }
- WidthRange curRange(firstIndex);
-
- for (int gId = firstIndex; gId <= lastIndex; gId++) {
- int16_t advance = kInvalidAdvance;
- if (gId < lastIndex) {
- // Get glyph id only when subset is nullptr, or the id is in subset.
- SkASSERT(!subsetGlyphIDs || (subsetIndex < subsetGlyphIDsLength &&
- static_cast<uint32_t>(gId) <= subsetGlyphIDs[subsetIndex]));
- if (!subsetGlyphIDs ||
- (subsetIndex < subsetGlyphIDsLength &&
- static_cast<uint32_t>(gId) == subsetGlyphIDs[subsetIndex])) {
- SkAssertResult(getAdvance(gId, &advance));
- ++subsetIndex;
- } else {
- advance = kDontCareAdvance;
- }
- }
- if (advance == lastAdvance) {
- repeatedAdvances++;
- trailingWildCards = 0;
- } else if (advance == kDontCareAdvance) {
- wildCardsInRun++;
- trailingWildCards++;
- } else if (curRange.fAdvance.count() ==
- repeatedAdvances + 1 + wildCardsInRun) { // All in run.
- if (lastAdvance == 0) {
- curRange.fStartId = gId; // reset
- curRange.fAdvance.setCount(0);
- trailingWildCards = 0;
- } else if (repeatedAdvances + 1 >= 2 || trailingWildCards >= 4) {
- FinishRange(&curRange, gId - 1, WidthRange::kRun);
- prevRange = fGlyphWidths.emplace_back(std::move(curRange));
- curRange = WidthRange(gId);
- trailingWildCards = 0;
- }
- repeatedAdvances = 0;
- wildCardsInRun = trailingWildCards;
- trailingWildCards = 0;
- } else {
- if (lastAdvance == 0 &&
- repeatedAdvances + 1 + wildCardsInRun >= 4) {
- FinishRange(&curRange,
- gId - repeatedAdvances - wildCardsInRun - 2,
- WidthRange::kRange);
- prevRange = fGlyphWidths.emplace_back(std::move(curRange));
- curRange = WidthRange(gId);
- trailingWildCards = 0;
- } else if (trailingWildCards >= 4 && repeatedAdvances + 1 < 2) {
- FinishRange(&curRange, gId - trailingWildCards - 1,
- WidthRange::kRange);
- prevRange = fGlyphWidths.emplace_back(std::move(curRange));
- curRange = WidthRange(gId);
- trailingWildCards = 0;
- } else if (lastAdvance != 0 &&
- (repeatedAdvances + 1 >= 3 ||
- (repeatedAdvances + 1 >= 2 && wildCardsInRun >= 3))) {
- FinishRange(&curRange,
- gId - repeatedAdvances - wildCardsInRun - 2,
- WidthRange::kRange);
- (void)fGlyphWidths.emplace_back(std::move(curRange));
- curRange =
- WidthRange(gId - repeatedAdvances - wildCardsInRun - 1);
- curRange.fAdvance.append(1, &lastAdvance);
- FinishRange(&curRange, gId - 1, WidthRange::kRun);
- prevRange = fGlyphWidths.emplace_back(std::move(curRange));
- curRange = WidthRange(gId);
- trailingWildCards = 0;
- }
- repeatedAdvances = 0;
- wildCardsInRun = trailingWildCards;
- trailingWildCards = 0;
- }
- curRange.fAdvance.append(1, &advance);
- if (advance != kDontCareAdvance) {
- lastAdvance = advance;
- }
- }
- if (curRange.fStartId == lastIndex) {
- if (!prevRange) {
- fGlyphWidths.reset();
- return; // https://crbug.com/567031
- }
- } else {
- FinishRange(&curRange, lastIndex - 1, WidthRange::kRange);
- fGlyphWidths.emplace_back(std::move(curRange));
- }
-}
diff --git a/src/core/SkAdvancedTypefaceMetrics.h b/src/core/SkAdvancedTypefaceMetrics.h
index 6dc1162..1b490e0 100644
--- a/src/core/SkAdvancedTypefaceMetrics.h
+++ b/src/core/SkAdvancedTypefaceMetrics.h
@@ -39,27 +39,7 @@
, fCapHeight(0)
, fBBox(SkIRect::MakeEmpty()) {}
- ~SkAdvancedTypefaceMetrics();
-
- /** Retrieve advance data for glyphs. Used by the PDF backend. It
- calls underlying platform dependent API getAdvance to acquire
- the data.
- @param num_glyphs Total number of glyphs in the given font.
- @param glyphIDs For per-glyph info, specify subset of the
- font by giving glyph ids. Each integer
- represents a glyph id. Passing nullptr
- means all glyphs in the font.
- @param glyphIDsCount Number of elements in subsetGlyphIds.
- Ignored if glyphIDs is nullptr.
- @param getAdvance A function that takes a glyph id and
- passes back advance data from the
- typeface. Returns false on failure.
- */
- typedef std::function<bool(int glyphId, int16_t* advanceData)> GetAdvance;
- void setGlyphWidths(int num_glyphs,
- const uint32_t* subsetGlyphIDs,
- uint32_t subsetGlyphIDsLength,
- GetAdvance getAdvance);
+ ~SkAdvancedTypefaceMetrics() {}
SkString fFontName;
@@ -108,48 +88,13 @@
SkIRect fBBox; // The bounding box of all glyphs (in font units).
- template <typename Data>
- struct AdvanceMetric {
- enum MetricType {
- kDefault, // Default advance: fAdvance.count = 1
- kRange, // Advances for a range: fAdvance.count = fEndID-fStartID
- kRun // fStartID-fEndID have same advance: fAdvance.count = 1
- };
- MetricType fType;
- uint16_t fStartId;
- uint16_t fEndId;
- SkTDArray<Data> fAdvance;
- AdvanceMetric(uint16_t startId) : fStartId(startId) {}
- AdvanceMetric(AdvanceMetric&& other) = default;
- AdvanceMetric& operator=(AdvanceMetric&& other) = default;
- AdvanceMetric(const AdvanceMetric&) = delete;
- AdvanceMetric& operator=(const AdvanceMetric&) = delete;
- };
-
- struct VerticalMetric {
- int16_t fVerticalAdvance;
- int16_t fOriginXDisp; // Horiz. displacement of the secondary origin.
- int16_t fOriginYDisp; // Vert. displacement of the secondary origin.
- };
- typedef AdvanceMetric<int16_t> WidthRange;
- typedef AdvanceMetric<VerticalMetric> VerticalAdvanceRange;
-
- // This is indexed by glyph id.
- SkSinglyLinkedList<WidthRange> fGlyphWidths;
- // Only used for Vertical CID fonts.
- SkSinglyLinkedList<VerticalAdvanceRange> fVerticalMetrics;
-
// The names of each glyph, only populated for postscript fonts.
- SkAutoTDelete<SkAutoTArray<SkString> > fGlyphNames;
+ SkTArray<SkString> fGlyphNames;
// The mapping from glyph to Unicode, only populated if
// kToUnicode_PerGlyphInfo is passed to GetAdvancedTypefaceMetrics.
SkTDArray<SkUnichar> fGlyphToUnicode;
- static void FinishRange(WidthRange* range,
- int endId,
- WidthRange::MetricType type);
-
private:
typedef SkRefCnt INHERITED;
};
diff --git a/src/pdf/SkPDFFont.cpp b/src/pdf/SkPDFFont.cpp
index db687fb..093ad4a 100644
--- a/src/pdf/SkPDFFont.cpp
+++ b/src/pdf/SkPDFFont.cpp
@@ -36,12 +36,230 @@
// non-symbolic, so always call it symbolic. (PDF 1.4 spec, section 5.7.1)
static const int kPdfSymbolic = 4;
+struct AdvanceMetric {
+ enum MetricType {
+ kDefault, // Default advance: fAdvance.count = 1
+ kRange, // Advances for a range: fAdvance.count = fEndID-fStartID
+ kRun // fStartID-fEndID have same advance: fAdvance.count = 1
+ };
+ MetricType fType;
+ uint16_t fStartId;
+ uint16_t fEndId;
+ SkTDArray<int16_t> fAdvance;
+ AdvanceMetric(uint16_t startId) : fStartId(startId) {}
+ AdvanceMetric(AdvanceMetric&&) = default;
+ AdvanceMetric& operator=(AdvanceMetric&& other) = default;
+ AdvanceMetric(const AdvanceMetric&) = delete;
+ AdvanceMetric& operator=(const AdvanceMetric&) = delete;
+};
+
namespace {
///////////////////////////////////////////////////////////////////////////////
// File-Local Functions
///////////////////////////////////////////////////////////////////////////////
+const int16_t kInvalidAdvance = SK_MinS16;
+const int16_t kDontCareAdvance = SK_MinS16 + 1;
+
+static void stripUninterestingTrailingAdvancesFromRange(
+ AdvanceMetric* range) {
+ SkASSERT(range);
+
+ int expectedAdvanceCount = range->fEndId - range->fStartId + 1;
+ if (range->fAdvance.count() < expectedAdvanceCount) {
+ return;
+ }
+
+ for (int i = expectedAdvanceCount - 1; i >= 0; --i) {
+ if (range->fAdvance[i] != kDontCareAdvance &&
+ range->fAdvance[i] != kInvalidAdvance &&
+ range->fAdvance[i] != 0) {
+ range->fEndId = range->fStartId + i;
+ break;
+ }
+ }
+}
+
+static void zeroWildcardsInRange(AdvanceMetric* range) {
+ SkASSERT(range);
+ if (range->fType != AdvanceMetric::kRange) {
+ return;
+ }
+ SkASSERT(range->fAdvance.count() == range->fEndId - range->fStartId + 1);
+
+ // Zero out wildcards.
+ for (int i = 0; i < range->fAdvance.count(); ++i) {
+ if (range->fAdvance[i] == kDontCareAdvance) {
+ range->fAdvance[i] = 0;
+ }
+ }
+}
+
+static void FinishRange(
+ AdvanceMetric* range,
+ int endId,
+ AdvanceMetric::MetricType type) {
+ range->fEndId = endId;
+ range->fType = type;
+ stripUninterestingTrailingAdvancesFromRange(range);
+ int newLength;
+ if (type == AdvanceMetric::kRange) {
+ newLength = range->fEndId - range->fStartId + 1;
+ } else {
+ if (range->fEndId == range->fStartId) {
+ range->fType = AdvanceMetric::kRange;
+ }
+ newLength = 1;
+ }
+ SkASSERT(range->fAdvance.count() >= newLength);
+ range->fAdvance.setCount(newLength);
+ zeroWildcardsInRange(range);
+}
+
+
+/** Retrieve advance data for glyphs. Used by the PDF backend.
+ @param num_glyphs Total number of glyphs in the given font.
+ @param glyphIDs For per-glyph info, specify subset of the
+ font by giving glyph ids. Each integer
+ represents a glyph id. Passing nullptr
+ means all glyphs in the font.
+ @param glyphIDsCount Number of elements in subsetGlyphIds.
+ Ignored if glyphIDs is nullptr.
+*/
+// TODO(halcanary): this function is complex enough to need its logic
+// tested with unit tests. On the other hand, I want to do another
+// round of re-factoring before figuring out how to mock this.
+// TODO(halcanary): this function should be combined with
+// composeAdvanceData() so that we don't need to produce a linked list
+// of intermediate values. Or we could make the intermediate value
+// something other than a linked list.
+static void get_glyph_widths(SkSinglyLinkedList<AdvanceMetric>* glyphWidths,
+ int num_glyphs,
+ const uint32_t* subsetGlyphIDs,
+ uint32_t subsetGlyphIDsLength,
+ SkGlyphCache* glyphCache) {
+ // Assuming that on average, the ASCII representation of an advance plus
+ // a space is 8 characters and the ASCII representation of a glyph id is 3
+ // characters, then the following cut offs for using different range types
+ // apply:
+ // The cost of stopping and starting the range is 7 characers
+ // a. Removing 4 0's or don't care's is a win
+ // The cost of stopping and starting the range plus a run is 22
+ // characters
+ // b. Removing 3 repeating advances is a win
+ // c. Removing 2 repeating advances and 3 don't cares is a win
+ // When not currently in a range the cost of a run over a range is 16
+ // characaters, so:
+ // d. Removing a leading 0/don't cares is a win because it is omitted
+ // e. Removing 2 repeating advances is a win
+
+ AdvanceMetric* prevRange = nullptr;
+ int16_t lastAdvance = kInvalidAdvance;
+ int repeatedAdvances = 0;
+ int wildCardsInRun = 0;
+ int trailingWildCards = 0;
+ uint32_t subsetIndex = 0;
+
+ // Limit the loop count to glyph id ranges provided.
+ int firstIndex = 0;
+ int lastIndex = num_glyphs;
+ if (subsetGlyphIDs) {
+ firstIndex = static_cast<int>(subsetGlyphIDs[0]);
+ lastIndex =
+ static_cast<int>(subsetGlyphIDs[subsetGlyphIDsLength - 1]) + 1;
+ }
+ AdvanceMetric curRange(firstIndex);
+
+ for (int gId = firstIndex; gId <= lastIndex; gId++) {
+ int16_t advance = kInvalidAdvance;
+ if (gId < lastIndex) {
+ // Get glyph id only when subset is nullptr, or the id is in subset.
+ SkASSERT(!subsetGlyphIDs || (subsetIndex < subsetGlyphIDsLength &&
+ static_cast<uint32_t>(gId) <= subsetGlyphIDs[subsetIndex]));
+ if (!subsetGlyphIDs ||
+ (subsetIndex < subsetGlyphIDsLength &&
+ static_cast<uint32_t>(gId) == subsetGlyphIDs[subsetIndex])) {
+ advance = (int16_t)glyphCache->getGlyphIDAdvance(gId).fAdvanceX;
+ ++subsetIndex;
+ } else {
+ advance = kDontCareAdvance;
+ }
+ }
+ if (advance == lastAdvance) {
+ repeatedAdvances++;
+ trailingWildCards = 0;
+ } else if (advance == kDontCareAdvance) {
+ wildCardsInRun++;
+ trailingWildCards++;
+ } else if (curRange.fAdvance.count() ==
+ repeatedAdvances + 1 + wildCardsInRun) { // All in run.
+ if (lastAdvance == 0) {
+ curRange.fStartId = gId; // reset
+ curRange.fAdvance.setCount(0);
+ trailingWildCards = 0;
+ } else if (repeatedAdvances + 1 >= 2 || trailingWildCards >= 4) {
+ FinishRange(&curRange, gId - 1, AdvanceMetric::kRun);
+ prevRange = glyphWidths->emplace_back(std::move(curRange));
+ curRange = AdvanceMetric(gId);
+ trailingWildCards = 0;
+ }
+ repeatedAdvances = 0;
+ wildCardsInRun = trailingWildCards;
+ trailingWildCards = 0;
+ } else {
+ if (lastAdvance == 0 &&
+ repeatedAdvances + 1 + wildCardsInRun >= 4) {
+ FinishRange(&curRange,
+ gId - repeatedAdvances - wildCardsInRun - 2,
+ AdvanceMetric::kRange);
+ prevRange = glyphWidths->emplace_back(std::move(curRange));
+ curRange = AdvanceMetric(gId);
+ trailingWildCards = 0;
+ } else if (trailingWildCards >= 4 && repeatedAdvances + 1 < 2) {
+ FinishRange(&curRange, gId - trailingWildCards - 1,
+ AdvanceMetric::kRange);
+ prevRange = glyphWidths->emplace_back(std::move(curRange));
+ curRange = AdvanceMetric(gId);
+ trailingWildCards = 0;
+ } else if (lastAdvance != 0 &&
+ (repeatedAdvances + 1 >= 3 ||
+ (repeatedAdvances + 1 >= 2 && wildCardsInRun >= 3))) {
+ FinishRange(&curRange,
+ gId - repeatedAdvances - wildCardsInRun - 2,
+ AdvanceMetric::kRange);
+ (void)glyphWidths->emplace_back(std::move(curRange));
+ curRange =
+ AdvanceMetric(gId - repeatedAdvances - wildCardsInRun - 1);
+ curRange.fAdvance.append(1, &lastAdvance);
+ FinishRange(&curRange, gId - 1, AdvanceMetric::kRun);
+ prevRange = glyphWidths->emplace_back(std::move(curRange));
+ curRange = AdvanceMetric(gId);
+ trailingWildCards = 0;
+ }
+ repeatedAdvances = 0;
+ wildCardsInRun = trailingWildCards;
+ trailingWildCards = 0;
+ }
+ curRange.fAdvance.append(1, &advance);
+ if (advance != kDontCareAdvance) {
+ lastAdvance = advance;
+ }
+ }
+ if (curRange.fStartId == lastIndex) {
+ if (!prevRange) {
+ glyphWidths->reset();
+ return; // https://crbug.com/567031
+ }
+ } else {
+ FinishRange(&curRange, lastIndex - 1, AdvanceMetric::kRange);
+ glyphWidths->emplace_back(std::move(curRange));
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+
bool parsePFBSection(const uint8_t** src, size_t* len, int sectionType,
size_t* size) {
// PFB sections have a two or six bytes header. 0x80 and a one byte
@@ -302,18 +520,18 @@
}
sk_sp<SkPDFArray> composeAdvanceData(
- const SkSinglyLinkedList<SkAdvancedTypefaceMetrics::WidthRange>& advanceInfo,
+ const SkSinglyLinkedList<AdvanceMetric>& advanceInfo,
uint16_t emSize,
int16_t* defaultAdvance) {
auto result = sk_make_sp<SkPDFArray>();
- for (const SkAdvancedTypefaceMetrics::WidthRange& range : advanceInfo) {
+ for (const AdvanceMetric& range : advanceInfo) {
switch (range.fType) {
- case SkAdvancedTypefaceMetrics::WidthRange::kDefault: {
+ case AdvanceMetric::kDefault: {
SkASSERT(range.fAdvance.count() == 1);
*defaultAdvance = range.fAdvance[0];
break;
}
- case SkAdvancedTypefaceMetrics::WidthRange::kRange: {
+ case AdvanceMetric::kRange: {
auto advanceArray = sk_make_sp<SkPDFArray>();
for (int j = 0; j < range.fAdvance.count(); j++)
advanceArray->appendScalar(
@@ -322,7 +540,7 @@
result->appendObject(std::move(advanceArray));
break;
}
- case SkAdvancedTypefaceMetrics::WidthRange::kRun: {
+ case AdvanceMetric::kRun: {
SkASSERT(range.fAdvance.count() == 1);
result->appendInt(range.fStartId);
result->appendInt(range.fEndId);
@@ -1042,24 +1260,17 @@
void set_glyph_widths(SkTypeface* tf,
const SkTDArray<uint32_t>* glyphIDs,
- SkAdvancedTypefaceMetrics* dst) {
+ SkSinglyLinkedList<AdvanceMetric>* 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);
+ get_glyph_widths(dst, tf->countGlyphs(), nullptr, 0, autoGlyphCache.get());
} else {
- dst->setGlyphWidths(tf->countGlyphs(),
- glyphIDs->begin(),
- glyphIDs->count(), advanceFn);
+ get_glyph_widths(dst, tf->countGlyphs(), glyphIDs->begin(),
+ glyphIDs->count(), autoGlyphCache.get());
}
}
@@ -1103,12 +1314,11 @@
sysInfo->insertInt("Supplement", 0);
this->insertObject("CIDSystemInfo", std::move(sysInfo));
- SkAdvancedTypefaceMetrics tmpMetrics;
+ SkSinglyLinkedList<AdvanceMetric> 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);
+ sk_sp<SkPDFArray> widths = composeAdvanceData(tmpMetrics, emSize, &defaultWidth);
if (widths->size()) {
this->insertObject("W", std::move(widths));
}
@@ -1169,25 +1379,22 @@
}
bool SkPDFType1Font::populate(int16_t glyphID) {
- SkASSERT(fontInfo()->fVerticalMetrics.empty());
- SkASSERT(fontInfo()->fGlyphWidths.empty());
-
adjustGlyphRangeForSingleByteEncoding(glyphID);
int16_t defaultWidth = 0;
- const SkAdvancedTypefaceMetrics::WidthRange* widthRangeEntry = nullptr;
+ const AdvanceMetric* widthRangeEntry = nullptr;
{
- SkAdvancedTypefaceMetrics tmpMetrics;
+ SkSinglyLinkedList<AdvanceMetric> tmpMetrics;
set_glyph_widths(this->typeface(), nullptr, &tmpMetrics);
- for (const auto& widthEntry : tmpMetrics.fGlyphWidths) {
+ for (const auto& widthEntry : tmpMetrics) {
switch (widthEntry.fType) {
- case SkAdvancedTypefaceMetrics::WidthRange::kDefault:
+ case AdvanceMetric::kDefault:
defaultWidth = widthEntry.fAdvance[0];
break;
- case SkAdvancedTypefaceMetrics::WidthRange::kRun:
+ case AdvanceMetric::kRun:
SkASSERT(false);
break;
- case SkAdvancedTypefaceMetrics::WidthRange::kRange:
+ case AdvanceMetric::kRange:
SkASSERT(widthRangeEntry == nullptr);
widthRangeEntry = &widthEntry;
break;
@@ -1206,8 +1413,9 @@
auto encDiffs = sk_make_sp<SkPDFArray>();
encDiffs->reserve(lastGlyphID() - firstGlyphID() + 2);
encDiffs->appendInt(1);
+ SkASSERT(this->fontInfo()->fGlyphNames.count() >= this->lastGlyphID());
for (int gID = firstGlyphID(); gID <= lastGlyphID(); gID++) {
- encDiffs->appendName(fontInfo()->fGlyphNames->get()[gID].c_str());
+ encDiffs->appendName(fontInfo()->fGlyphNames[gID].c_str());
}
auto encoding = sk_make_sp<SkPDFDict>("Encoding");
@@ -1218,7 +1426,7 @@
void SkPDFType1Font::addWidthInfoFromRange(
int16_t defaultWidth,
- const SkAdvancedTypefaceMetrics::WidthRange* widthRangeEntry) {
+ const AdvanceMetric* widthRangeEntry) {
auto widthArray = sk_make_sp<SkPDFArray>();
int firstChar = 0;
if (widthRangeEntry) {
diff --git a/src/pdf/SkPDFFontImpl.h b/src/pdf/SkPDFFontImpl.h
index 0dfa191..05774de 100644
--- a/src/pdf/SkPDFFontImpl.h
+++ b/src/pdf/SkPDFFontImpl.h
@@ -52,6 +52,8 @@
const SkTDArray<uint32_t>* subset);
};
+struct AdvanceMetric;
+
class SkPDFType1Font final : public SkPDFFont {
public:
virtual ~SkPDFType1Font();
@@ -68,7 +70,7 @@
bool populate(int16_t glyphID);
bool addFontDescriptor(int16_t defaultWidth);
void addWidthInfoFromRange(int16_t defaultWidth,
- const SkAdvancedTypefaceMetrics::WidthRange* widthRangeEntry);
+ const AdvanceMetric* widthRangeEntry);
};
class SkPDFType3Font final : public SkPDFFont {
diff --git a/src/ports/SkFontHost_FreeType.cpp b/src/ports/SkFontHost_FreeType.cpp
index e093bf0..5c30341 100644
--- a/src/ports/SkFontHost_FreeType.cpp
+++ b/src/ports/SkFontHost_FreeType.cpp
@@ -577,38 +577,17 @@
perGlyphInfo = kNo_PerGlyphInfo;
}
- if (perGlyphInfo & kHAdvance_PerGlyphInfo) {
- info->setGlyphWidths(
- face->num_glyphs,
- glyphIDs,
- glyphIDsCount,
- SkAdvancedTypefaceMetrics::GetAdvance([face](int gId, int16_t* data) {
- FT_Fixed advance = 0;
- if (FT_Get_Advances(face, gId, 1, FT_LOAD_NO_SCALE, &advance)) {
- return false;
- }
- SkASSERT(data);
- *data = advance;
- return true;
- })
- );
- }
-
- if (perGlyphInfo & kVAdvance_PerGlyphInfo && FT_HAS_VERTICAL(face)) {
- SkASSERT(false); // Not implemented yet.
- }
-
if (perGlyphInfo & kGlyphNames_PerGlyphInfo &&
info->fType == SkAdvancedTypefaceMetrics::kType1_Font)
{
// Postscript fonts may contain more than 255 glyphs, so we end up
// using multiple font descriptions with a glyph ordering. Record
// the name of each glyph.
- info->fGlyphNames.reset(new SkAutoTArray<SkString>(face->num_glyphs));
+ info->fGlyphNames.reset(face->num_glyphs);
for (int gID = 0; gID < face->num_glyphs; gID++) {
char glyphName[128]; // PS limit for names is 127 bytes.
FT_Get_Glyph_Name(face, gID, glyphName, 128);
- info->fGlyphNames->get()[gID].set(glyphName);
+ info->fGlyphNames[gID].set(glyphName);
}
}
diff --git a/src/ports/SkFontHost_mac.cpp b/src/ports/SkFontHost_mac.cpp
index d95ebbb..842c5e6 100644
--- a/src/ports/SkFontHost_mac.cpp
+++ b/src/ports/SkFontHost_mac.cpp
@@ -1667,24 +1667,6 @@
}
}
}
-
- if (perGlyphInfo & kHAdvance_PerGlyphInfo) {
- CTFontRef borrowedCTFont = ctFont.get();
- info->setGlyphWidths(
- SkToInt(glyphCount),
- glyphIDs,
- glyphIDsCount,
- SkAdvancedTypefaceMetrics::GetAdvance([borrowedCTFont](int gId, int16_t* data) {
- CGSize advance;
- advance.width = 0;
- CGGlyph glyph = gId;
- CTFontGetAdvancesForGlyphs(borrowedCTFont, kCTFontHorizontalOrientation,
- &glyph, &advance, 1);
- *data = sk_float_round2int(advance.width);
- return true;
- })
- );
- }
return info;
}
diff --git a/src/ports/SkFontHost_win.cpp b/src/ports/SkFontHost_win.cpp
index fa5c972..a2d9da7 100644
--- a/src/ports/SkFontHost_win.cpp
+++ b/src/ports/SkFontHost_win.cpp
@@ -1818,29 +1818,6 @@
}
}
- if (perGlyphInfo & kHAdvance_PerGlyphInfo) {
- info->setGlyphWidths(
- glyphCount,
- glyphIDs,
- glyphIDsCount,
- SkAdvancedTypefaceMetrics::GetAdvance([hdc](int gId, int16_t* advance) {
- // Initialize the MAT2 structure to
- // the identify transformation matrix.
- static const MAT2 mat2 = {
- SkScalarToFIXED(1), SkScalarToFIXED(0),
- SkScalarToFIXED(0), SkScalarToFIXED(1)};
- int flags = GGO_METRICS | GGO_GLYPH_INDEX;
- GLYPHMETRICS gm;
- if (GDI_ERROR == GetGlyphOutline(hdc, gId, flags, &gm, 0, nullptr, &mat2)) {
- return false;
- }
- SkASSERT(advance);
- *advance = gm.gmCellIncX;
- return true;
- })
- );
- }
-
Error:
ReturnInfo:
SelectObject(hdc, savefont);
diff --git a/src/ports/SkTypeface_win_dw.cpp b/src/ports/SkTypeface_win_dw.cpp
index 11e5727..7e5c409 100644
--- a/src/ports/SkTypeface_win_dw.cpp
+++ b/src/ports/SkTypeface_win_dw.cpp
@@ -419,50 +419,6 @@
(int32_t)SkEndian_SwapBE16((uint16_t)headTable->yMax),
(int32_t)SkEndian_SwapBE16((uint16_t)headTable->xMax),
(int32_t)SkEndian_SwapBE16((uint16_t)headTable->yMin));
-
- //TODO: is this even desired? It seems PDF only wants this value for Type1
- //fonts, and we only get here for TrueType fonts.
- info->fStemV = 0;
- /*
- // Figure out a good guess for StemV - Min width of i, I, !, 1.
- // This probably isn't very good with an italic font.
- int16_t min_width = SHRT_MAX;
- info->fStemV = 0;
- char stem_chars[] = {'i', 'I', '!', '1'};
- for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) {
- ABC abcWidths;
- if (GetCharABCWidths(hdc, stem_chars[i], stem_chars[i], &abcWidths)) {
- int16_t width = abcWidths.abcB;
- if (width > 0 && width < min_width) {
- min_width = width;
- info->fStemV = min_width;
- }
- }
- }
- */
-
- if (perGlyphInfo & kHAdvance_PerGlyphInfo) {
- if (fixedWidth) {
- SkAdvancedTypefaceMetrics::WidthRange range(0);
- int16_t advance;
- getWidthAdvance(fDWriteFontFace.get(), 1, &advance);
- range.fAdvance.append(1, &advance);
- SkAdvancedTypefaceMetrics::FinishRange(
- &range, 0, SkAdvancedTypefaceMetrics::WidthRange::kDefault);
- info->fGlyphWidths.emplace_back(std::move(range));
- } else {
- IDWriteFontFace* borrowedFontFace = fDWriteFontFace.get();
- info->setGlyphWidths(
- glyphCount,
- glyphIDs,
- glyphIDsCount,
- SkAdvancedTypefaceMetrics::GetAdvance([borrowedFontFace](int gId, int16_t* data) {
- return getWidthAdvance(borrowedFontFace, gId, data);
- })
- );
- }
- }
-
return info;
}
#endif//defined(SK_BUILD_FOR_WIN32)
diff --git a/tests/WArrayTest.cpp b/tests/WArrayTest.cpp
deleted file mode 100644
index 9a239fb..0000000
--- a/tests/WArrayTest.cpp
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "Test.h"
-
-// Include the implementation so we can make an appropriate template instance.
-#include "SkAdvancedTypefaceMetrics.h"
-
-// Negative values and zeros in a range plus trailing zeros.
-// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
-static const int16_t data1[] = {-1, 0, -3, 4, 5, 6, 7, 0, 0, 0, 8, 0, 0, 0, 0};
-static const char* expected1 = "0[-1 0 -3 4 5 6 7 0 0 0 8]";
-
-// Run with leading and trailing zeros.
-// Test rules: d 0 1 2 3 4 5 6 7 8 9 10 11
-static const int16_t data2[] = {0, 0, 0, 100, 100, 100, 100, 100, 100, 100, 0, 0};
-static const char* expected2 = "3 9 100";
-
-// Removing 0's from a range.
-// Test rules: a 0 1 2 3 4 5 6 7 8 9 10 11
-static const int16_t data3[] = {1, 2, 0, 0, 0, 3, 4, 0, 0, 0, 0, 5};
-static const char* expected3 = "0[1 2 0 0 0 3 4] 11[5]";
-
-// Removing 0's from a run/range and between runs.
-// Test rules: a, b 0 1 2 3 4 5 6 7 8 9 10 11 12 14 15
-static const int16_t data4[] = {1, 0, 0, 0, 1, 2, 2, 2, 3, 0, 0, 0, 0, 3, 4};
-static const char* expected4 = "0[1 0 0 0 1] 5 7 2 8[3] 13[3 4]";
-
-// Runs that starts outside a range.
-// Test rules: a, e 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
-static const int16_t data5[] = {1, 1, 2, 3, 0, 0, 0, 0, 5, 5, 6, 7, 0, 0, 0, 0, 8, 0};
-static const char* expected5 = "0 1 1 2[2 3] 8 9 5 10[6 7] 16[8]";
-
-// Zeros and runs that should be broken out.
-// Test rules: a, b, e 0 1 2 3 4 5 6 7 8 9 10 11 12 13
-static const int16_t data6[] = {1, 0, 0, 0, 0, 1, 2, 3, 3, 4, 5, 5, 5, 6};
-static const char* expected6 = "0[1] 5[1 2 3 3 4] 10 12 5 13[6]";
-
-// Don't cares that aren't enough to break out a run.
-// Test rules: c 0 1 2 3 4 5
-static const int16_t data7[] = {1, 2, 10, 11, 2, 3};
-static const char* expected7 = "0[1 2 10 11 2 3]";
-static const uint32_t subset7[] = {0, 1, 4, 5};
-static const char* expectedSubset7 = "0[1 2 0 0 2 3]";
-
-// Don't cares that are enough to break out a run.
-// Test rules: c 0 1 2 3 4 5 6
-static const int16_t data8[] = {1, 2, 10, 11, 12, 2, 3};
-static const char* expected8 = "0[1 2 10 11 12 2 3]";
-static const uint32_t subset8[] = {0, 1, 5, 6};
-static const char* expectedSubset8 = "0[1] 1 5 2 6[3]";
-
-// Leading don't cares.
-// Test rules: d 0 1 2 3 4
-static const int16_t data9[] = {1, 1, 10, 2, 3};
-static const char* expected9 = "0 1 1 2[10 2 3]";
-static const uint32_t subset9[] = {0, 1, 3, 4};
-static const char* expectedSubset9 = "0 1 1 3[2 3]";
-
-// Almost run of don't cares inside a range.
-// Test rules: c 0 1 2 3 4 5
-static const int16_t data10[] = {1, 2, 10, 11, 12, 3};
-static const char* expected10 = "0[1 2 10 11 12 3]";
-static const uint32_t subset10[] = {0, 1, 5};
-static const char* expectedSubset10 = "0[1 2 0 0 0 3]";
-
-// Run of don't cares inside a range.
-// Test rules: c 0 1 2 3 4 5 6
-static const int16_t data11[] = {1, 2, 10, 11, 12, 13, 3};
-static const char* expected11 = "0[1 2 10 11 12 13 3]";
-static const uint32_t subset11[] = {0, 1, 6};
-static const char* expectedSubset11 = "0[1 2] 6[3]";
-
-// Almost run within a range with leading don't cares.
-// Test rules: c 0 1 2 3 4 5 6
-static const int16_t data12[] = {1, 10, 11, 2, 12, 13, 3};
-static const char* expected12 = "0[1 10 11 2 12 13 3]";
-static const uint32_t subset12[] = {0, 3, 6};
-static const char* expectedSubset12 = "0[1 0 0 2 0 0 3]";
-
-// Run within a range with leading don't cares.
-// Test rules: c 0 1 2 3 4 5 6 7
-static const int16_t data13[] = {1, 10, 11, 2, 2, 12, 13, 3};
-static const char* expected13 = "0[1 10 11 2 2 12 13 3]";
-static const uint32_t subset13[] = {0, 3, 4, 7};
-static const char* expectedSubset13 = "0[1] 1 6 2 7[3]";
-
-// Enough don't cares to breakup something.
-// Test rules: a 0 1 2 3 4 5
-static const int16_t data14[] = {1, 0, 0, 0, 0, 2};
-static const char* expected14 = "0[1] 5[2]";
-static const uint32_t subset14[] = {0, 5};
-static const char* expectedSubset14 = "0[1] 5[2]";
-
-static SkString stringify_advance_data(const SkSinglyLinkedList<
- SkAdvancedTypefaceMetrics::AdvanceMetric<int16_t>>& list) {
- SkString result;
- bool leadingSpace = false;
- for (const SkAdvancedTypefaceMetrics::AdvanceMetric<int16_t>& data : list) {
- if (leadingSpace) {
- result.append(" ");
- } else {
- leadingSpace = true;
- }
- switch (data.fType) {
- case SkAdvancedTypefaceMetrics::AdvanceMetric<int16_t>::kRun:
- result.appendf("%d %d %d", data.fStartId, data.fEndId,
- data.fAdvance[0]);
- break;
- case SkAdvancedTypefaceMetrics::AdvanceMetric<int16_t>::kRange:
- result.appendf("%d[", data.fStartId);
- for (int i = 0; i < data.fAdvance.count(); ++i) {
- if (i > 0) {
- result.append(" ");
- }
- result.appendf("%d", data.fAdvance[i]);
- }
- result.append("]");
- break;
- case SkAdvancedTypefaceMetrics::AdvanceMetric<int16_t>::kDefault:
- result.appendf("<Default=%d>", data.fAdvance[0]);
- break;
- }
- }
- return result;
-}
-
-class TestWData {
- public:
- TestWData(skiatest::Reporter* reporter,
- const int16_t advances[], int advanceLen,
- const uint32_t subset[], int subsetLen,
- const char* expected)
- : fAdvances(advances)
- , fAdvancesLen(advanceLen)
- , fSubset(subset)
- , fSubsetLen(subsetLen)
- , fExpected(expected) {
- this->runTest(reporter);
- }
-
- private:
- const int16_t* fAdvances;
- const int fAdvancesLen;
- const uint32_t* fSubset;
- const int fSubsetLen;
- const char* fExpected;
-
- void runTest(skiatest::Reporter* reporter) {
- SkAdvancedTypefaceMetrics metrics;
- metrics.setGlyphWidths(
- fAdvancesLen, fSubset, fSubsetLen,
- std::function<bool(int, int16_t*)>([this](int gId, int16_t* advance) {
- if (gId >= 0 && gId < fAdvancesLen) {
- *advance = fAdvances[gId];
- return true;
- }
- return false;
- }));
-
- SkString stringResult = stringify_advance_data(metrics.fGlyphWidths);
- if (!stringResult.equals(fExpected)) {
- ERRORF(reporter, "Expected: %s\n Result: %s\n", fExpected, stringResult.c_str());
- }
- }
-};
-
-DEF_TEST(WArray, reporter) {
- TestWData(reporter, data1, SK_ARRAY_COUNT(data1), nullptr, 0, expected1);
- TestWData(reporter, data2, SK_ARRAY_COUNT(data2), nullptr, 0, expected2);
- TestWData(reporter, data3, SK_ARRAY_COUNT(data3), nullptr, 0, expected3);
- TestWData(reporter, data4, SK_ARRAY_COUNT(data4), nullptr, 0, expected4);
- TestWData(reporter, data5, SK_ARRAY_COUNT(data5), nullptr, 0, expected5);
- TestWData(reporter, data6, SK_ARRAY_COUNT(data6), nullptr, 0, expected6);
- TestWData(reporter, data7, SK_ARRAY_COUNT(data7), nullptr, 0, expected7);
- TestWData(reporter, data7, SK_ARRAY_COUNT(data7), subset7,
- SK_ARRAY_COUNT(subset7), expectedSubset7);
- TestWData(reporter, data8, SK_ARRAY_COUNT(data8), nullptr, 0, expected8);
- TestWData(reporter, data8, SK_ARRAY_COUNT(data8), subset8,
- SK_ARRAY_COUNT(subset8), expectedSubset8);
- TestWData(reporter, data9, SK_ARRAY_COUNT(data9), nullptr, 0, expected9);
- TestWData(reporter, data9, SK_ARRAY_COUNT(data9), subset9,
- SK_ARRAY_COUNT(subset9), expectedSubset9);
- TestWData(reporter, data10, SK_ARRAY_COUNT(data10), nullptr, 0, expected10);
- TestWData(reporter, data10, SK_ARRAY_COUNT(data10), subset10,
- SK_ARRAY_COUNT(subset10), expectedSubset10);
- TestWData(reporter, data11, SK_ARRAY_COUNT(data11), nullptr, 0, expected11);
- TestWData(reporter, data11, SK_ARRAY_COUNT(data11), subset11,
- SK_ARRAY_COUNT(subset11), expectedSubset11);
- TestWData(reporter, data12, SK_ARRAY_COUNT(data12), nullptr, 0, expected12);
- TestWData(reporter, data12, SK_ARRAY_COUNT(data12), subset12,
- SK_ARRAY_COUNT(subset12), expectedSubset12);
- TestWData(reporter, data13, SK_ARRAY_COUNT(data13), nullptr, 0, expected13);
- TestWData(reporter, data13, SK_ARRAY_COUNT(data13), subset13,
- SK_ARRAY_COUNT(subset13), expectedSubset13);
- TestWData(reporter, data14, SK_ARRAY_COUNT(data14), nullptr, 0, expected14);
- TestWData(reporter, data14, SK_ARRAY_COUNT(data14), subset14,
- SK_ARRAY_COUNT(subset14), expectedSubset14);
-}