未验证 提交 ed392808 编写于 作者: J Jason Simmons 提交者: GitHub

Integration with more of Skia's SkShaper/SkParagraph APIs (#13008)

Based on https://github.com/Rusino/engine/tree/temp
上级 0b6aa5e3
......@@ -16,40 +16,137 @@
#include "paragraph_skia.h"
#include <algorithm>
namespace txt {
namespace skt = skia::textlayout;
namespace {
// Convert SkFontStyle::Weight values (ranging from 100-900) to txt::FontWeight
// values (ranging from 0-8).
txt::FontWeight GetTxtFontWeight(int font_weight) {
int txt_weight = (font_weight - 100) / 100;
txt_weight = std::clamp(txt_weight, static_cast<int>(txt::FontWeight::w100),
static_cast<int>(txt::FontWeight::w900));
return static_cast<txt::FontWeight>(txt_weight);
}
txt::FontStyle GetTxtFontStyle(SkFontStyle::Slant font_slant) {
return font_slant == SkFontStyle::Slant::kUpright_Slant
? txt::FontStyle::normal
: txt::FontStyle::italic;
}
TextStyle SkiaToTxt(const skt::TextStyle& skia) {
TextStyle txt;
txt.color = skia.getColor();
txt.decoration = static_cast<TextDecoration>(skia.getDecorationType());
txt.decoration_color = skia.getDecorationColor();
txt.decoration_style =
static_cast<TextDecorationStyle>(skia.getDecorationStyle());
txt.decoration_thickness_multiplier =
SkScalarToDouble(skia.getDecorationThicknessMultiplier());
txt.font_weight = GetTxtFontWeight(skia.getFontStyle().weight());
txt.font_style = GetTxtFontStyle(skia.getFontStyle().slant());
txt.text_baseline = static_cast<TextBaseline>(skia.getTextBaseline());
for (const SkString& font_family : skia.getFontFamilies()) {
txt.font_families.emplace_back(font_family.c_str());
}
txt.font_size = SkScalarToDouble(skia.getFontSize());
txt.letter_spacing = SkScalarToDouble(skia.getLetterSpacing());
txt.word_spacing = SkScalarToDouble(skia.getWordSpacing());
txt.height = SkScalarToDouble(skia.getHeight());
txt.locale = skia.getLocale().c_str();
if (skia.hasBackground()) {
txt.background = skia.getBackground();
}
if (skia.hasForeground()) {
txt.foreground = skia.getForeground();
}
txt.text_shadows.clear();
for (const skt::TextShadow& skia_shadow : skia.getShadows()) {
txt::TextShadow shadow;
shadow.offset = skia_shadow.fOffset;
shadow.blur_radius = skia_shadow.fBlurRadius;
shadow.color = skia_shadow.fColor;
txt.text_shadows.emplace_back(shadow);
}
return txt;
}
} // anonymous namespace
ParagraphSkia::ParagraphSkia(std::unique_ptr<skt::Paragraph> paragraph)
: paragraph_(std::move(paragraph)) {}
double ParagraphSkia::GetMaxWidth() {
return paragraph_->getMaxWidth();
return SkScalarToDouble(paragraph_->getMaxWidth());
}
double ParagraphSkia::GetHeight() {
return paragraph_->getHeight();
return SkScalarToDouble(paragraph_->getHeight());
}
double ParagraphSkia::GetLongestLine() {
// TODO: implement
return 0;
return SkScalarToDouble(paragraph_->getLongestLine());
}
std::vector<LineMetrics>& ParagraphSkia::GetLineMetrics() {
if (!line_metrics_) {
std::vector<skt::LineMetrics> metrics;
paragraph_->getLineMetrics(metrics);
line_metrics_.emplace();
for (const skt::LineMetrics& skm : metrics) {
LineMetrics& txtm = line_metrics_->emplace_back(
skm.fStartIndex, skm.fEndIndex, skm.fEndExcludingWhitespaces,
skm.fEndIncludingNewline, skm.fHardBreak);
txtm.ascent = skm.fAscent;
txtm.descent = skm.fDescent;
txtm.unscaled_ascent = skm.fUnscaledAscent;
txtm.height = skm.fHeight;
txtm.width = skm.fWidth;
txtm.left = skm.fLeft;
txtm.baseline = skm.fBaseline;
txtm.line_number = skm.fLineNumber;
for (const auto& sk_iter : skm.fLineMetrics) {
const skt::StyleMetrics& sk_style_metrics = sk_iter.second;
line_metrics_styles_.push_back(SkiaToTxt(*sk_style_metrics.text_style));
txtm.run_metrics.emplace(
std::piecewise_construct, std::forward_as_tuple(sk_iter.first),
std::forward_as_tuple(&line_metrics_styles_.back(),
sk_style_metrics.font_metrics));
}
}
}
return line_metrics_.value();
}
double ParagraphSkia::GetMinIntrinsicWidth() {
return paragraph_->getMinIntrinsicWidth();
return SkScalarToDouble(paragraph_->getMinIntrinsicWidth());
}
double ParagraphSkia::GetMaxIntrinsicWidth() {
return paragraph_->getMaxIntrinsicWidth();
return SkScalarToDouble(paragraph_->getMaxIntrinsicWidth());
}
double ParagraphSkia::GetAlphabeticBaseline() {
return paragraph_->getAlphabeticBaseline();
return SkScalarToDouble(paragraph_->getAlphabeticBaseline());
}
double ParagraphSkia::GetIdeographicBaseline() {
return paragraph_->getIdeographicBaseline();
return SkScalarToDouble(paragraph_->getIdeographicBaseline());
}
bool ParagraphSkia::DidExceedMaxLines() {
......@@ -83,8 +180,15 @@ std::vector<Paragraph::TextBox> ParagraphSkia::GetRectsForRange(
}
std::vector<Paragraph::TextBox> ParagraphSkia::GetRectsForPlaceholders() {
// TODO: implement
return {};
std::vector<skt::TextBox> skia_boxes = paragraph_->getRectsForPlaceholders();
std::vector<Paragraph::TextBox> boxes;
for (const skt::TextBox skia_box : skia_boxes) {
boxes.emplace_back(skia_box.rect,
static_cast<TextDirection>(skia_box.direction));
}
return boxes;
}
Paragraph::PositionWithAffinity ParagraphSkia::GetGlyphPositionAtCoordinate(
......
......@@ -44,6 +44,8 @@ class ParagraphSkia : public Paragraph {
double GetIdeographicBaseline() override;
std::vector<LineMetrics>& GetLineMetrics() override;
bool DidExceedMaxLines() override;
void Layout(double width) override;
......@@ -65,6 +67,8 @@ class ParagraphSkia : public Paragraph {
private:
std::unique_ptr<skia::textlayout::Paragraph> paragraph_;
std::optional<std::vector<LineMetrics>> line_metrics_;
std::vector<TextStyle> line_metrics_styles_;
};
} // namespace txt
......
......@@ -27,7 +27,7 @@ class RunMetrics {
public:
RunMetrics(const TextStyle* style) : text_style(style) {}
RunMetrics(const TextStyle* style, SkFontMetrics& metrics)
RunMetrics(const TextStyle* style, const SkFontMetrics& metrics)
: text_style(style), font_metrics(metrics) {}
const TextStyle* text_style;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册