10#include "flutter/fml/logging.h"
11#include "flutter/fml/trace_event.h"
33 return std::make_shared<TypographerContextSkia>();
40std::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) {
87 if (!rect_packer || atlas_size.
IsEmpty()) {
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;
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,
169 metrics.point_size, metrics.scaleX, metrics.skewX);
191 const std::shared_ptr<SkBitmap>&
bitmap,
192 const std::vector<FontGlyphPair>& new_pairs) {
200 auto canvas =
surface->getCanvas();
208 auto pos = atlas.FindFontGlyphBounds(pair);
209 if (!
pos.has_value()) {
212 DrawGlyph(canvas, pair.scaled_font, pair.glyph,
pos.value(), has_color);
218 const ISize& atlas_size) {
220 auto bitmap = std::make_shared<SkBitmap>();
223 switch (atlas.GetType()) {
227 static_cast<int32_t
>(atlas_size.
height)});
235 if (!
bitmap->tryAllocPixels(image_info)) {
243 auto canvas =
surface->getCanvas();
250 atlas.IterateGlyphs([canvas, has_color](
const ScaledFont& scaled_font,
252 const Rect& location) ->
bool {
253 DrawGlyph(canvas, scaled_font, glyph, location, has_color);
261 const std::shared_ptr<Texture>&
texture) {
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,
287 const auto& pixmap =
bitmap->pixmap();
292 texture_descriptor.
size = atlas_size;
294 if (pixmap.rowBytes() * pixmap.height() !=
299 auto texture = allocator->CreateTexture(texture_descriptor);
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,
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));
constexpr SkColor SK_ColorBLACK
constexpr SkColor SK_ColorWHITE
@ kSlight
minimal modification to improve constrast
void drawGlyphs(int count, const SkGlyphID glyphs[], const SkPoint positions[], const uint32_t clusters[], int textByteCount, const char utf8text[], SkPoint origin, const SkFont &font, const SkPaint &paint)
void scale(SkScalar sx, SkScalar sy)
void setEdging(Edging edging)
void setHinting(SkFontHinting hintingLevel)
@ kAntiAlias
may have transparent pixels on glyph edges
void setEmbolden(bool embolden)
void setColor(SkColor color)
static uint32_t NextPowerOfTwoSize(uint32_t x)
static TypefaceSkia & Cast(Typeface &base)
To do anything rendering related with Impeller, you need a context.
virtual const std::shared_ptr< const Capabilities > & GetCapabilities() const =0
Get the capabilities of Impeller context. All optionally supported feature of the platform,...
virtual std::shared_ptr< Allocator > GetResourceAllocator() const =0
Returns the allocator used to create textures and buffers on the device.
An object that can look up glyph locations within the GlyphAtlas for a particular typeface.
std::optional< Rect > FindGlyphBounds(const Glyph &glyph) const
Find the location of a glyph in the atlas.
const std::shared_ptr< Typeface > & GetTypeface() const
The typeface whose intrinsic properties this font modifies.
const Metrics & GetMetrics() const
A texture containing the bitmap representation of glyphs in different fonts along with the ability to...
Type
Describes how the glyphs are represented in the texture.
static std::unique_ptr< RectanglePacker > Factory(int width, int height)
Return an empty packer with area specified by width and height.
const sk_sp< SkTypeface > & GetSkiaTypeface() const
std::shared_ptr< GlyphAtlasContext > CreateGlyphAtlasContext() const override
std::shared_ptr< GlyphAtlas > CreateGlyphAtlas(Context &context, GlyphAtlas::Type type, const std::shared_ptr< GlyphAtlasContext > &atlas_context, const FontGlyphMap &font_glyph_map) const override
~TypographerContextSkia() override
static std::shared_ptr< TypographerContext > Make()
virtual bool IsValid() const
uint32_t uint32_t * format
#define FML_DCHECK(condition)
SK_API sk_sp< SkSurface > WrapPixels(const SkImageInfo &imageInfo, void *pixels, size_t rowBytes, const SkSurfaceProps *surfaceProps=nullptr)
std::unordered_map< ScaledFont, std::unordered_set< Glyph > > FontGlyphMap
static std::shared_ptr< Texture > UploadGlyphTextureAtlas(const std::shared_ptr< Allocator > &allocator, std::shared_ptr< SkBitmap > bitmap, const ISize &atlas_size, PixelFormat format)
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
static std::shared_ptr< SkBitmap > CreateAtlasBitmap(const GlyphAtlas &atlas, const ISize &atlas_size)
static void DrawGlyph(SkCanvas *canvas, const ScaledFont &scaled_font, const Glyph &glyph, const Rect &location, bool has_color)
static ISize OptimumAtlasSizeForFontGlyphPairs(const std::vector< FontGlyphPair > &pairs, std::vector< Rect > &glyph_positions, const std::shared_ptr< GlyphAtlasContext > &atlas_context, GlyphAtlas::Type type, const ISize &max_texture_size)
static bool UpdateGlyphTextureAtlas(std::shared_ptr< SkBitmap > bitmap, const std::shared_ptr< Texture > &texture)
static size_t PairsFitInAtlasOfSize(const std::vector< FontGlyphPair > &pairs, const ISize &atlas_size, std::vector< Rect > &glyph_positions, const std::shared_ptr< RectanglePacker > &rect_packer)
static bool UpdateAtlasBitmap(const GlyphAtlas &atlas, const std::shared_ptr< SkBitmap > &bitmap, const std::vector< FontGlyphPair > &new_pairs)
static bool CanAppendToExistingAtlas(const std::shared_ptr< GlyphAtlas > &atlas, const std::vector< FontGlyphPair > &extra_pairs, std::vector< Rect > &glyph_positions, ISize atlas_size, const std::shared_ptr< RectanglePacker > &rect_packer)
static SkImageInfo MakeN32Premul(int width, int height)
static SkImageInfo MakeA8(int width, int height)
static constexpr SkPoint Make(float x, float y)
A font along with a glyph in that font rendered at a particular scale.
const ScaledFont & scaled_font
The glyph index in the typeface.
Rect bounds
Visibility coverage of the glyph in text run space (relative to the baseline, no scaling applied).
A font and a scale. Used as a key that represents a typeface within a glyph atlas.
constexpr Type GetY() const
Returns the Y coordinate of the upper left corner, equivalent to |GetOrigin().y|.
constexpr auto GetTop() const
constexpr TSize< Type > GetSize() const
Returns the size of the rectangle which may be negative in either width or height and may have been c...
constexpr auto GetLeft() const
constexpr Type GetX() const
Returns the X coordinate of the upper left corner, equivalent to |GetOrigin().x|.
static constexpr TRect MakeXYWH(Type x, Type y, Type width, Type height)
constexpr TSize Ceil() const
static constexpr TSize MakeWH(Type width, Type height)
constexpr bool IsEmpty() const
Returns true if either of the width or height are 0, negative, or NaN.
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...
constexpr size_t GetByteSizeOfBaseMipLevel() const
#define TRACE_EVENT0(category_group, name)