[core] Pass images and evaluated layout text size to shaping

This commit is contained in:
Alexander Shalamov
2019-11-13 11:22:26 +02:00
parent a9c3b5a389
commit 34a9bc08ce
5 changed files with 65 additions and 22 deletions

View File

@@ -352,16 +352,22 @@ void SymbolLayout::prepareSymbols(const GlyphMap& glyphMap, const GlyphPositions
ShapedTextOrientations shapedTextOrientations;
optional<PositionedIcon> shapedIcon;
std::array<float, 2> textOffset{{0.0f, 0.0f}};
const float layoutTextSize = layout->evaluate<TextSize>(zoom + 1, feature);
const float layoutIconSize = layout->evaluate<IconSize>(zoom + 1, feature);
// if feature has text, shape the text
if (feature.formattedText) {
const float lineHeight = layout->get<TextLineHeight>() * util::ONE_EM;
const float spacing = util::i18n::allowsLetterSpacing(feature.formattedText->rawText()) ? layout->evaluate<TextLetterSpacing>(zoom, feature) * util::ONE_EM : 0.0f;
auto applyShaping = [&] (const TaggedString& formattedText, WritingModeType writingMode, SymbolAnchorType textAnchor, TextJustifyType textJustify) {
auto applyShaping = [&](const TaggedString& formattedText,
WritingModeType writingMode,
SymbolAnchorType textAnchor,
TextJustifyType textJustify) {
const Shaping result = getShaping(
/* string */ formattedText,
/* maxWidth: ems */ isPointPlacement ? layout->evaluate<TextMaxWidth>(zoom, feature) * util::ONE_EM : 0.0f,
/* maxWidth: ems */
isPointPlacement ? layout->evaluate<TextMaxWidth>(zoom, feature) * util::ONE_EM : 0.0f,
/* ems */ lineHeight,
textAnchor,
textJustify,
@@ -370,10 +376,13 @@ void SymbolLayout::prepareSymbols(const GlyphMap& glyphMap, const GlyphPositions
/* writingMode */ writingMode,
/* bidirectional algorithm object */ bidi,
/* glyphs */ glyphMap,
/* images */ imagePositions,
layoutTextSize,
allowVerticalPlacement);
return result;
};
const std::vector<style::TextVariableAnchorType> variableTextAnchor = layout->evaluate<TextVariableAnchor>(zoom, feature);
const SymbolAnchorType textAnchor = layout->evaluate<TextAnchor>(zoom, feature);
if (variableTextAnchor.empty()) {
@@ -475,7 +484,15 @@ void SymbolLayout::prepareSymbols(const GlyphMap& glyphMap, const GlyphPositions
// if either shapedText or icon position is present, add the feature
if (getDefaultHorizontalShaping(shapedTextOrientations) || shapedIcon) {
addFeature(std::distance(features.begin(), it), feature, shapedTextOrientations, std::move(shapedIcon), glyphPositions, textOffset, iconType);
addFeature(std::distance(features.begin(), it),
feature,
shapedTextOrientations,
std::move(shapedIcon),
glyphPositions,
textOffset,
layoutTextSize,
layoutIconSize,
iconType);
}
feature.geometry.clear();
@@ -490,13 +507,12 @@ void SymbolLayout::addFeature(const std::size_t layoutFeatureIndex,
optional<PositionedIcon> shapedIcon,
const GlyphPositions& glyphPositions,
std::array<float, 2> textOffset,
float layoutTextSize,
float layoutIconSize,
const SymbolContent iconType) {
const float minScale = 0.5f;
const float glyphSize = 24.0f;
const float layoutTextSize = layout->evaluate<TextSize>(zoom + 1, feature);
const float layoutIconSize = layout->evaluate<IconSize>(zoom + 1, feature);
const std::array<float, 2> iconOffset = layout->evaluate<IconOffset>(zoom, feature);
// To reduce the number of labels that jump around when zooming we need

View File

@@ -62,6 +62,8 @@ private:
optional<PositionedIcon> shapedIcon,
const GlyphPositions&,
std::array<float, 2> textOffset,
float layoutTextSize,
float layoutIconSize,
const SymbolContent iconType);
bool anchorIsTooClose(const std::u16string& text, const float repeatDistance, const Anchor&);

View File

@@ -166,7 +166,9 @@ void justifyLine(std::vector<PositionedGlyph>& positionedGlyphs,
float determineAverageLineWidth(const TaggedString& logicalInput,
const float spacing,
float maxWidth,
const GlyphMap& glyphMap) {
const GlyphMap& glyphMap,
const ImagePositions& /*imagePositions*/,
float /*layoutTextSize*/) {
float totalWidth = 0;
for (std::size_t i = 0; i < logicalInput.length(); i++) {
@@ -279,7 +281,9 @@ std::set<std::size_t> leastBadBreaks(const PotentialBreak& lastLineBreak) {
std::set<std::size_t> determineLineBreaks(const TaggedString& logicalInput,
const float spacing,
float maxWidth,
const GlyphMap& glyphMap) {
const GlyphMap& glyphMap,
const ImagePositions& imagePositions,
float layoutTextSize) {
if (!maxWidth) {
return {};
}
@@ -287,9 +291,10 @@ std::set<std::size_t> determineLineBreaks(const TaggedString& logicalInput,
if (logicalInput.empty()) {
return {};
}
const float targetWidth = determineAverageLineWidth(logicalInput, spacing, maxWidth, glyphMap);
const float targetWidth =
determineAverageLineWidth(logicalInput, spacing, maxWidth, glyphMap, imagePositions, layoutTextSize);
std::list<PotentialBreak> potentialBreaks;
float currentX = 0;
// Find first occurance of zero width space (ZWSP) character.
@@ -332,6 +337,8 @@ void shapeLines(Shaping& shaping,
const style::TextJustifyType textJustify,
const WritingModeType writingMode,
const GlyphMap& glyphMap,
const ImagePositions& /*imagePositions*/,
float /*layoutTextSize*/,
bool allowVerticalPlacement) {
float x = 0;
float y = Shaping::yOffset;
@@ -425,27 +432,39 @@ const Shaping getShaping(const TaggedString& formattedString,
const WritingModeType writingMode,
BiDi& bidi,
const GlyphMap& glyphs,
const ImagePositions& imagePositions,
float layoutTextSize,
bool allowVerticalPlacement) {
std::vector<TaggedString> reorderedLines;
if (formattedString.sectionCount() == 1) {
auto untaggedLines = bidi.processText(formattedString.rawText(),
determineLineBreaks(formattedString, spacing, maxWidth, glyphs));
auto untaggedLines = bidi.processText(
formattedString.rawText(),
determineLineBreaks(formattedString, spacing, maxWidth, glyphs, imagePositions, layoutTextSize));
for (const auto& line : untaggedLines) {
reorderedLines.emplace_back(line, formattedString.sectionAt(0));
}
} else {
auto processedLines = bidi.processStyledText(formattedString.getStyledText(),
determineLineBreaks(formattedString, spacing, maxWidth, glyphs));
auto processedLines = bidi.processStyledText(
formattedString.getStyledText(),
determineLineBreaks(formattedString, spacing, maxWidth, glyphs, imagePositions, layoutTextSize));
for (const auto& line : processedLines) {
reorderedLines.emplace_back(line, formattedString.getSections());
}
}
Shaping shaping(translate[0], translate[1], writingMode, reorderedLines.size());
shapeLines(shaping, reorderedLines, spacing, lineHeight, textAnchor,
textJustify, writingMode, glyphs, allowVerticalPlacement);
shapeLines(shaping,
reorderedLines,
spacing,
lineHeight,
textAnchor,
textJustify,
writingMode,
glyphs,
imagePositions,
layoutTextSize,
allowVerticalPlacement);
return shaping;
}
} // namespace mbgl

View File

@@ -69,6 +69,8 @@ const Shaping getShaping(const TaggedString& string,
const WritingModeType,
BiDi& bidi,
const GlyphMap& glyphs,
const ImagePositions& imagePositions,
float layoutTextSize,
bool allowVerticalPlacement);
} // namespace mbgl

View File

@@ -26,17 +26,21 @@ TEST(Shaping, ZWSP) {
{ FontStackHasher()(fontStack), {{u'中', std::move(immutableGlyph)}} }
};
const auto testGetShaping = [&] (const TaggedString& string, unsigned maxWidthInChars) {
ImagePositions imagePositions;
const auto testGetShaping = [&](const TaggedString& string, unsigned maxWidthInChars) {
return getShaping(string,
maxWidthInChars * ONE_EM,
ONE_EM, // lineHeight
ONE_EM, // lineHeight
style::SymbolAnchorType::Center,
style::TextJustifyType::Center,
0, // spacing
0, // spacing
{{0.0f, 0.0f}}, // translate
WritingModeType::Horizontal,
bidi,
glyphs,
imagePositions,
16.0,
/*allowVerticalPlacement*/ false);
};