[core] Render half-width glyphs in upright orientation

This change forces glyphs whose natural orientation in vertical writing
mode is 'sideways' to be rendered in upright orientation (only for non complex
text layouts). This is different compared to W3C / browser behavior that is by
default, renders glyphs in their respective natural orientation.

In the future, there  might need to add a new layout property that would control
glyph orientation separately (e.g., text-glyph-orientation: natural | upright).
This commit is contained in:
Alexander Shalamov
2019-08-04 14:44:22 +03:00
parent 03bb17f8c5
commit 1b9d4d792c
6 changed files with 31 additions and 8 deletions

View File

@@ -314,7 +314,8 @@ void SymbolLayout::prepareSymbols(const GlyphMap& glyphMap, const GlyphPositions
/* translate */ textOffset,
/* writingMode */ writingMode,
/* bidirectional algorithm object */ bidi,
/* glyphs */ glyphMap);
/* glyphs */ glyphMap,
allowVerticalPlacement);
return result;
};

View File

@@ -160,7 +160,11 @@ SymbolQuads getGlyphQuads(const Shaping& shapedText,
const Point<float> center{ -halfAdvance, halfAdvance - Shaping::yOffset };
const float verticalRotation = -M_PI_2;
const Point<float> xOffsetCorrection{ 5.0f - Shaping::yOffset, 0.0f };
// xHalfWidhtOffsetcorrection is a difference between full-width and half-width
// advance, should be 0 for full-width glyphs and will pull up half-width glyphs.
const float xHalfWidhtOffsetcorrection = util::ONE_EM / 2 - halfAdvance;
const Point<float> xOffsetCorrection{ 5.0f - Shaping::yOffset - xHalfWidhtOffsetcorrection, 0.0f };
tl = util::rotate(tl - center, verticalRotation) + center + xOffsetCorrection + verticalizedLabelOffset;
tr = util::rotate(tr - center, verticalRotation) + center + xOffsetCorrection + verticalizedLabelOffset;

View File

@@ -290,7 +290,8 @@ void shapeLines(Shaping& shaping,
const style::SymbolAnchorType textAnchor,
const style::TextJustifyType textJustify,
const WritingModeType writingMode,
const GlyphMap& glyphMap) {
const GlyphMap& glyphMap,
bool allowVerticalPlacement) {
float x = 0;
float y = Shaping::yOffset;
@@ -332,8 +333,13 @@ void shapeLines(Shaping& shaping,
const double baselineOffset = (lineMaxScale - section.scale) * util::ONE_EM;
const Glyph& glyph = **it->second;
if (writingMode == WritingModeType::Horizontal || !util::i18n::hasUprightVerticalOrientation(codePoint)) {
if (writingMode == WritingModeType::Horizontal ||
// Don't verticalize glyphs that have no upright orientation if vertical placement is disabled.
(!allowVerticalPlacement && !util::i18n::hasUprightVerticalOrientation(codePoint)) ||
// If vertical placement is ebabled, don't verticalize glyphs that
// are from complex text layout script, or whitespaces.
(allowVerticalPlacement && (util::i18n::isWhitespace(codePoint) || util::i18n::isCharInComplexShapingScript(codePoint)))) {
shaping.positionedGlyphs.emplace_back(codePoint, x, y + baselineOffset, false, section.fontStackHash, section.scale, sectionIndex);
x += glyph.metrics.advance * section.scale + spacing;
} else {
@@ -377,7 +383,8 @@ const Shaping getShaping(const TaggedString& formattedString,
const Point<float>& translate,
const WritingModeType writingMode,
BiDi& bidi,
const GlyphMap& glyphs) {
const GlyphMap& glyphs,
bool allowVerticalPlacement) {
std::vector<TaggedString> reorderedLines;
if (formattedString.sectionCount() == 1) {
auto untaggedLines = bidi.processText(formattedString.rawText(),
@@ -394,7 +401,7 @@ const Shaping getShaping(const TaggedString& formattedString,
}
Shaping shaping(translate.x, translate.y, writingMode, reorderedLines.size());
shapeLines(shaping, reorderedLines, spacing, lineHeight, textAnchor,
textJustify, writingMode, glyphs);
textJustify, writingMode, glyphs, allowVerticalPlacement);
return shaping;
}

View File

@@ -69,6 +69,7 @@ const Shaping getShaping(const TaggedString& string,
const Point<float>& translate,
const WritingModeType,
BiDi& bidi,
const GlyphMap& glyphs);
const GlyphMap& glyphs,
bool allowVerticalPlacement);
} // namespace mbgl

View File

@@ -643,6 +643,14 @@ bool isStringInSupportedScript(const std::string& input) {
return true;
}
bool isCharInComplexShapingScript(char16_t chr) {
return isInArabic(chr) ||
isInArabicSupplement(chr) ||
isInArabicExtendedA(chr) ||
isInArabicPresentationFormsA(chr) ||
isInArabicPresentationFormsB(chr);
}
bool isWhitespace(char16_t chr) {
return chr == u' ' || chr == u'\t' || chr == u'\n' || chr == u'\v' || chr == u'\f' || chr == u'\r';
}

View File

@@ -75,6 +75,8 @@ char16_t verticalizePunctuation(char16_t chr);
bool isStringInSupportedScript(const std::string& input);
bool isCharInComplexShapingScript(char16_t chr);
bool isWhitespace(char16_t chr);
} // namespace i18n