summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/skia/src
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/skia/src')
-rw-r--r--chromium/third_party/skia/src/pdf/SkPDFFont.cpp10
-rw-r--r--chromium/third_party/skia/src/pdf/SkPDFMakeCIDGlyphWidthsArray.cpp351
-rw-r--r--chromium/third_party/skia/src/pdf/SkPDFMakeCIDGlyphWidthsArray.h2
-rw-r--r--chromium/third_party/skia/src/pdf/SkPDFSubsetFont.cpp4
4 files changed, 149 insertions, 218 deletions
diff --git a/chromium/third_party/skia/src/pdf/SkPDFFont.cpp b/chromium/third_party/skia/src/pdf/SkPDFFont.cpp
index 33ec05b76ab..ba79a15c9a5 100644
--- a/chromium/third_party/skia/src/pdf/SkPDFFont.cpp
+++ b/chromium/third_party/skia/src/pdf/SkPDFFont.cpp
@@ -231,7 +231,11 @@ SkPDFFont::SkPDFFont(sk_sp<SkTypeface> typeface,
: fTypeface(std::move(typeface))
, fGlyphUsage(firstGlyphID, lastGlyphID)
, fIndirectReference(indirectReference)
- , fFontType(fontType) {}
+ , fFontType(fontType)
+{
+ // Always include glyph 0
+ this->noteGlyphUsage(0);
+}
void SkPDFFont::PopulateCommonFontDescriptor(SkPDFDict* descriptor,
const SkAdvancedTypefaceMetrics& metrics,
@@ -290,7 +294,7 @@ static void emit_subset_type0(const SkPDFFont& font, SkPDFDocument* doc) {
auto descriptor = SkPDFMakeDict("FontDescriptor");
uint16_t emSize = SkToU16(font.typeface()->getUnitsPerEm());
- SkPDFFont::PopulateCommonFontDescriptor(descriptor.get(), metrics, emSize , 0);
+ SkPDFFont::PopulateCommonFontDescriptor(descriptor.get(), metrics, emSize, 0);
int ttcIndex;
std::unique_ptr<SkStreamAsset> fontAsset = face->openStream(&ttcIndex);
@@ -369,7 +373,7 @@ static void emit_subset_type0(const SkPDFFont& font, SkPDFDocument* doc) {
SkScalar defaultWidth = 0;
{
std::unique_ptr<SkPDFArray> widths = SkPDFMakeCIDGlyphWidthsArray(
- *face, &font.glyphUsage(), &defaultWidth);
+ *face, font.glyphUsage(), &defaultWidth);
if (widths && widths->size() > 0) {
newCIDFont->insertObject("W", std::move(widths));
}
diff --git a/chromium/third_party/skia/src/pdf/SkPDFMakeCIDGlyphWidthsArray.cpp b/chromium/third_party/skia/src/pdf/SkPDFMakeCIDGlyphWidthsArray.cpp
index 589cfa76202..210202db4d1 100644
--- a/chromium/third_party/skia/src/pdf/SkPDFMakeCIDGlyphWidthsArray.cpp
+++ b/chromium/third_party/skia/src/pdf/SkPDFMakeCIDGlyphWidthsArray.cpp
@@ -13,6 +13,7 @@
#include "src/core/SkStrikeSpec.h"
#include "src/pdf/SkPDFGlyphUse.h"
+#include <algorithm>
#include <vector>
// TODO(halcanary): Write unit tests for SkPDFMakeCIDGlyphWidthsArray().
@@ -23,28 +24,8 @@
namespace {
-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;
- std::vector<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;
-};
-const int16_t kInvalidAdvance = SK_MinS16;
-const int16_t kDontCareAdvance = SK_MinS16 + 1;
-} // namespace
-
// scale from em-units to base-1000, returning as a SkScalar
-static SkScalar from_font_units(SkScalar scaled, uint16_t emSize) {
+SkScalar from_font_units(SkScalar scaled, uint16_t emSize) {
if (emSize == 1000) {
return scaled;
} else {
@@ -52,224 +33,174 @@ static SkScalar from_font_units(SkScalar scaled, uint16_t emSize) {
}
}
-static SkScalar scale_from_font_units(int16_t val, uint16_t emSize) {
+SkScalar scale_from_font_units(int16_t val, uint16_t emSize) {
return from_font_units(SkIntToScalar(val), emSize);
}
-static void strip_uninteresting_trailing_advances_from_range(
- AdvanceMetric* range) {
- SkASSERT(range);
-
- int expectedAdvanceCount = range->fEndId - range->fStartId + 1;
- if (SkToInt(range->fAdvance.size()) < 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 zero_wildcards_in_range(AdvanceMetric* range) {
- SkASSERT(range);
- if (range->fType != AdvanceMetric::kRange) {
- return;
+// Unfortunately poppler does not appear to respect the default width setting.
+#if defined(SK_PDF_CAN_USE_DW)
+int16_t findMode(SkSpan<const int16_t> advances) {
+ if (advances.empty()) {
+ return 0;
}
- SkASSERT(SkToInt(range->fAdvance.size()) == range->fEndId - range->fStartId + 1);
- // Zero out wildcards.
- for (size_t i = 0; i < range->fAdvance.size(); ++i) {
- if (range->fAdvance[i] == kDontCareAdvance) {
- range->fAdvance[i] = 0;
- }
- }
-}
+ int16_t previousAdvance = advances[0];
+ int16_t currentModeAdvance = advances[0];
+ size_t currentCount = 1;
+ size_t currentModeCount = 1;
-static void finish_range(
- AdvanceMetric* range,
- int endId,
- AdvanceMetric::MetricType type) {
- range->fEndId = endId;
- range->fType = type;
- strip_uninteresting_trailing_advances_from_range(range);
- size_t newLength;
- if (type == AdvanceMetric::kRange) {
- newLength = range->fEndId - range->fStartId + 1;
- } else {
- if (range->fEndId == range->fStartId) {
- range->fType = AdvanceMetric::kRange;
+ for (size_t i = 1; i < advances.size(); ++i) {
+ if (advances[i] == previousAdvance) {
+ ++currentCount;
+ } else {
+ if (currentCount > currentModeCount) {
+ currentModeAdvance = previousAdvance;
+ currentModeCount = currentCount;
+ }
+ previousAdvance = advances[i];
+ currentCount = 1;
}
- newLength = 1;
}
- SkASSERT(range->fAdvance.size() >= newLength);
- range->fAdvance.resize(newLength);
- zero_wildcards_in_range(range);
-}
-static void compose_advance_data(const AdvanceMetric& range,
- uint16_t emSize,
- SkScalar* defaultAdvance,
- SkPDFArray* result) {
- switch (range.fType) {
- case AdvanceMetric::kDefault: {
- SkASSERT(range.fAdvance.size() == 1);
- *defaultAdvance = scale_from_font_units(range.fAdvance[0], emSize);
- break;
- }
- case AdvanceMetric::kRange: {
- auto advanceArray = SkPDFMakeArray();
- for (size_t j = 0; j < range.fAdvance.size(); j++)
- advanceArray->appendScalar(scale_from_font_units(range.fAdvance[j], emSize));
- result->appendInt(range.fStartId);
- result->appendObject(std::move(advanceArray));
- break;
- }
- case AdvanceMetric::kRun: {
- SkASSERT(range.fAdvance.size() == 1);
- result->appendInt(range.fStartId);
- result->appendInt(range.fEndId);
- result->appendScalar(scale_from_font_units(range.fAdvance[0], emSize));
- break;
- }
- }
+ return currentCount > currentModeCount ? previousAdvance : currentModeAdvance;
}
+#endif
+} // namespace
/** Retrieve advance data for glyphs. Used by the PDF backend. */
// TODO(halcanary): this function is complex enough to need its logic
// tested with unit tests.
std::unique_ptr<SkPDFArray> SkPDFMakeCIDGlyphWidthsArray(const SkTypeface& typeface,
- const SkPDFGlyphUse* subset,
+ const SkPDFGlyphUse& subset,
SkScalar* defaultAdvance) {
- // 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 characters
- // 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
- // characters, so:
- // d. Removing a leading 0/don't cares is a win because it is omitted
- // e. Removing 2 repeating advances is a win
+ // There are two ways of expressing advances
+ //
+ // range: " gfid [adv.ances adv.ances ... adv.ances]"
+ // run: " gfid gfid adv.ances"
+ //
+ // Assuming that on average
+ // the ASCII representation of an advance plus a space is 10 characters
+ // the ASCII representation of a glyph id plus a space is 4 characters
+ // the ASCII representation of unused gid plus a space in a range is 2 characters
+ //
+ // When not in a range or run
+ // a. Skipping don't cares or defaults is a win (trivial)
+ // b. Run wins for 2+ repeats " gid gid adv.ances"
+ // " gid [adv.ances adv.ances]"
+ // rule: 2+ repeats create run as long as possible, else start range
+ //
+ // When in a range
+ // Cost of stopping and starting a range is 8 characters "] gid ["
+ // c. Skipping defaults is always a win " adv.ances"
+ // rule: end range if default seen
+ // d. Skipping 4+ don't cares is a win " 0 0 0 0"
+ // rule: end range if 4+ don't cares
+ // Cost of stop and start range plus run is 28 characters "] gid gid adv.ances gid ["
+ // e. Switching for 2+ repeats and 4+ don't cares wins " 0 0 adv.ances 0 0 adv.ances"
+ // rule: end range for 2+ repeats with 4+ don't cares
+ // f. Switching for 3+ repeats wins " adv.ances adv.ances adv.ances"
+ // rule: end range for 3+ repeats
int emSize;
SkStrikeSpec strikeSpec = SkStrikeSpec::MakePDFVector(typeface, &emSize);
SkBulkGlyphMetricsAndPaths paths{strikeSpec};
auto result = SkPDFMakeArray();
- int num_glyphs = SkToInt(typeface.countGlyphs());
-
- bool prevRange = false;
-
- int16_t lastAdvance = kInvalidAdvance;
- int repeatedAdvances = 0;
- int wildCardsInRun = 0;
- int trailingWildCards = 0;
- // Limit the loop count to glyph id ranges provided.
- int lastIndex = num_glyphs;
- if (subset) {
- while (!subset->has(lastIndex - 1) && lastIndex > 0) {
- --lastIndex;
- }
- }
- AdvanceMetric curRange(0);
-
- SkAutoTArray<SkGlyphID> glyphIDs{lastIndex + 1};
- for (int gId = 0; gId <= lastIndex; gId++) {
- glyphIDs[gId] = gId;
+ std::vector<SkGlyphID> glyphIDs;
+ subset.getSetValues([&](unsigned index) {
+ glyphIDs.push_back(SkToU16(index));
+ });
+ auto glyphs = paths.glyphs(SkMakeSpan(glyphIDs));
+
+#if defined(SK_PDF_CAN_USE_DW)
+ std::vector<int16_t> advances;
+ advances.reserve(glyphs.size());
+ for (const SkGlyph* glyph : glyphs) {
+ advances.push_back((int16_t)glyph->advanceX());
}
-
- auto glyphs = paths.glyphs(SkMakeSpan(glyphIDs.get(), lastIndex + 1));
-
- for (int gId = 0; gId <= lastIndex; gId++) {
- int16_t advance = kInvalidAdvance;
- if (gId < lastIndex) {
- if (!subset || 0 == gId || subset->has(gId)) {
- advance = (int16_t)glyphs[gId]->advanceX();
- } else {
- advance = kDontCareAdvance;
- }
+ std::sort(advances.begin(), advances.end());
+ int16_t modeAdvance = findMode(SkMakeSpan(advances));
+ *defaultAdvance = scale_from_font_units(modeAdvance, emSize);
+#else
+ *defaultAdvance = 0;
+#endif
+
+ for (size_t i = 0; i < glyphs.size(); ++i) {
+ int16_t advance = (int16_t)glyphs[i]->advanceX();
+
+#if defined(SK_PDF_CAN_USE_DW)
+ // a. Skipping don't cares or defaults is a win (trivial)
+ if (advance == modeAdvance) {
+ continue;
}
- if (advance == lastAdvance) {
- repeatedAdvances++;
- trailingWildCards = 0;
- } else if (advance == kDontCareAdvance) {
- wildCardsInRun++;
- trailingWildCards++;
- } else if (SkToInt(curRange.fAdvance.size()) ==
- repeatedAdvances + 1 + wildCardsInRun) { // All in run.
- if (lastAdvance == 0) {
- curRange.fStartId = gId; // reset
- curRange.fAdvance.resize(0);
- trailingWildCards = 0;
- } else if (repeatedAdvances + 1 >= 2 || trailingWildCards >= 4) {
- finish_range(&curRange, gId - 1, AdvanceMetric::kRun);
- compose_advance_data(curRange, emSize, defaultAdvance, result.get());
- prevRange = true;
- curRange = AdvanceMetric(gId);
- trailingWildCards = 0;
+#endif
+
+ // b. 2+ repeats create run as long as possible, else start range
+ {
+ size_t j = i + 1; // j is always one past the last known repeat
+ for (; j < glyphs.size(); ++j) {
+ int16_t next_advance = (int16_t)glyphs[j]->advanceX();
+ if (advance != next_advance) {
+ break;
+ }
}
- repeatedAdvances = 0;
- wildCardsInRun = trailingWildCards;
- trailingWildCards = 0;
- } else {
- if (lastAdvance == 0 &&
- repeatedAdvances + 1 + wildCardsInRun >= 4) {
- finish_range(&curRange,
- gId - repeatedAdvances - wildCardsInRun - 2,
- AdvanceMetric::kRange);
- compose_advance_data(curRange, emSize, defaultAdvance, result.get());
- prevRange = true;
- curRange = AdvanceMetric(gId);
- trailingWildCards = 0;
- } else if (trailingWildCards >= 4 && repeatedAdvances + 1 < 2) {
- finish_range(&curRange, gId - trailingWildCards - 1,
- AdvanceMetric::kRange);
- compose_advance_data(curRange, emSize, defaultAdvance, result.get());
- prevRange = true;
- curRange = AdvanceMetric(gId);
- trailingWildCards = 0;
- } else if (lastAdvance != 0 &&
- (repeatedAdvances + 1 >= 3 ||
- (repeatedAdvances + 1 >= 2 && wildCardsInRun >= 3))) {
- finish_range(&curRange,
- gId - repeatedAdvances - wildCardsInRun - 2,
- AdvanceMetric::kRange);
- compose_advance_data(curRange, emSize, defaultAdvance, result.get());
- curRange =
- AdvanceMetric(gId - repeatedAdvances - wildCardsInRun - 1);
- curRange.fAdvance.push_back(lastAdvance);
- finish_range(&curRange, gId - 1, AdvanceMetric::kRun);
- compose_advance_data(curRange, emSize, defaultAdvance, result.get());
- prevRange = true;
- curRange = AdvanceMetric(gId);
- trailingWildCards = 0;
+ if (j - i >= 2) {
+ result->appendInt(glyphs[i]->getGlyphID());
+ result->appendInt(glyphs[j - 1]->getGlyphID());
+ result->appendScalar(scale_from_font_units(advance, emSize));
+ i = j - 1;
+ continue;
}
- repeatedAdvances = 0;
- wildCardsInRun = trailingWildCards;
- trailingWildCards = 0;
- }
- curRange.fAdvance.push_back(advance);
- if (advance != kDontCareAdvance) {
- lastAdvance = advance;
}
- }
- if (curRange.fStartId == lastIndex) {
- if (!prevRange) {
- return nullptr; // https://crbug.com/567031
+
+ {
+ result->appendInt(glyphs[i]->getGlyphID());
+ auto advanceArray = SkPDFMakeArray();
+ advanceArray->appendScalar(scale_from_font_units(advance, emSize));
+ size_t j = i + 1; // j is always one past the last output
+ for (; j < glyphs.size(); ++j) {
+ advance = (int16_t)glyphs[j]->advanceX();
+#if defined(SK_PDF_CAN_USE_DW)
+ // c. end range if default seen
+ if (advance == modeAdvance) {
+ break;
+ }
+#endif
+
+ int dontCares = glyphs[j]->getGlyphID() - glyphs[j - 1]->getGlyphID() - 1;
+ // d. end range if 4+ don't cares
+ if (dontCares >= 4) {
+ break;
+ }
+
+ int16_t next_advance = 0;
+ // e. end range for 2+ repeats with 4+ don't cares
+ if (j + 1 < glyphs.size()) {
+ next_advance = (int16_t)glyphs[j+1]->advanceX();
+ int next_dontCares = glyphs[j+1]->getGlyphID() - glyphs[j]->getGlyphID() - 1;
+ if (advance == next_advance && dontCares + next_dontCares >= 4) {
+ break;
+ }
+ }
+
+ // f. end range for 3+ repeats
+ if (j + 2 < glyphs.size() && advance == next_advance) {
+ next_advance = (int16_t)glyphs[j+2]->advanceX();
+ if (advance == next_advance) {
+ break;
+ }
+ }
+
+ while (dontCares --> 0) {
+ advanceArray->appendScalar(0);
+ }
+ advanceArray->appendScalar(scale_from_font_units(advance, emSize));
+ }
+ result->appendObject(std::move(advanceArray));
+ i = j - 1;
}
- } else {
- finish_range(&curRange, lastIndex - 1, AdvanceMetric::kRange);
- compose_advance_data(curRange, emSize, defaultAdvance, result.get());
}
+
return result;
}
diff --git a/chromium/third_party/skia/src/pdf/SkPDFMakeCIDGlyphWidthsArray.h b/chromium/third_party/skia/src/pdf/SkPDFMakeCIDGlyphWidthsArray.h
index b2e1e1df55a..041fe28d8cb 100644
--- a/chromium/third_party/skia/src/pdf/SkPDFMakeCIDGlyphWidthsArray.h
+++ b/chromium/third_party/skia/src/pdf/SkPDFMakeCIDGlyphWidthsArray.h
@@ -17,7 +17,7 @@ class SkTypeface;
format that can specify individual widths for consecutive CIDs or
one width for a range of CIDs". */
std::unique_ptr<SkPDFArray> SkPDFMakeCIDGlyphWidthsArray(const SkTypeface& typeface,
- const SkPDFGlyphUse* subset,
+ const SkPDFGlyphUse& subset,
SkScalar* defaultAdvance);
#endif // SkPDFMakeCIDGlyphWidthsArray_DEFINED
diff --git a/chromium/third_party/skia/src/pdf/SkPDFSubsetFont.cpp b/chromium/third_party/skia/src/pdf/SkPDFSubsetFont.cpp
index 0bb92bb9622..5485f3b4ba3 100644
--- a/chromium/third_party/skia/src/pdf/SkPDFSubsetFont.cpp
+++ b/chromium/third_party/skia/src/pdf/SkPDFSubsetFont.cpp
@@ -68,7 +68,6 @@ static sk_sp<SkData> subset_harfbuzz(sk_sp<SkData> fontData,
return nullptr;
}
hb_set_t* glyphs = hb_subset_input_glyph_set(input.get());
- hb_set_add(glyphs, 0);
glyphUsage.getSetValues([&glyphs](unsigned gid) { hb_set_add(glyphs, gid);});
hb_subset_input_set_retain_gids(input.get(), true);
@@ -99,9 +98,6 @@ static sk_sp<SkData> subset_sfntly(sk_sp<SkData> fontData,
// Generate glyph id array in format needed by sfntly.
// TODO(halcanary): sfntly should take a more compact format.
std::vector<unsigned> subset;
- if (!glyphUsage.has(0)) {
- subset.push_back(0); // Always include glyph 0.
- }
glyphUsage.getSetValues([&subset](unsigned v) { subset.push_back(v); });
unsigned char* subsetFont{nullptr};