Skip to content

Commit

Permalink
Support top ratio based vertical alignment
Browse files Browse the repository at this point in the history
  • Loading branch information
MatkovIvan committed Sep 13, 2024
1 parent 1d69d9b commit 5728d39
Show file tree
Hide file tree
Showing 11 changed files with 49 additions and 39 deletions.
15 changes: 9 additions & 6 deletions modules/skparagraph/include/ParagraphStyle.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,17 @@ struct StrutStyle {
bool getHeightOverride() const { return fHeightOverride; }
void setHeightOverride(bool v) { fHeightOverride = v; }

void setHalfLeading(bool halfLeading) { fHalfLeading = halfLeading; }
bool getHalfLeading() const { return fHalfLeading; }
void setHalfLeading(bool halfLeading) { fTopRatio = halfLeading ? 0.5f : -1.0f; }
bool getHalfLeading() const { return fTopRatio == 0.5f; }

void setTopRatio(SkScalar topRatio) { fTopRatio = topRatio; }
SkScalar getTopRatio() const { return fTopRatio; }

bool operator==(const StrutStyle& rhs) const {
return this->fEnabled == rhs.fEnabled &&
this->fHeightOverride == rhs.fHeightOverride &&
this->fForceHeight == rhs.fForceHeight &&
this->fHalfLeading == rhs.fHalfLeading &&
this->fTopRatio == rhs.fTopRatio &&
nearlyEqual(this->fLeading, rhs.fLeading) &&
nearlyEqual(this->fHeight, rhs.fHeight) &&
nearlyEqual(this->fFontSize, rhs.fFontSize) &&
Expand All @@ -71,9 +74,9 @@ struct StrutStyle {
bool fForceHeight;
bool fEnabled;
bool fHeightOverride;
// true: half leading.
// false: scale ascent/descent with fHeight.
bool fHalfLeading;
// [0..1]: the ratio of ascent to ascent+descent
// -1: proportional to the ascent/descent
SkScalar fTopRatio;
};

struct TextIndent {
Expand Down
13 changes: 8 additions & 5 deletions modules/skparagraph/include/TextStyle.h
Original file line number Diff line number Diff line change
Expand Up @@ -264,8 +264,11 @@ class TextStyle {
void setHeightOverride(bool heightOverride) { fHeightOverride = heightOverride; }
bool getHeightOverride() const { return fHeightOverride; }

void setHalfLeading(bool halfLeading) { fHalfLeading = halfLeading; }
bool getHalfLeading() const { return fHalfLeading; }
void setHalfLeading(bool halfLeading) { fTopRatio = halfLeading ? 0.5f : -1.0f; }
bool getHalfLeading() const { return fTopRatio == 0.5f; }

void setTopRatio(SkScalar topRatio) { fTopRatio = topRatio; }
SkScalar getTopRatio() const { return fTopRatio; }

void setLetterSpacing(SkScalar letterSpacing) { fLetterSpacing = letterSpacing; }
SkScalar getLetterSpacing() const { return fLetterSpacing; }
Expand Down Expand Up @@ -312,9 +315,9 @@ class TextStyle {
SkScalar fHeight = 1.0;
bool fHeightOverride = false;
SkScalar fBaselineShift = 0.0f;
// true: half leading.
// false: scale ascent/descent with fHeight.
bool fHalfLeading = false;
// [0..1]: the ratio of ascent to ascent+descent
// -1: proportional to the ascent/descent
SkScalar fTopRatio = -1.0f;
SkString fLocale = {};
SkScalar fLetterSpacing = 0.0;
SkScalar fWordSpacing = 0.0;
Expand Down
4 changes: 2 additions & 2 deletions modules/skparagraph/src/OneLineShaper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ void OneLineShaper::finish(const Block& block, SkScalar height, SkScalar& advanc
info,
run->fClusterStart,
height,
block.fStyle.getHalfLeading(),
block.fStyle.getTopRatio(),
block.fStyle.getBaselineShift(),
this->fParagraph->fRuns.size(),
advanceX
Expand Down Expand Up @@ -639,7 +639,7 @@ bool OneLineShaper::shape() {

// Start from the beginning (hoping that it's a simple case one block - one run)
fHeight = block.fStyle.getHeightOverride() ? block.fStyle.getHeight() : 0;
fUseHalfLeading = block.fStyle.getHalfLeading();
fTopRatio = block.fStyle.getTopRatio();
fBaselineShift = block.fStyle.getBaselineShift();
fAdvance = SkVector::Make(advanceX, 0);
fCurrentText = block.fRange;
Expand Down
6 changes: 3 additions & 3 deletions modules/skparagraph/src/OneLineShaper.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class OneLineShaper : public SkShaper::RunHandler {
explicit OneLineShaper(ParagraphImpl* paragraph)
: fParagraph(paragraph)
, fHeight(0.0f)
, fUseHalfLeading(false)
, fTopRatio(-1.0f)
, fBaselineShift(0.0f)
, fAdvance(SkPoint::Make(0.0f, 0.0f))
, fUnresolvedGlyphs(0)
Expand Down Expand Up @@ -93,7 +93,7 @@ class OneLineShaper : public SkShaper::RunHandler {
info,
fCurrentText.start,
fHeight,
fUseHalfLeading,
fTopRatio,
fBaselineShift,
++fUniqueRunId,
fAdvance.fX);
Expand All @@ -115,7 +115,7 @@ class OneLineShaper : public SkShaper::RunHandler {
ParagraphImpl* fParagraph;
TextRange fCurrentText;
SkScalar fHeight;
bool fUseHalfLeading;
SkScalar fTopRatio;
SkScalar fBaselineShift;
SkVector fAdvance;
size_t fUnresolvedGlyphs;
Expand Down
1 change: 1 addition & 0 deletions modules/skparagraph/src/ParagraphCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ uint32_t ParagraphCacheKey::computeHash() const {
hash = mix(hash, SkGoodHash()(relax(strutStyle.getHeight())));
hash = mix(hash, SkGoodHash()(relax(strutStyle.getLeading())));
hash = mix(hash, SkGoodHash()(relax(strutStyle.getFontSize())));
hash = mix(hash, SkGoodHash()(relax(strutStyle.getTopRatio())));
hash = mix(hash, SkGoodHash()(strutStyle.getHeightOverride()));
hash = mix(hash, SkGoodHash()(strutStyle.getFontStyle()));
hash = mix(hash, SkGoodHash()(strutStyle.getForceStrutHeight()));
Expand Down
17 changes: 10 additions & 7 deletions modules/skparagraph/src/ParagraphImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -707,12 +707,13 @@ void ParagraphImpl::resolveStrut() {
if (strutStyle.getHeightOverride()) {
SkScalar strutAscent = 0.0f;
SkScalar strutDescent = 0.0f;
// The half leading flag doesn't take effect unless there's height override.
if (strutStyle.getHalfLeading()) {
// The top ratio doesn't take effect unless there's height override.
SkScalar topRatio = strutStyle.getTopRatio();
if (topRatio >= 0.0f && topRatio <= 1.0f) {
const auto occupiedHeight = metrics.fDescent - metrics.fAscent;
auto flexibleHeight = strutStyle.getHeight() * strutStyle.getFontSize() - occupiedHeight;
// Distribute the flexible height evenly over and under.
flexibleHeight /= 2;
flexibleHeight *= topRatio;
strutAscent = metrics.fAscent - flexibleHeight;
strutDescent = metrics.fDescent + flexibleHeight;
} else {
Expand Down Expand Up @@ -1036,11 +1037,13 @@ void ParagraphImpl::computeEmptyMetrics() {
textStyle.getHeightOverride()) {
const auto intrinsicHeight = fEmptyMetrics.height();
const auto strutHeight = textStyle.getHeight() * textStyle.getFontSize();
if (paragraphStyle().getStrutStyle().getHalfLeading()) {
SkScalar topRatio = paragraphStyle().getStrutStyle().getTopRatio();
if (topRatio >= 0.0f && topRatio <= 1.0f) {
const auto extraLeading = (strutHeight - intrinsicHeight) * topRatio;
fEmptyMetrics.update(
fEmptyMetrics.ascent(),
fEmptyMetrics.descent(),
fEmptyMetrics.leading() + strutHeight - intrinsicHeight);
fEmptyMetrics.ascent() - extraLeading,
fEmptyMetrics.descent() + extraLeading,
fEmptyMetrics.leading() + extraLeading * 2.0f);
} else {
const auto multiplier = strutHeight / intrinsicHeight;
fEmptyMetrics.update(
Expand Down
2 changes: 1 addition & 1 deletion modules/skparagraph/src/ParagraphStyle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ StrutStyle::StrutStyle() {
fLeading = -1;
fForceHeight = false;
fHeightOverride = false;
fHalfLeading = false;
fTopRatio = -1.0f;
fEnabled = false;
}

Expand Down
8 changes: 4 additions & 4 deletions modules/skparagraph/src/Run.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Run::Run(ParagraphImpl* owner,
const SkShaper::RunHandler::RunInfo& info,
size_t firstChar,
SkScalar heightMultiplier,
bool useHalfLeading,
SkScalar topRatio,
SkScalar baselineShift,
size_t index,
SkScalar offsetX)
Expand All @@ -33,7 +33,7 @@ Run::Run(ParagraphImpl* owner,
, fOffsets(fGlyphData->offsets)
, fClusterIndexes(fGlyphData->clusterIndexes)
, fHeightMultiplier(heightMultiplier)
, fUseHalfLeading(useHalfLeading)
, fTopRatio(topRatio)
, fBaselineShift(baselineShift)
{
fBidiLevel = info.fBidiLevel;
Expand Down Expand Up @@ -67,8 +67,8 @@ void Run::calculateMetrics() {
}
const auto runHeight = fHeightMultiplier * fFont.getSize();
const auto fontIntrinsicHeight = fCorrectDescent - fCorrectAscent;
if (fUseHalfLeading) {
const auto extraLeading = (runHeight - fontIntrinsicHeight) / 2;
if (fTopRatio >= 0.0f && fTopRatio <= 1.0f) {
const auto extraLeading = (runHeight - fontIntrinsicHeight) * fTopRatio;
fCorrectAscent -= extraLeading;
fCorrectDescent += extraLeading;
} else {
Expand Down
6 changes: 3 additions & 3 deletions modules/skparagraph/src/Run.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class Run {
const SkShaper::RunHandler::RunInfo& info,
size_t firstChar,
SkScalar heightMultiplier,
bool useHalfLeading,
SkScalar topRatio,
SkScalar baselineShift,
size_t index,
SkScalar shiftX);
Expand Down Expand Up @@ -97,7 +97,7 @@ class Run {
TextDirection getTextDirection() const { return leftToRight() ? TextDirection::kLtr : TextDirection::kRtl; }
size_t index() const { return fIndex; }
SkScalar heightMultiplier() const { return fHeightMultiplier; }
bool useHalfLeading() const { return fUseHalfLeading; }
SkScalar topRatio() const { return fTopRatio; }
SkScalar baselineShift() const { return fBaselineShift; }
PlaceholderStyle* placeholderStyle() const;
bool isPlaceholder() const { return fPlaceholderIndex != std::numeric_limits<size_t>::max(); }
Expand Down Expand Up @@ -204,7 +204,7 @@ class Run {

SkFontMetrics fFontMetrics;
const SkScalar fHeightMultiplier;
const bool fUseHalfLeading;
const SkScalar fTopRatio;
const SkScalar fBaselineShift;
SkScalar fCorrectAscent;
SkScalar fCorrectDescent;
Expand Down
10 changes: 5 additions & 5 deletions modules/skparagraph/src/TextLine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -643,8 +643,8 @@ std::unique_ptr<Run> TextLine::shapeEllipsis(const SkString& ellipsis, const Clu

class ShapeHandler final : public SkShaper::RunHandler {
public:
ShapeHandler(SkScalar lineHeight, bool useHalfLeading, SkScalar baselineShift, const SkString& ellipsis)
: fRun(nullptr), fLineHeight(lineHeight), fUseHalfLeading(useHalfLeading), fBaselineShift(baselineShift), fEllipsis(ellipsis) {}
ShapeHandler(SkScalar lineHeight, SkScalar topRatio, SkScalar baselineShift, const SkString& ellipsis)
: fRun(nullptr), fLineHeight(lineHeight), fTopRatio(topRatio), fBaselineShift(baselineShift), fEllipsis(ellipsis) {}
std::unique_ptr<Run> run() & { return std::move(fRun); }

private:
Expand All @@ -656,7 +656,7 @@ std::unique_ptr<Run> TextLine::shapeEllipsis(const SkString& ellipsis, const Clu

Buffer runBuffer(const RunInfo& info) override {
SkASSERT(!fRun);
fRun = std::make_unique<Run>(nullptr, info, 0, fLineHeight, fUseHalfLeading, fBaselineShift, 0, 0);
fRun = std::make_unique<Run>(nullptr, info, 0, fLineHeight, fTopRatio, fBaselineShift, 0, 0);
return fRun->newRunBuffer();
}

Expand All @@ -671,7 +671,7 @@ std::unique_ptr<Run> TextLine::shapeEllipsis(const SkString& ellipsis, const Clu

std::unique_ptr<Run> fRun;
SkScalar fLineHeight;
bool fUseHalfLeading;
SkScalar fTopRatio;
SkScalar fBaselineShift;
SkString fEllipsis;
};
Expand All @@ -690,7 +690,7 @@ std::unique_ptr<Run> TextLine::shapeEllipsis(const SkString& ellipsis, const Clu
}

auto shaped = [&](sk_sp<SkTypeface> typeface, sk_sp<SkFontMgr> fallback) -> std::unique_ptr<Run> {
ShapeHandler handler(run.heightMultiplier(), run.useHalfLeading(), run.baselineShift(), ellipsis);
ShapeHandler handler(run.heightMultiplier(), run.topRatio(), run.baselineShift(), ellipsis);
SkFont font(std::move(typeface), textStyle.getFontSize());
font.setEdging(SkFont::Edging::kAntiAlias);
font.setHinting(SkFontHinting::kSlight);
Expand Down
6 changes: 3 additions & 3 deletions modules/skparagraph/src/TextStyle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ TextStyle TextStyle::cloneForPlaceholder() {
result.fHeightOverride = fHeightOverride;
result.fIsPlaceholder = true;
result.fFontFeatures = fFontFeatures;
result.fHalfLeading = fHalfLeading;
result.fTopRatio = fTopRatio;
result.fBaselineShift = fBaselineShift;
result.fFontArguments = fFontArguments;
return result;
Expand Down Expand Up @@ -58,7 +58,7 @@ bool TextStyle::equals(const TextStyle& other) const {
if (fHeightOverride != other.fHeightOverride) {
return false;
}
if (fHalfLeading != other.fHalfLeading) {
if (fTopRatio != other.fTopRatio) {
return false;
}
if (fBaselineShift != other.fBaselineShift) {
Expand Down Expand Up @@ -155,7 +155,7 @@ bool TextStyle::matchOneAttribute(StyleType styleType, const TextStyle& other) c
fFontFamilies == other.fFontFamilies &&
fFontSize == other.fFontSize &&
fHeight == other.fHeight &&
fHalfLeading == other.fHalfLeading &&
fTopRatio == other.fTopRatio &&
fBaselineShift == other.fBaselineShift &&
fFontArguments == other.fFontArguments;
default:
Expand Down

0 comments on commit 5728d39

Please sign in to comment.