Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
text_contents.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
7#include <cstring>
8#include <optional>
9#include <utility>
10
19
20namespace impeller {
21
23
25
26void TextContents::SetTextFrame(const std::shared_ptr<TextFrame>& frame) {
27 frame_ = frame;
28}
29
31 color_ = color;
32}
33
35 return color_.WithAlpha(color_.alpha * inherited_opacity_);
36}
37
38bool TextContents::CanInheritOpacity(const Entity& entity) const {
39 return !frame_->MaybeHasOverlapping();
40}
41
43 inherited_opacity_ = opacity;
44}
45
47 offset_ = offset;
48}
49
51 force_text_color_ = value;
52}
53
54std::optional<Rect> TextContents::GetCoverage(const Entity& entity) const {
55 return frame_->GetBounds().TransformBounds(entity.GetTransform());
56}
57
59 const std::shared_ptr<LazyGlyphAtlas>& lazy_glyph_atlas,
60 Scalar scale) {
61 lazy_glyph_atlas->AddTextFrame(*frame_, scale);
62 scale_ = scale;
63}
64
66 const Entity& entity,
67 RenderPass& pass) const {
68 auto color = GetColor();
69 if (color.IsTransparent()) {
70 return true;
71 }
72
73 auto type = frame_->GetAtlasType();
74 const std::shared_ptr<GlyphAtlas>& atlas =
75 renderer.GetLazyGlyphAtlas()->CreateOrGetGlyphAtlas(
76 *renderer.GetContext(), type);
77
78 if (!atlas || !atlas->IsValid()) {
79 VALIDATION_LOG << "Cannot render glyphs without prepared atlas.";
80 return false;
81 }
82
83 // Information shared by all glyph draw calls.
84 pass.SetCommandLabel("TextFrame");
85 auto opts = OptionsFromPassAndEntity(pass, entity);
86 opts.primitive_type = PrimitiveType::kTriangle;
87 pass.SetPipeline(renderer.GetGlyphAtlasPipeline(opts));
88
91
92 // Common vertex uniforms for all glyphs.
93 VS::FrameInfo frame_info;
94 frame_info.mvp =
96 frame_info.atlas_size =
97 Vector2{static_cast<Scalar>(atlas->GetTexture()->GetSize().width),
98 static_cast<Scalar>(atlas->GetTexture()->GetSize().height)};
99 frame_info.offset = offset_;
100 frame_info.is_translation_scale =
102 frame_info.entity_transform = entity.GetTransform();
103
104 VS::BindFrameInfo(pass,
105 renderer.GetTransientsBuffer().EmplaceUniform(frame_info));
106
107 FS::FragInfo frag_info;
108 frag_info.use_text_color = force_text_color_ ? 1.0 : 0.0;
109 frag_info.text_color = ToVector(color.Premultiply());
110 frag_info.is_color_glyph = type == GlyphAtlas::Type::kColorBitmap;
111
112 FS::BindFragInfo(pass,
113 renderer.GetTransientsBuffer().EmplaceUniform(frag_info));
114
115 SamplerDescriptor sampler_desc;
116 if (frame_info.is_translation_scale) {
117 sampler_desc.min_filter = MinMagFilter::kNearest;
118 sampler_desc.mag_filter = MinMagFilter::kNearest;
119 } else {
120 // Currently, we only propagate the scale of the transform to the atlas
121 // renderer, so if the transform has more than just a translation, we turn
122 // on linear sampling to prevent crunchiness caused by the pixel grid not
123 // being perfectly aligned.
124 // The downside is that this slightly over-blurs rotated/skewed text.
125 sampler_desc.min_filter = MinMagFilter::kLinear;
126 sampler_desc.mag_filter = MinMagFilter::kLinear;
127 }
128 sampler_desc.mip_filter = MipFilter::kNearest;
129
130 FS::BindGlyphAtlasSampler(
131 pass, // command
132 atlas->GetTexture(), // texture
133 renderer.GetContext()->GetSamplerLibrary()->GetSampler(
134 sampler_desc) // sampler
135 );
136
137 // Common vertex information for all glyphs.
138 // All glyphs are given the same vertex information in the form of a
139 // unit-sized quad. The size of the glyph is specified in per instance data
140 // and the vertex shader uses this to size the glyph correctly. The
141 // interpolated vertex information is also used in the fragment shader to
142 // sample from the glyph atlas.
143
144 constexpr std::array<Point, 6> unit_points = {Point{0, 0}, Point{1, 0},
145 Point{0, 1}, Point{1, 0},
146 Point{0, 1}, Point{1, 1}};
147
148 auto& host_buffer = renderer.GetTransientsBuffer();
149 size_t vertex_count = 0;
150 for (const auto& run : frame_->GetRuns()) {
151 vertex_count += run.GetGlyphPositions().size();
152 }
153 vertex_count *= 6;
154
155 BufferView buffer_view = host_buffer.Emplace(
156 vertex_count * sizeof(VS::PerVertexData), alignof(VS::PerVertexData),
157 [&](uint8_t* contents) {
158 VS::PerVertexData vtx;
159 VS::PerVertexData* vtx_contents =
160 reinterpret_cast<VS::PerVertexData*>(contents);
161 size_t offset = 0u;
162 for (const TextRun& run : frame_->GetRuns()) {
163 const Font& font = run.GetFont();
165 scale_, font.GetMetrics().point_size);
166 const FontGlyphAtlas* font_atlas =
167 atlas->GetFontGlyphAtlas(font, rounded_scale);
168 if (!font_atlas) {
169 VALIDATION_LOG << "Could not find font in the atlas.";
170 continue;
171 }
172
173 for (const TextRun::GlyphPosition& glyph_position :
174 run.GetGlyphPositions()) {
175 std::optional<Rect> maybe_atlas_glyph_bounds =
176 font_atlas->FindGlyphBounds(glyph_position.glyph);
177 if (!maybe_atlas_glyph_bounds.has_value()) {
178 VALIDATION_LOG << "Could not find glyph position in the atlas.";
179 continue;
180 }
181 const Rect& atlas_glyph_bounds = maybe_atlas_glyph_bounds.value();
182 vtx.atlas_glyph_bounds = Vector4(atlas_glyph_bounds.GetXYWH());
183 vtx.glyph_bounds = Vector4(glyph_position.glyph.bounds.GetXYWH());
184 vtx.glyph_position = glyph_position.position;
185
186 for (const Point& point : unit_points) {
187 vtx.unit_position = point;
188 vtx_contents[offset++] = vtx;
189 }
190 }
191 }
192 });
193
194 pass.SetVertexBuffer({
195 .vertex_buffer = std::move(buffer_view),
196 .index_buffer = {},
197 .vertex_count = vertex_count,
198 .index_type = IndexType::kNone,
199 });
200
201 return pass.Draw().ok();
202}
203
204} // namespace impeller
SkColor4f color
int width() const
Definition SkImage.h:285
int height() const
Definition SkImage.h:291
bool ok() const
Definition status.h:71
Matrix GetShaderTransform(const RenderPass &pass) const
Get the vertex shader transform used for drawing this Entity.
Definition entity.cc:50
const Matrix & GetTransform() const
Get the global transform matrix for this Entity.
Definition entity.cc:46
float GetShaderClipDepth() const
Definition entity.cc:106
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.
Describes a typeface along with any modifications to its intrinsic properties.
Definition font.h:22
Render passes encode render commands directed as one specific render target into an underlying comman...
Definition render_pass.h:33
virtual bool SetVertexBuffer(VertexBuffer buffer)
Specify the vertex and index buffer to use for this command.
virtual void SetPipeline(const std::shared_ptr< Pipeline< PipelineDescriptor > > &pipeline)
The pipeline to use for this command.
virtual fml::Status Draw()
Record the currently pending command.
virtual void SetCommandLabel(std::string_view label)
The debugging label to use for the command.
FragmentShader_ FragmentShader
Definition pipeline.h:106
void PopulateGlyphAtlas(const std::shared_ptr< LazyGlyphAtlas > &lazy_glyph_atlas, Scalar scale) override
Add any text data to the specified lazy atlas. The scale parameter must be used again later when draw...
void SetOffset(Vector2 offset)
bool CanInheritOpacity(const Entity &entity) const override
Whether or not this contents can accept the opacity peephole optimization.
void SetInheritedOpacity(Scalar opacity) override
Inherit the provided opacity.
void SetForceTextColor(bool value)
Force the text color to apply to the rendered glyphs, even if those glyphs are bitmaps.
bool Render(const ContentContext &renderer, const Entity &entity, RenderPass &pass) const override
std::optional< Rect > GetCoverage(const Entity &entity) const override
Get the area of the render pass that will be affected when this contents is rendered.
void SetTextFrame(const std::shared_ptr< TextFrame > &frame)
void SetColor(Color color)
static Scalar RoundScaledFontSize(Scalar scale, Scalar point_size)
Definition text_frame.cc:66
Represents a collection of positioned glyphs from a specific font.
Definition text_run.h:20
double frame
Definition examples.cpp:31
uint8_t value
@ kNone
Does not use the index buffer.
float Scalar
Definition scalar.h:18
@ kNearest
Sample from the nearest mip level.
SolidFillVertexShader VS
constexpr Vector4 ToVector(Color color)
@ kNearest
Select nearest to the sample point. Most widely supported.
ContentContextOptions OptionsFromPassAndEntity(const RenderPass &pass, const Entity &entity)
Definition contents.cc:35
Definition run.py:1
SolidFillVertexShader::PerVertexData vtx
const Scalar scale
Point offset
Scalar alpha
Definition color.h:143
constexpr Color WithAlpha(Scalar new_alpha) const
Definition color.h:270
A 4x4 matrix using column-major storage.
Definition matrix.h:37
constexpr bool IsTranslationScaleOnly() const
Returns true if the matrix has a scale-only basis and is non-projective. Note that an identity matrix...
Definition matrix.h:390
constexpr std::array< T, 4 > GetXYWH() const
Get the x, y coordinates of the origin and the width and height of the rectangle in an array.
Definition rect.h:361
#define VALIDATION_LOG
Definition validation.h:73