blob: e451695dc8b6dec4d18bbe3e1d20274b7dd085d9 [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "impeller/typographer/backends/skia/text_frame_skia.h"
#include <vector>
#include "flutter/fml/logging.h"
#include "impeller/typographer/backends/skia/typeface_skia.h"
#include "include/core/SkFontTypes.h"
#include "include/core/SkRect.h"
#include "third_party/skia/include/core/SkFont.h"
#include "third_party/skia/include/core/SkFontMetrics.h"
#include "third_party/skia/src/core/SkStrikeSpec.h" // nogncheck
#include "third_party/skia/src/core/SkTextBlobPriv.h" // nogncheck
namespace impeller {
static Font ToFont(const SkTextBlobRunIterator& run, Scalar scale) {
auto& font = run.font();
auto typeface = std::make_shared<TypefaceSkia>(font.refTypefaceOrDefault());
SkFontMetrics sk_metrics;
font.getMetrics(&sk_metrics);
Font::Metrics metrics;
metrics.scale = scale;
metrics.point_size = font.getSize();
metrics.embolden = font.isEmbolden();
metrics.skewX = font.getSkewX();
metrics.scaleX = font.getScaleX();
return Font{std::move(typeface), metrics};
}
static Rect ToRect(const SkRect& rect) {
return Rect::MakeLTRB(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);
}
TextFrame TextFrameFromTextBlob(const sk_sp<SkTextBlob>& blob, Scalar scale) {
if (!blob) {
return {};
}
TextFrame frame;
for (SkTextBlobRunIterator run(blob.get()); !run.done(); run.next()) {
TextRun text_run(ToFont(run, scale));
// TODO(jonahwilliams): ask Skia for a public API to look this up.
// https://github.com/flutter/flutter/issues/112005
SkStrikeSpec strikeSpec = SkStrikeSpec::MakeWithNoDevice(run.font());
SkBulkGlyphMetricsAndPaths paths{strikeSpec};
const auto glyph_count = run.glyphCount();
const auto* glyphs = run.glyphs();
switch (run.positioning()) {
case SkTextBlobRunIterator::kDefault_Positioning:
FML_DLOG(ERROR) << "Unimplemented.";
break;
case SkTextBlobRunIterator::kHorizontal_Positioning:
FML_DLOG(ERROR) << "Unimplemented.";
break;
case SkTextBlobRunIterator::kFull_Positioning: {
std::vector<SkRect> glyph_bounds;
glyph_bounds.resize(glyph_count);
run.font().getBounds(glyphs, glyph_count, glyph_bounds.data(), nullptr);
for (auto i = 0u; i < glyph_count; i++) {
// kFull_Positioning has two scalars per glyph.
const SkPoint* glyph_points = run.points();
const auto* point = glyph_points + i;
Glyph::Type type = paths.glyph(glyphs[i])->isColor()
? Glyph::Type::kBitmap
: Glyph::Type::kPath;
text_run.AddGlyph(Glyph{glyphs[i], type, ToRect(glyph_bounds[i])},
Point{point->x(), point->y()});
}
break;
}
case SkTextBlobRunIterator::kRSXform_Positioning:
FML_DLOG(ERROR) << "Unimplemented.";
break;
default:
FML_DLOG(ERROR) << "Unimplemented.";
continue;
}
frame.AddTextRun(text_run);
}
return frame;
}
} // namespace impeller