10 #include "flutter/fml/logging.h"
11 #include "flutter/fml/trace_event.h"
18 #include "third_party/skia/include/core/SkBitmap.h"
19 #include "third_party/skia/include/core/SkCanvas.h"
20 #include "third_party/skia/include/core/SkFont.h"
21 #include "third_party/skia/include/core/SkSurface.h"
31 return std::make_shared<TypographerContextSkia>();
38 std::shared_ptr<GlyphAtlasContext>
40 return std::make_shared<GlyphAtlasContextSkia>();
44 const std::vector<FontGlyphPair>& pairs,
45 const ISize& atlas_size,
46 std::vector<Rect>& glyph_positions,
47 const std::shared_ptr<RectanglePacker>& rect_packer) {
52 glyph_positions.clear();
53 glyph_positions.reserve(pairs.size());
56 for (
auto it = pairs.begin(); it != pairs.end(); ++i, ++it) {
57 const auto& pair = *it;
59 const auto glyph_size =
60 ISize::Ceil(pair.glyph.bounds.size * pair.scaled_font.scale);
62 if (!rect_packer->addRect(glyph_size.width +
kPadding,
66 return pairs.size() - i;
69 location_in_atlas.
y(),
79 const std::shared_ptr<GlyphAtlas>& atlas,
80 const std::vector<FontGlyphPair>& extra_pairs,
81 std::vector<Rect>& glyph_positions,
83 const std::shared_ptr<RectanglePacker>& rect_packer) {
84 TRACE_EVENT0(
"impeller", __FUNCTION__);
85 if (!rect_packer || atlas_size.
IsEmpty()) {
92 FML_DCHECK(glyph_positions.size() == 0);
93 glyph_positions.reserve(extra_pairs.size());
94 for (
size_t i = 0; i < extra_pairs.size(); i++) {
97 const auto glyph_size =
100 if (!rect_packer->addRect(glyph_size.width +
kPadding,
107 location_in_atlas.
y(),
117 const std::vector<FontGlyphPair>& pairs,
118 std::vector<Rect>& glyph_positions,
119 const std::shared_ptr<GlyphAtlasContext>& atlas_context,
121 const ISize& max_texture_size) {
122 static constexpr
auto kMinAtlasSize = 8u;
123 static constexpr
auto kMinAlphaBitmapSize = 1024u;
125 TRACE_EVENT0(
"impeller", __FUNCTION__);
128 ?
ISize(kMinAlphaBitmapSize, kMinAlphaBitmapSize)
129 :
ISize(kMinAtlasSize, kMinAtlasSize);
130 size_t total_pairs = pairs.size() + 1;
132 auto rect_packer = std::shared_ptr<RectanglePacker>(
136 glyph_positions, rect_packer);
137 if (remaining_pairs == 0) {
138 atlas_context->UpdateRectPacker(rect_packer);
140 }
else if (remaining_pairs < std::ceil(total_pairs / 2)) {
144 std::min(current_size.
width, current_size.
height) + 1));
150 }
while (current_size.
width <= max_texture_size.
width &&
158 const Rect& location,
161 const auto position = SkPoint::Make(location.
origin.
x / scaled_font.
scale,
163 SkGlyphID glyph_id = glyph.
index;
167 metrics.point_size, metrics.scaleX, metrics.skewX);
168 sk_font.setEdging(SkFont::Edging::kAntiAlias);
169 sk_font.setHinting(SkFontHinting::kSlight);
170 sk_font.setEmbolden(metrics.embolden);
172 auto glyph_color = has_color ? SK_ColorWHITE : SK_ColorBLACK;
175 glyph_paint.setColor(glyph_color);
176 canvas->resetMatrix();
177 canvas->scale(scaled_font.
scale, scaled_font.
scale);
178 canvas->drawGlyphs(1u,
189 const std::shared_ptr<SkBitmap>& bitmap,
190 const std::vector<FontGlyphPair>& new_pairs) {
191 TRACE_EVENT0(
"impeller", __FUNCTION__);
192 FML_DCHECK(bitmap !=
nullptr);
194 auto surface = SkSurfaces::WrapPixels(bitmap->pixmap());
198 auto canvas = surface->getCanvas();
207 if (!pos.has_value()) {
210 DrawGlyph(canvas, pair.scaled_font, pair.glyph, pos.value(), has_color);
216 const ISize& atlas_size) {
217 TRACE_EVENT0(
"impeller", __FUNCTION__);
218 auto bitmap = std::make_shared<SkBitmap>();
219 SkImageInfo image_info;
223 image_info = SkImageInfo::MakeA8(atlas_size.
width, atlas_size.
height);
227 SkImageInfo::MakeN32Premul(atlas_size.
width, atlas_size.
height);
231 if (!bitmap->tryAllocPixels(image_info)) {
235 auto surface = SkSurfaces::WrapPixels(bitmap->pixmap());
239 auto canvas = surface->getCanvas();
248 const Rect& location) ->
bool {
249 DrawGlyph(canvas, scaled_font, glyph, location, has_color);
257 const std::shared_ptr<Texture>& texture) {
258 TRACE_EVENT0(
"impeller", __FUNCTION__);
260 FML_DCHECK(bitmap !=
nullptr);
261 auto texture_descriptor = texture->GetTextureDescriptor();
263 auto mapping = std::make_shared<fml::NonOwnedMapping>(
264 reinterpret_cast<const uint8_t*
>(bitmap->getAddr(0, 0)),
265 texture_descriptor.GetByteSizeOfBaseMipLevel(),
266 [bitmap](
auto,
auto)
mutable { bitmap.reset(); }
269 return texture->SetContents(mapping);
273 const std::shared_ptr<Allocator>& allocator,
274 std::shared_ptr<SkBitmap> bitmap,
275 const ISize& atlas_size,
277 TRACE_EVENT0(
"impeller", __FUNCTION__);
282 FML_DCHECK(bitmap !=
nullptr);
283 const auto& pixmap = bitmap->pixmap();
287 texture_descriptor.
format = format;
288 texture_descriptor.
size = atlas_size;
290 if (pixmap.rowBytes() * pixmap.height() !=
295 auto texture = allocator->CreateTexture(texture_descriptor);
296 if (!texture || !texture->IsValid()) {
299 texture->SetLabel(
"GlyphAtlas");
301 auto mapping = std::make_shared<fml::NonOwnedMapping>(
302 reinterpret_cast<const uint8_t*
>(bitmap->getAddr(0, 0)),
304 [bitmap](
auto,
auto)
mutable { bitmap.reset(); }
307 if (!texture->SetContents(mapping)) {
316 std::shared_ptr<GlyphAtlasContext> atlas_context,
318 TRACE_EVENT0(
"impeller", __FUNCTION__);
323 std::shared_ptr<GlyphAtlas> last_atlas = atlas_context->GetGlyphAtlas();
325 if (font_glyph_map.empty()) {
333 std::vector<FontGlyphPair> new_glyphs;
334 for (
const auto& font_value : font_glyph_map) {
335 const ScaledFont& scaled_font = font_value.first;
337 last_atlas->GetFontGlyphAtlas(scaled_font.
font, scaled_font.
scale);
338 if (font_glyph_atlas) {
339 for (
const Glyph& glyph : font_value.second) {
341 new_glyphs.emplace_back(scaled_font, glyph);
345 for (
const Glyph& glyph : font_value.second) {
346 new_glyphs.emplace_back(scaled_font, glyph);
350 if (last_atlas->GetType() == type && new_glyphs.size() == 0) {
359 std::vector<Rect> glyph_positions;
360 if (last_atlas->GetType() == type &&
362 atlas_context->GetAtlasSize(),
363 atlas_context->GetRectPacker())) {
371 for (
size_t i = 0, count = glyph_positions.size(); i < count; i++) {
372 last_atlas->AddTypefaceGlyphPosition(new_glyphs[i], glyph_positions[i]);
378 auto bitmap = atlas_context_skia.GetBitmap();
396 std::vector<FontGlyphPair> font_glyph_pairs;
397 font_glyph_pairs.reserve(std::accumulate(
398 font_glyph_map.begin(), font_glyph_map.end(), 0,
399 [](
const int a,
const auto& b) { return a + b.second.size(); }));
400 for (
const auto& font_value : font_glyph_map) {
401 const ScaledFont& scaled_font = font_value.first;
402 for (
const Glyph& glyph : font_value.second) {
403 font_glyph_pairs.push_back({scaled_font, glyph});
406 auto glyph_atlas = std::make_shared<GlyphAtlas>(type);
415 atlas_context->UpdateGlyphAtlas(glyph_atlas, atlas_size);
416 if (atlas_size.IsEmpty()) {
425 if (glyph_positions.size() != font_glyph_pairs.size()) {
434 for (
auto it = font_glyph_pairs.begin(); it != font_glyph_pairs.end();
436 glyph_atlas->AddTypefaceGlyphPosition(*it, glyph_positions[i]);
447 atlas_context_skia.UpdateBitmap(bitmap);
470 glyph_atlas->SetTexture(std::move(texture));