10 #include "flutter/fml/logging.h"
11 #include "flutter/fml/trace_event.h"
18 #include "include/core/SkColor.h"
19 #include "include/core/SkSize.h"
20 #include "third_party/skia/include/core/SkBitmap.h"
21 #include "third_party/skia/include/core/SkCanvas.h"
22 #include "third_party/skia/include/core/SkFont.h"
23 #include "third_party/skia/include/core/SkSurface.h"
33 return std::make_shared<TypographerContextSkia>();
40 std::shared_ptr<GlyphAtlasContext>
42 return std::make_shared<GlyphAtlasContextSkia>();
46 const std::vector<FontGlyphPair>& pairs,
47 const ISize& atlas_size,
48 std::vector<Rect>& glyph_positions,
49 const std::shared_ptr<RectanglePacker>& rect_packer) {
54 glyph_positions.clear();
55 glyph_positions.reserve(pairs.size());
58 for (
auto it = pairs.begin(); it != pairs.end(); ++i, ++it) {
59 const auto& pair = *it;
61 const auto glyph_size =
62 ISize::Ceil(pair.glyph.bounds.GetSize() * pair.scaled_font.scale);
64 if (!rect_packer->addRect(glyph_size.width +
kPadding,
68 return pairs.size() - i;
71 location_in_atlas.
y(),
81 const std::shared_ptr<GlyphAtlas>& atlas,
82 const std::vector<FontGlyphPair>& extra_pairs,
83 std::vector<Rect>& glyph_positions,
85 const std::shared_ptr<RectanglePacker>& rect_packer) {
86 TRACE_EVENT0(
"impeller", __FUNCTION__);
87 if (!rect_packer || atlas_size.
IsEmpty()) {
94 FML_DCHECK(glyph_positions.size() == 0);
95 glyph_positions.reserve(extra_pairs.size());
96 for (
size_t i = 0; i < extra_pairs.size(); i++) {
99 const auto glyph_size =
102 if (!rect_packer->addRect(glyph_size.width +
kPadding,
109 location_in_atlas.
y(),
119 const std::vector<FontGlyphPair>& pairs,
120 std::vector<Rect>& glyph_positions,
121 const std::shared_ptr<GlyphAtlasContext>& atlas_context,
123 const ISize& max_texture_size) {
124 static constexpr
auto kMinAtlasSize = 8u;
125 static constexpr
auto kMinAlphaBitmapSize = 1024u;
127 TRACE_EVENT0(
"impeller", __FUNCTION__);
130 ?
ISize(kMinAlphaBitmapSize, kMinAlphaBitmapSize)
131 :
ISize(kMinAtlasSize, kMinAtlasSize);
132 size_t total_pairs = pairs.size() + 1;
134 auto rect_packer = std::shared_ptr<RectanglePacker>(
138 glyph_positions, rect_packer);
139 if (remaining_pairs == 0) {
140 atlas_context->UpdateRectPacker(rect_packer);
142 }
else if (remaining_pairs < std::ceil(total_pairs / 2)) {
146 std::min(current_size.
width, current_size.
height) + 1));
152 }
while (current_size.
width <= max_texture_size.
width &&
160 const Rect& location,
163 const auto position = SkPoint::Make(location.
GetX() / scaled_font.
scale,
165 SkGlyphID glyph_id = glyph.
index;
169 metrics.point_size, metrics.scaleX, metrics.skewX);
170 sk_font.setEdging(SkFont::Edging::kAntiAlias);
171 sk_font.setHinting(SkFontHinting::kSlight);
172 sk_font.setEmbolden(metrics.embolden);
174 auto glyph_color = has_color ? SK_ColorWHITE : SK_ColorBLACK;
177 glyph_paint.setColor(glyph_color);
178 canvas->resetMatrix();
179 canvas->scale(scaled_font.
scale, scaled_font.
scale);
180 canvas->drawGlyphs(1u,
191 const std::shared_ptr<SkBitmap>& bitmap,
192 const std::vector<FontGlyphPair>& new_pairs) {
193 TRACE_EVENT0(
"impeller", __FUNCTION__);
194 FML_DCHECK(bitmap !=
nullptr);
196 auto surface = SkSurfaces::WrapPixels(bitmap->pixmap());
200 auto canvas = surface->getCanvas();
209 if (!pos.has_value()) {
212 DrawGlyph(canvas, pair.scaled_font, pair.glyph, pos.value(), has_color);
218 const ISize& atlas_size) {
219 TRACE_EVENT0(
"impeller", __FUNCTION__);
220 auto bitmap = std::make_shared<SkBitmap>();
221 SkImageInfo image_info;
226 SkImageInfo::MakeA8(SkISize{
static_cast<int32_t
>(atlas_size.
width),
227 static_cast<int32_t
>(atlas_size.
height)});
231 SkImageInfo::MakeN32Premul(atlas_size.
width, atlas_size.
height);
235 if (!bitmap->tryAllocPixels(image_info)) {
239 auto surface = SkSurfaces::WrapPixels(bitmap->pixmap());
243 auto canvas = surface->getCanvas();
252 const Rect& location) ->
bool {
253 DrawGlyph(canvas, scaled_font, glyph, location, has_color);
261 const std::shared_ptr<Texture>& texture) {
262 TRACE_EVENT0(
"impeller", __FUNCTION__);
264 FML_DCHECK(bitmap !=
nullptr);
265 auto texture_descriptor = texture->GetTextureDescriptor();
267 auto mapping = std::make_shared<fml::NonOwnedMapping>(
268 reinterpret_cast<const uint8_t*
>(bitmap->getAddr(0, 0)),
269 texture_descriptor.GetByteSizeOfBaseMipLevel(),
270 [bitmap](
auto,
auto)
mutable { bitmap.reset(); }
273 return texture->SetContents(mapping);
277 const std::shared_ptr<Allocator>& allocator,
278 std::shared_ptr<SkBitmap> bitmap,
279 const ISize& atlas_size,
281 TRACE_EVENT0(
"impeller", __FUNCTION__);
286 FML_DCHECK(bitmap !=
nullptr);
287 const auto& pixmap = bitmap->pixmap();
291 texture_descriptor.
format = format;
292 texture_descriptor.
size = atlas_size;
294 if (pixmap.rowBytes() * pixmap.height() !=
299 auto texture = allocator->CreateTexture(texture_descriptor);
300 if (!texture || !texture->IsValid()) {
303 texture->SetLabel(
"GlyphAtlas");
305 auto mapping = std::make_shared<fml::NonOwnedMapping>(
306 reinterpret_cast<const uint8_t*
>(bitmap->getAddr(0, 0)),
308 [bitmap](
auto,
auto)
mutable { bitmap.reset(); }
311 if (!texture->SetContents(mapping)) {
320 const std::shared_ptr<GlyphAtlasContext>& atlas_context,
322 TRACE_EVENT0(
"impeller", __FUNCTION__);
327 std::shared_ptr<GlyphAtlas> last_atlas = atlas_context->GetGlyphAtlas();
329 if (font_glyph_map.empty()) {
337 std::vector<FontGlyphPair> new_glyphs;
338 for (
const auto& font_value : font_glyph_map) {
339 const ScaledFont& scaled_font = font_value.first;
341 last_atlas->GetFontGlyphAtlas(scaled_font.
font, scaled_font.
scale);
342 if (font_glyph_atlas) {
343 for (
const Glyph& glyph : font_value.second) {
345 new_glyphs.emplace_back(scaled_font, glyph);
349 for (
const Glyph& glyph : font_value.second) {
350 new_glyphs.emplace_back(scaled_font, glyph);
354 if (last_atlas->GetType() == type && new_glyphs.size() == 0) {
363 std::vector<Rect> glyph_positions;
364 if (last_atlas->GetType() == type &&
366 atlas_context->GetAtlasSize(),
367 atlas_context->GetRectPacker())) {
375 for (
size_t i = 0, count = glyph_positions.size(); i < count; i++) {
376 last_atlas->AddTypefaceGlyphPosition(new_glyphs[i], glyph_positions[i]);
382 auto bitmap = atlas_context_skia.GetBitmap();
400 std::vector<FontGlyphPair> font_glyph_pairs;
401 font_glyph_pairs.reserve(std::accumulate(
402 font_glyph_map.begin(), font_glyph_map.end(), 0,
403 [](
const int a,
const auto&
b) { return a + b.second.size(); }));
404 for (
const auto& font_value : font_glyph_map) {
405 const ScaledFont& scaled_font = font_value.first;
406 for (
const Glyph& glyph : font_value.second) {
407 font_glyph_pairs.push_back({scaled_font, glyph});
410 auto glyph_atlas = std::make_shared<GlyphAtlas>(type);
419 atlas_context->UpdateGlyphAtlas(glyph_atlas, atlas_size);
420 if (atlas_size.IsEmpty()) {
429 if (glyph_positions.size() != font_glyph_pairs.size()) {
438 for (
auto it = font_glyph_pairs.begin(); it != font_glyph_pairs.end();
440 glyph_atlas->AddTypefaceGlyphPosition(*it, glyph_positions[i]);
451 atlas_context_skia.UpdateBitmap(bitmap);
474 glyph_atlas->SetTexture(std::move(texture));