[core] Calculate line width and line breaks for images

This commit is contained in:
Alexander Shalamov
2019-11-13 11:50:43 +02:00
parent 34a9bc08ce
commit f4f652063d
2 changed files with 34 additions and 23 deletions

View File

@@ -367,7 +367,7 @@ void SymbolLayout::prepareSymbols(const GlyphMap& glyphMap, const GlyphPositions
const Shaping result = getShaping(
/* string */ formattedText,
/* maxWidth: ems */
isPointPlacement ? layout->evaluate<TextMaxWidth>(zoom, feature) * util::ONE_EM : 0.0f,
isPointPlacement ? layout->evaluate<TextMaxWidth>(zoom, feature) * util::ONE_EM : 0.0f,
/* ems */ lineHeight,
textAnchor,
textJustify,

View File

@@ -163,27 +163,43 @@ void justifyLine(std::vector<PositionedGlyph>& positionedGlyphs,
}
}
float getGlyphAdvance(char16_t codePoint,
const SectionOptions& section,
const GlyphMap& glyphMap,
const ImagePositions& imagePositions,
float layoutTextSize,
float spacing) {
if (!section.imageID) {
auto glyphs = glyphMap.find(section.fontStackHash);
if (glyphs == glyphMap.end()) {
return 0.0;
}
auto it = glyphs->second.find(codePoint);
if (it == glyphs->second.end() || !it->second) {
return 0.0;
}
return (*it->second)->metrics.advance * section.scale + spacing;
} else {
auto image = imagePositions.find(*section.imageID);
if (image == imagePositions.end()) {
return 0.0;
}
return image->second.displaySize()[0] * section.scale * util::ONE_EM / layoutTextSize + spacing;
}
}
float determineAverageLineWidth(const TaggedString& logicalInput,
const float spacing,
float spacing,
float maxWidth,
const GlyphMap& glyphMap,
const ImagePositions& /*imagePositions*/,
float /*layoutTextSize*/) {
const ImagePositions& imagePositions,
float layoutTextSize) {
float totalWidth = 0;
for (std::size_t i = 0; i < logicalInput.length(); i++) {
const SectionOptions& section = logicalInput.getSection(i);
char16_t codePoint = logicalInput.getCharCodeAt(i);
auto glyphs = glyphMap.find(section.fontStackHash);
if (glyphs == glyphMap.end()) {
continue;
}
auto it = glyphs->second.find(codePoint);
if (it == glyphs->second.end() || !it->second) {
continue;
}
totalWidth += (*it->second)->metrics.advance * section.scale + spacing;
totalWidth += getGlyphAdvance(codePoint, section, glyphMap, imagePositions, layoutTextSize, spacing);
}
int32_t targetLineCount = ::fmax(1, std::ceil(totalWidth / maxWidth));
@@ -303,20 +319,15 @@ std::set<std::size_t> determineLineBreaks(const TaggedString& logicalInput,
for (std::size_t i = 0; i < logicalInput.length(); i++) {
const SectionOptions& section = logicalInput.getSection(i);
char16_t codePoint = logicalInput.getCharCodeAt(i);
auto glyphs = glyphMap.find(section.fontStackHash);
if (glyphs == glyphMap.end()) {
continue;
if (!util::i18n::isWhitespace(codePoint)) {
currentX += getGlyphAdvance(codePoint, section, glyphMap, imagePositions, layoutTextSize, spacing);
}
auto it = glyphs->second.find(codePoint);
if (it != glyphs->second.end() && it->second && !util::i18n::isWhitespace(codePoint)) {
currentX += (*it->second)->metrics.advance * section.scale + spacing;
}
// Ideographic characters, spaces, and word-breaking punctuation that often appear without
// surrounding spaces.
if (i < logicalInput.length() - 1) {
const bool allowsIdeographicBreak = util::i18n::allowsIdeographicBreaking(codePoint);
if (allowsIdeographicBreak || util::i18n::allowsWordBreaking(codePoint)) {
if (section.imageID || allowsIdeographicBreak || util::i18n::allowsWordBreaking(codePoint)) {
const bool penalizableIdeographicBreak = allowsIdeographicBreak && hasServerSuggestedBreaks;
const std::size_t nextIndex = i + 1;
potentialBreaks.push_back(evaluateBreak(nextIndex, currentX, targetWidth, potentialBreaks,