[skottie] Use explicit font ascent in Shaper
Bodymovin exports an explicit ascent for each font, as a percentage of
the text size.
Change-Id: I25708944b2b79b42a6ccb05abbe002685e36dfa1
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/223986
Reviewed-by: Ben Wagner <bungeman@google.com>
diff --git a/modules/skottie/src/SkottiePriv.h b/modules/skottie/src/SkottiePriv.h
index d2b23b2..cc24fac 100644
--- a/modules/skottie/src/SkottiePriv.h
+++ b/modules/skottie/src/SkottiePriv.h
@@ -53,7 +53,15 @@
std::unique_ptr<sksg::Scene> parse(const skjson::ObjectValue&);
- sk_sp<SkTypeface> findFont(const SkString& name) const;
+ struct FontInfo {
+ SkString fFamily,
+ fStyle;
+ SkScalar fAscentPct;
+ sk_sp<SkTypeface> fTypeface;
+
+ bool matches(const char family[], const char style[]) const;
+ };
+ const FontInfo* findFont(const SkString& name) const;
// This is the workhorse for property binding: depending on whether the property is animated,
// it will either apply immediately or instantiate and attach a keyframe animator.
@@ -195,15 +203,6 @@
mutable bool fIsAttaching; // Used for cycle detection
};
- struct FontInfo {
- SkString fFamily,
- fStyle;
- SkScalar fAscent;
- sk_sp<SkTypeface> fTypeface;
-
- bool matches(const char family[], const char style[]) const;
- };
-
struct ImageAssetInfo {
sk_sp<ImageAsset> fAsset;
SkISize fSize;
diff --git a/modules/skottie/src/SkottieTest.cpp b/modules/skottie/src/SkottieTest.cpp
index 72069d5..a8934dd 100644
--- a/modules/skottie/src/SkottieTest.cpp
+++ b/modules/skottie/src/SkottieTest.cpp
@@ -294,6 +294,7 @@
typeface,
tsize.text_size,
tsize.text_size,
+ 0,
talign.align,
skottie::Shaper::VAlign::kTopBaseline,
Shaper::Flags::kNone
@@ -357,6 +358,7 @@
typeface,
tsize.text_size,
tsize.text_size,
+ 0,
SkTextUtils::Align::kCenter_Align,
talign.align,
Shaper::Flags::kNone
@@ -391,6 +393,7 @@
SkTypeface::MakeDefault(),
18,
18,
+ 0,
SkTextUtils::Align::kCenter_Align,
Shaper::VAlign::kTop,
Shaper::Flags::kNone
diff --git a/modules/skottie/src/text/SkottieShaper.cpp b/modules/skottie/src/text/SkottieShaper.cpp
index fb2b48b..862785f 100644
--- a/modules/skottie/src/text/SkottieShaper.cpp
+++ b/modules/skottie/src/text/SkottieShaper.cpp
@@ -115,26 +115,30 @@
fResult.fFragments.push_back({fBuilder.make(), {fBox.x(), fBox.y()}, 0, false});
}
+ // Use the explicit ascent, when specified.
+ // Note: ascent values are negative (relative to the baseline).
+ const auto ascent = fDesc.fAscent ? fDesc.fAscent : fFirstLineAscent;
+
// By default, first line is vertically-aligned on a baseline of 0.
// The content height considered for vertical alignment is the distance between the first
// line top (ascent) to the last line bottom (descent).
- const auto content_height = fLastLineDescent - fFirstLineAscent +
+ const auto content_height = fLastLineDescent - ascent +
fDesc.fLineHeight * (fLineCount > 0 ? fLineCount - 1 : 0ul);
// Perform additional adjustments based on VAlign.
float v_offset = 0;
switch (fDesc.fVAlign) {
case Shaper::VAlign::kTop:
- v_offset = -fFirstLineAscent;
+ v_offset = -ascent;
break;
case Shaper::VAlign::kTopBaseline:
// Default behavior.
break;
case Shaper::VAlign::kCenter:
- v_offset = -fFirstLineAscent + (fBox.height() - content_height) * 0.5f;
+ v_offset = -ascent + (fBox.height() - content_height) * 0.5f;
break;
case Shaper::VAlign::kBottom:
- v_offset = -fFirstLineAscent + (fBox.height() - content_height);
+ v_offset = -ascent + (fBox.height() - content_height);
break;
case Shaper::VAlign::kResizeToFit:
SkASSERT(false);
@@ -310,6 +314,7 @@
SkASSERT(try_scale >= in_scale && try_scale <= out_scale);
desc.fTextSize = try_scale * orig_desc.fTextSize;
desc.fLineHeight = try_scale * orig_desc.fLineHeight;
+ desc.fAscent = try_scale * orig_desc.fAscent;
float res_height = 0;
auto res = ShapeImpl(txt, desc, box, &res_height);
diff --git a/modules/skottie/src/text/SkottieShaper.h b/modules/skottie/src/text/SkottieShaper.h
index a919e43..64d624a 100644
--- a/modules/skottie/src/text/SkottieShaper.h
+++ b/modules/skottie/src/text/SkottieShaper.h
@@ -59,7 +59,8 @@
struct TextDesc {
const sk_sp<SkTypeface>& fTypeface;
SkScalar fTextSize,
- fLineHeight;
+ fLineHeight,
+ fAscent;
SkTextUtils::Align fHAlign;
VAlign fVAlign;
uint32_t fFlags;
diff --git a/modules/skottie/src/text/TextAdapter.cpp b/modules/skottie/src/text/TextAdapter.cpp
index 58556d4..a3ee5b3 100644
--- a/modules/skottie/src/text/TextAdapter.cpp
+++ b/modules/skottie/src/text/TextAdapter.cpp
@@ -123,6 +123,7 @@
fText.fTypeface,
fText.fTextSize,
fText.fLineHeight,
+ fText.fAscent,
fText.fHAlign,
fText.fVAlign,
fHasAnimators ? Shaper::Flags::kFragmentGlyphs : Shaper::Flags::kNone,
diff --git a/modules/skottie/src/text/TextLayer.cpp b/modules/skottie/src/text/TextLayer.cpp
index 6acc3ec..be17d77 100644
--- a/modules/skottie/src/text/TextLayer.cpp
+++ b/modules/skottie/src/text/TextLayer.cpp
@@ -244,13 +244,8 @@
}
}
-sk_sp<SkTypeface> AnimationBuilder::findFont(const SkString& font_name) const {
- if (const auto* font = fFonts.find(font_name)) {
- return font->fTypeface;
- }
-
- this->log(Logger::Level::kError, nullptr, "Unknown font: \"%s\".", font_name.c_str());
- return nullptr;
+const AnimationBuilder::FontInfo* AnimationBuilder::findFont(const SkString& font_name) const {
+ return fFonts.find(font_name);
}
sk_sp<sksg::RenderNode> AnimationBuilder::attachTextLayer(const skjson::ObjectValue& layer,
diff --git a/modules/skottie/src/text/TextValue.cpp b/modules/skottie/src/text/TextValue.cpp
index 0229d75..b53b26b 100644
--- a/modules/skottie/src/text/TextValue.cpp
+++ b/modules/skottie/src/text/TextValue.cpp
@@ -44,13 +44,21 @@
const skjson::StringValue* text = (*jtxt)["t"];
const skjson::NumberValue* text_size = (*jtxt)["s"];
const skjson::NumberValue* line_height = (*jtxt)["lh"];
- if (!font_name || !text || !text_size || !line_height ||
- !(v->fTypeface = abuilder->findFont(SkString(font_name->begin(), font_name->size())))) {
+ if (!font_name || !text || !text_size || !line_height) {
return false;
}
+
+ const auto* font = abuilder->findFont(SkString(font_name->begin(), font_name->size()));
+ if (!font) {
+ abuilder->log(Logger::Level::kError, nullptr, "Unknown font: \"%s\".", font_name->begin());
+ return false;
+ }
+
v->fText.set(text->begin(), text->size());
v->fTextSize = **text_size;
v->fLineHeight = **line_height;
+ v->fTypeface = font->fTypeface;
+ v->fAscent = font->fAscentPct * -0.01f * v->fTextSize; // negative ascent per SkFontMetrics
static constexpr SkTextUtils::Align gAlignMap[] = {
SkTextUtils::kLeft_Align, // 'j': 0
diff --git a/modules/skottie/src/text/TextValue.h b/modules/skottie/src/text/TextValue.h
index 685f7e7..1201956 100644
--- a/modules/skottie/src/text/TextValue.h
+++ b/modules/skottie/src/text/TextValue.h
@@ -20,7 +20,8 @@
SkString fText;
float fTextSize = 0,
fStrokeWidth = 0,
- fLineHeight = 0;
+ fLineHeight = 0,
+ fAscent = 0;
SkTextUtils::Align fHAlign = SkTextUtils::kLeft_Align;
Shaper::VAlign fVAlign = Shaper::VAlign::kTop;
SkRect fBox = SkRect::MakeEmpty();