/* * Copyright 2019 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "paragraph_skia.h" #include 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(txt::FontWeight::w100), static_cast(txt::FontWeight::w900)); return static_cast(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(skia.getDecorationType()); txt.decoration_color = skia.getDecorationColor(); txt.decoration_style = static_cast(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(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.fBlurSigma; shadow.color = skia_shadow.fColor; txt.text_shadows.emplace_back(shadow); } return txt; } } // anonymous namespace ParagraphSkia::ParagraphSkia(std::unique_ptr paragraph) : paragraph_(std::move(paragraph)) {} double ParagraphSkia::GetMaxWidth() { return SkScalarToDouble(paragraph_->getMaxWidth()); } double ParagraphSkia::GetHeight() { return SkScalarToDouble(paragraph_->getHeight()); } double ParagraphSkia::GetLongestLine() { return SkScalarToDouble(paragraph_->getLongestLine()); } std::vector& ParagraphSkia::GetLineMetrics() { if (!line_metrics_) { std::vector 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 SkScalarToDouble(paragraph_->getMinIntrinsicWidth()); } double ParagraphSkia::GetMaxIntrinsicWidth() { return SkScalarToDouble(paragraph_->getMaxIntrinsicWidth()); } double ParagraphSkia::GetAlphabeticBaseline() { return SkScalarToDouble(paragraph_->getAlphabeticBaseline()); } double ParagraphSkia::GetIdeographicBaseline() { return SkScalarToDouble(paragraph_->getIdeographicBaseline()); } bool ParagraphSkia::DidExceedMaxLines() { return paragraph_->didExceedMaxLines(); } void ParagraphSkia::Layout(double width) { paragraph_->layout(width); } void ParagraphSkia::Paint(SkCanvas* canvas, double x, double y) { paragraph_->paint(canvas, x, y); } std::vector ParagraphSkia::GetRectsForRange( size_t start, size_t end, RectHeightStyle rect_height_style, RectWidthStyle rect_width_style) { std::vector skia_boxes = paragraph_->getRectsForRange( start, end, static_cast(rect_height_style), static_cast(rect_width_style)); std::vector boxes; for (const skt::TextBox& skia_box : skia_boxes) { boxes.emplace_back(skia_box.rect, static_cast(skia_box.direction)); } return boxes; } std::vector ParagraphSkia::GetRectsForPlaceholders() { std::vector skia_boxes = paragraph_->getRectsForPlaceholders(); std::vector boxes; for (const skt::TextBox& skia_box : skia_boxes) { boxes.emplace_back(skia_box.rect, static_cast(skia_box.direction)); } return boxes; } Paragraph::PositionWithAffinity ParagraphSkia::GetGlyphPositionAtCoordinate( double dx, double dy) { skt::PositionWithAffinity skia_pos = paragraph_->getGlyphPositionAtCoordinate(dx, dy); return ParagraphSkia::PositionWithAffinity( skia_pos.position, static_cast(skia_pos.affinity)); } Paragraph::Range ParagraphSkia::GetWordBoundary(size_t offset) { skt::SkRange range = paragraph_->getWordBoundary(offset); return Paragraph::Range(range.start, range.end); } } // namespace txt