[skottie] Shaper downscale-to-fit vertical alignment mode

Introduce a new hybrid valign extension, kVisualDownscaleToFit (sk_vj: 4):

  - when the text shaped at the requested size fits within the box,
    center vertically (same as kVisualCenter)
  - otherwise, scale down until it fits (same as kVisualResizeToFit)

Change-Id: I8e096a49e2b87582e1bd42161657ec4ef561ebdf
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/235601
Reviewed-by: Ben Wagner <bungeman@google.com>
Commit-Queue: Florin Malita <fmalita@chromium.org>
This commit is contained in:
Florin Malita 2019-08-19 13:27:16 -04:00 committed by Skia Commit-Bot
parent aae845f219
commit b9fb29f21e
4 changed files with 9651 additions and 11 deletions

View File

@ -171,7 +171,6 @@ public:
return box;
};
// Only ShapeToFit cares about the result height, and it uses kVisualCenter.
SkASSERT(!shaped_height || fDesc.fVAlign == Shaper::VAlign::kVisualCenter);
// Perform additional adjustments based on VAlign.
@ -197,6 +196,7 @@ public:
v_offset = fBox.fBottom - extent_box().fBottom;
break;
case Shaper::VAlign::kVisualResizeToFit:
case Shaper::VAlign::kVisualDownscaleToFit:
SkASSERT(false);
break;
}
@ -406,16 +406,35 @@ Shaper::Result ShapeToFit(const SkString& txt, const Shaper::TextDesc& orig_desc
Shaper::Result Shaper::Shape(const SkString& txt, const TextDesc& desc, const SkPoint& point,
const sk_sp<SkFontMgr>& fontmgr) {
return (desc.fVAlign == VAlign::kVisualResizeToFit) // makes no sense in point mode
return (desc.fVAlign == VAlign::kVisualResizeToFit ||
desc.fVAlign == VAlign::kVisualDownscaleToFit) // makes no sense in point mode
? Result()
: ShapeImpl(txt, desc, SkRect::MakeEmpty().makeOffset(point.x(), point.y()), fontmgr);
}
Shaper::Result Shaper::Shape(const SkString& txt, const TextDesc& desc, const SkRect& box,
const sk_sp<SkFontMgr>& fontmgr) {
return (desc.fVAlign == VAlign::kVisualResizeToFit)
? ShapeToFit(txt, desc, box, fontmgr)
: ShapeImpl(txt, desc, box, fontmgr);
if (desc.fVAlign == VAlign::kVisualResizeToFit) {
return ShapeToFit(txt, desc, box, fontmgr);
}
if (desc.fVAlign == VAlign::kVisualDownscaleToFit) {
auto adjusted_desc = desc;
adjusted_desc.fVAlign = VAlign::kVisualCenter;
float height;
auto result = ShapeImpl(txt, adjusted_desc, box, fontmgr, &height);
if (height <= box.height()) {
return result;
}
adjusted_desc.fVAlign = VAlign::kVisualResizeToFit;
return ShapeToFit(txt, adjusted_desc, box, fontmgr);
}
return ShapeImpl(txt, desc, box, fontmgr);
}
SkRect Shaper::Result::computeVisualBounds() const {

View File

@ -63,6 +63,9 @@ public:
kVisualBottom,
// Resize the text such that the extent box fits (snuggly) in the text box.
kVisualResizeToFit,
// Same kVisualResizeToFit if the text doesn't fit at the specified font size.
// Otherwise, same as kVisualCenter.
kVisualDownscaleToFit,
};
enum Flags : uint32_t {

View File

@ -72,14 +72,20 @@ bool ValueTraits<TextValue>::FromJSON(const skjson::Value& jv,
// Skia vertical alignment extension "sk_vj":
static constexpr Shaper::VAlign gVAlignMap[] = {
Shaper::VAlign::kVisualTop, // 'sk_vj': 0
Shaper::VAlign::kVisualCenter, // 'sk_vj': 1
Shaper::VAlign::kVisualBottom, // 'sk_vj': 2
Shaper::VAlign::kVisualResizeToFit, // 'sk_vj': 3
Shaper::VAlign::kVisualTop, // 'sk_vj': 0
Shaper::VAlign::kVisualCenter, // 'sk_vj': 1
Shaper::VAlign::kVisualBottom, // 'sk_vj': 2
Shaper::VAlign::kVisualResizeToFit, // 'sk_vj': 3
Shaper::VAlign::kVisualDownscaleToFit, // 'sk_vj': 4
};
size_t sk_vj;
if (Parse((*jtxt)["sk_vj"], &sk_vj) && sk_vj < SK_ARRAY_COUNT(gVAlignMap)) {
v->fVAlign = gVAlignMap[sk_vj];
if (Parse((*jtxt)["sk_vj"], &sk_vj)) {
if (sk_vj < SK_ARRAY_COUNT(gVAlignMap)) {
v->fVAlign = gVAlignMap[sk_vj];
} else {
abuilder->log(Logger::Level::kWarning, nullptr,
"Ignoring unknown 'sk_vj' value: %zu", sk_vj);
}
}
const auto& parse_color = [] (const skjson::ArrayValue* jcolor,

File diff suppressed because it is too large Load Diff