13 #include "flutter/fml/logging.h"
14 #include "flutter/fml/trace_event.h"
15 #include "fml/closure.h"
34 #include "include/core/SkColor.h"
35 #include "include/core/SkImageInfo.h"
36 #include "include/core/SkPaint.h"
37 #include "include/core/SkSize.h"
39 #include "third_party/skia/include/core/SkBitmap.h"
40 #include "third_party/skia/include/core/SkBlendMode.h"
41 #include "third_party/skia/include/core/SkCanvas.h"
42 #include "third_party/skia/include/core/SkFont.h"
43 #include "third_party/skia/include/core/SkSurface.h"
56 return SkPaint::Cap::kButt_Cap;
58 return SkPaint::Cap::kRound_Cap;
60 return SkPaint::Cap::kSquare_Cap;
68 return SkPaint::Join::kMiter_Join;
70 return SkPaint::Join::kRound_Join;
72 return SkPaint::Join::kBevel_Join;
79 return std::make_shared<TypographerContextSkia>();
86 std::shared_ptr<GlyphAtlasContext>
88 return std::make_shared<GlyphAtlasContext>(
type);
94 return SkImageInfo::MakeA8(SkISize{
static_cast<int32_t
>(size.
width),
95 static_cast<int32_t
>(size.
height)});
97 return SkImageInfo::MakeN32Premul(size.
width, size.
height);
105 const std::shared_ptr<GlyphAtlas>& atlas,
106 const std::vector<FontGlyphPair>& extra_pairs,
107 std::vector<Rect>& glyph_positions,
108 const std::vector<Rect>& glyph_sizes,
110 int64_t height_adjustment,
111 const std::shared_ptr<RectanglePacker>& rect_packer) {
112 TRACE_EVENT0(
"impeller", __FUNCTION__);
113 if (!rect_packer || atlas_size.
IsEmpty()) {
117 for (
size_t i = 0; i < extra_pairs.size(); i++) {
128 location_in_atlas.
x() + 1,
129 location_in_atlas.
y() + height_adjustment + 1,
135 return extra_pairs.size();
139 const std::vector<FontGlyphPair>& pairs,
140 const ISize& atlas_size,
141 std::vector<Rect>& glyph_positions,
142 const std::vector<Rect>& glyph_sizes,
143 int64_t height_adjustment,
144 const std::shared_ptr<RectanglePacker>& rect_packer,
145 size_t start_index) {
146 FML_DCHECK(!atlas_size.
IsEmpty());
148 for (
size_t i = start_index; i < pairs.size(); i++) {
158 location_in_atlas.
x() + 1,
159 location_in_atlas.
y() + height_adjustment + 1,
169 const std::shared_ptr<GlyphAtlasContext>& atlas_context,
170 const std::vector<FontGlyphPair>& extra_pairs,
171 std::vector<Rect>& glyph_positions,
172 const std::vector<Rect>& glyph_sizes,
173 size_t glyph_index_start,
174 int64_t max_texture_height) {
177 static constexpr int64_t kAtlasWidth = 4096;
178 static constexpr int64_t kMinAtlasHeight = 1024;
180 ISize current_size =
ISize(kAtlasWidth, kMinAtlasHeight);
181 if (atlas_context->GetAtlasSize().height > current_size.
height) {
182 current_size.
height = atlas_context->GetAtlasSize().height * 2;
185 auto height_adjustment = atlas_context->GetAtlasSize().height;
186 while (current_size.
height <= max_texture_height) {
187 std::shared_ptr<RectanglePacker> rect_packer;
188 if (atlas_context->GetRectPacker() || glyph_index_start) {
191 current_size.
height - atlas_context->GetAtlasSize().height);
195 glyph_positions.erase(glyph_positions.begin() + glyph_index_start,
196 glyph_positions.end());
197 atlas_context->UpdateRectPacker(rect_packer);
199 extra_pairs, current_size, glyph_positions, glyph_sizes,
200 height_adjustment, rect_packer, glyph_index_start);
201 if (next_index == extra_pairs.size()) {
212 const Rect& scaled_bounds,
216 SkPoint position = SkPoint::Make(1, 1);
221 metrics.point_size, metrics.scaleX, metrics.skewX);
222 sk_font.setEdging(SkFont::Edging::kAntiAlias);
223 sk_font.setHinting(SkFontHinting::kSlight);
224 sk_font.setEmbolden(metrics.embolden);
225 sk_font.setSubpixel(
true);
226 sk_font.setSize(sk_font.getSize() * scaled_font.
scale);
232 glyph_paint.setColor(glyph_color);
233 glyph_paint.setBlendMode(SkBlendMode::kSrc);
235 glyph_paint.setStroke(
true);
242 canvas->drawGlyphs(1u,
245 SkPoint::Make(-scaled_bounds.
GetLeft(),
253 std::shared_ptr<BlitPass>& blit_pass,
255 const std::shared_ptr<Texture>& texture,
256 const std::vector<FontGlyphPair>& new_pairs,
259 TRACE_EVENT0(
"impeller", __FUNCTION__);
263 for (
size_t i = start_index; i < end_index; i++) {
266 if (!
data.has_value()) {
269 auto [pos, bounds] =
data.value();
270 Size size = pos.GetSize();
281 if (!bitmap.tryAllocPixels()) {
285 auto surface = SkSurfaces::WrapPixels(bitmap.pixmap());
289 auto canvas = surface->getCanvas();
300 bitmap.getAddr(0, 0),
302 atlas.
GetTexture()->GetTextureDescriptor().format),
319 return blit_pass->ConvertTextureToShaderRead(texture);
325 SkRect scaled_bounds;
328 glyph_paint.setStroke(
true);
334 font.getBounds(&glyph.
glyph.
index, 1, &scaled_bounds, &glyph_paint);
341 return Rect::MakeLTRB(scaled_bounds.fLeft - adjustment, scaled_bounds.fTop,
342 scaled_bounds.fRight + adjustment,
343 scaled_bounds.fBottom);
350 const std::shared_ptr<GlyphAtlasContext>& atlas_context,
352 TRACE_EVENT0(
"impeller", __FUNCTION__);
356 std::shared_ptr<GlyphAtlas> last_atlas = atlas_context->GetGlyphAtlas();
357 FML_DCHECK(last_atlas->GetType() ==
type);
359 if (font_glyph_map.empty()) {
368 std::vector<Rect> glyph_sizes;
369 std::vector<FontGlyphPair> new_glyphs;
370 for (
const auto& font_value : font_glyph_map) {
371 const ScaledFont& scaled_font = font_value.first;
373 last_atlas->GetFontGlyphAtlas(scaled_font.
font, scaled_font.
scale);
379 metrics.point_size, metrics.scaleX, metrics.skewX);
380 sk_font.setEdging(SkFont::Edging::kAntiAlias);
381 sk_font.setHinting(SkFontHinting::kSlight);
382 sk_font.setEmbolden(metrics.embolden);
386 sk_font.setSize(sk_font.getSize() * scaled_font.
scale);
387 sk_font.setSubpixel(
true);
389 if (font_glyph_atlas) {
392 new_glyphs.emplace_back(scaled_font, glyph);
393 glyph_sizes.push_back(
399 new_glyphs.emplace_back(scaled_font, glyph);
400 glyph_sizes.push_back(
405 if (new_glyphs.size() == 0) {
413 std::vector<Rect> glyph_positions;
414 glyph_positions.reserve(new_glyphs.size());
415 size_t first_missing_index = 0;
417 if (last_atlas->GetTexture()) {
420 last_atlas, new_glyphs, glyph_positions, glyph_sizes,
421 atlas_context->GetAtlasSize(), atlas_context->GetHeightAdjustment(),
422 atlas_context->GetRectPacker());
428 for (
size_t i = 0; i < first_missing_index; i++) {
429 last_atlas->AddTypefaceGlyphPositionAndBounds(
430 new_glyphs[i], glyph_positions[i], glyph_sizes[i]);
434 std::shared_ptr<BlitPass> blit_pass = cmd_buffer->CreateBlitPass();
436 fml::ScopedCleanupClosure closure([&]() {
446 last_atlas->GetTexture(), new_glyphs, 0,
447 first_missing_index)) {
452 if (first_missing_index == new_glyphs.size()) {
457 int64_t height_adjustment = atlas_context->GetAtlasSize().height;
458 const int64_t max_texture_height =
466 bool blit_old_atlas =
true;
467 std::shared_ptr<GlyphAtlas> new_atlas = last_atlas;
468 if (atlas_context->GetAtlasSize().height >= max_texture_height ||
470 blit_old_atlas =
false;
471 first_missing_index = 0;
472 glyph_positions.clear();
473 height_adjustment = 0;
474 new_atlas = std::make_shared<GlyphAtlas>(
type);
475 atlas_context->UpdateRectPacker(
nullptr);
476 atlas_context->UpdateGlyphAtlas(new_atlas, {0, 0}, 0);
488 atlas_context->UpdateGlyphAtlas(new_atlas, atlas_size, height_adjustment);
492 FML_DCHECK(new_glyphs.size() == glyph_positions.size());
504 descriptor.
size = atlas_size;
507 std::shared_ptr<Texture> new_texture =
513 new_texture->SetLabel(
"GlyphAtlas");
516 std::shared_ptr<BlitPass> blit_pass = cmd_buffer->CreateBlitPass();
522 TRACE_EVENT0(
"flutter",
"ClearGlyphAtlas");
524 new_texture->GetTextureDescriptor().GetByteSizeOfBaseMipLevel();
534 fml::ScopedCleanupClosure closure([&]() {
540 if (new_atlas->GetTexture() && blit_old_atlas) {
541 blit_pass->AddCopy(new_atlas->GetTexture(), new_texture,
547 new_atlas->SetTexture(std::move(new_texture));
553 for (
size_t i = first_missing_index; i < glyph_positions.size(); i++) {
554 new_atlas->AddTypefaceGlyphPositionAndBounds(
555 new_glyphs[i], glyph_positions[i], glyph_sizes[i]);
563 new_atlas->GetTexture(), new_glyphs,
564 first_missing_index, new_glyphs.size())) {