for (size_t i = 1; i < advances.size(); ++i) { if (advances[i] == currentAdvance) {
++currentCount;
} else { if (currentCount > currentModeCount) {
currentModeAdvance = currentAdvance;
currentModeCount = currentCount;
}
currentAdvance = advances[i];
currentCount = 1;
}
} return currentCount > currentModeCount ? currentAdvance : currentModeAdvance;
}
} // namespace
std::unique_ptr<SkPDFArray> SkPDFMakeCIDGlyphWidthsArray(const SkPDFStrikeSpec& pdfStrikeSpec, const SkPDFGlyphUse& subset,
int32_t* defaultAdvance) { // 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 = pdfStrikeSpec.fUnitsPerEM;
SkBulkGlyphMetricsAndPaths paths{pdfStrikeSpec.fStrikeSpec};
// C++20 = make_unique_for_overwrite<SkScalar[]>(glyphs.size()); auto advances = std::unique_ptr<SkScalar[]>(new SkScalar[glyphs.size()]);
// Find the pdf integer mode (most common pdf integer advance). // Unfortunately, poppler enforces DW (default width) must be an integer, // so only consider integer pdf advances when finding the mode.
size_t numIntAdvances = 0; for (const SkGlyph* glyph : glyphs) {
SkScalar currentAdvance = from_font_units(glyph->advanceX(), emSize); if ((int32_t)currentAdvance == currentAdvance) {
advances[numIntAdvances++] = currentAdvance;
}
}
std::sort(advances.get(), advances.get() + numIntAdvances);
int32_t modeAdvance = (int32_t)find_mode_or_0(SkSpan(advances.get(), numIntAdvances));
*defaultAdvance = modeAdvance;
// Pre-convert to pdf advances. for (size_t i = 0; i < glyphs.size(); ++i) {
advances[i] = from_font_units(glyphs[i]->advanceX(), emSize);
}
for (size_t i = 0; i < glyphs.size(); ++i) {
SkScalar advance = advances[i];
// a. Skipping don't cares or defaults is a win (trivial) if (advance == modeAdvance) { continue;
}
// 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) {
SkScalar next_advance = advances[j]; if (advance != next_advance) { break;
}
} if (j - i >= 2) {
result->appendInt(glyphs[i]->getGlyphID());
result->appendInt(glyphs[j - 1]->getGlyphID());
result->appendScalar(advance);
i = j - 1; continue;
}
}
{
result->appendInt(glyphs[i]->getGlyphID()); auto advanceArray = SkPDFMakeArray();
advanceArray->appendScalar(advance);
size_t j = i + 1; // j is always one past the last output for (; j < glyphs.size(); ++j) {
advance = advances[j];
// c. end range if default seen if (advance == modeAdvance) { break;
}
int dontCares = glyphs[j]->getGlyphID() - glyphs[j - 1]->getGlyphID() - 1; // d. end range if 4+ don't cares if (dontCares >= 4) { break;
}
SkScalar next_advance = 0; // e. end range for 2+ repeats with 4+ don't cares if (j + 1 < glyphs.size()) {
next_advance = advances[j+1]; 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 = advances[j+2]; if (advance == next_advance) { break;
}
}
while (dontCares --> 0) {
advanceArray->appendScalar(0);
}
advanceArray->appendScalar(advance);
}
result->appendObject(std::move(advanceArray));
i = j - 1;
}
}
return result;
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.