| Flutter Impeller |

Public Member Functions | Static Public Member Functions | List of all members
impeller::TextContents Class Referencefinal

`#include <text_contents.h>`

Inheritance diagram for impeller::TextContents:

## Public Member Functions
| TextContents ()
| ~TextContents ()
void | SetTextFrame (const std::shared_ptr< TextFrame > &frame)
void | SetColor (Color color)
void | SetForceTextColor (bool value)
| Force the text color to apply to the rendered glyphs, even if those glyphs are bitmaps. More...
void | SetTextProperties (Color color, bool stroke, Scalar stroke_width, Cap stroke_cap, Join stroke_join, Scalar stroke_miter)
| Must be set after text frame. More...
Color | GetColor () const
void | SetInheritedOpacity (Scalar opacity) override
| Inherit the provided opacity. More...
void | SetOffset (Vector2 offset)
std::optional< Rect > | GetTextFrameBounds () const
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. More...
void | SetScale (Scalar scale)
bool | Render (const ContentContext &renderer, const Entity &entity, RenderPass &pass) const override
Public Member Functions inherited from impeller::Contents
| Contents ()
virtual | ~Contents ()
void | SetCoverageHint (std::optional< Rect > coverage_hint)
| Hint that specifies the coverage area of this Contents that will actually be used during rendering. This is for optimization purposes only and can not be relied on as a clip. May optionally affect the result of `GetCoverage()`. More...
const std::optional< Rect > & | GetCoverageHint () const
virtual bool | IsOpaque (const Matrix &transform) const
| Whether this Contents only emits opaque source colors from the fragment stage. This value does not account for any entity properties (e.g. the blend mode), clips/visibility culling, or inherited opacity. More...
virtual std::optional< Snapshot > | RenderToSnapshot (const ContentContext &renderer, const Entity &entity, std::optional< Rect > coverage_limit=std::nullopt, const std::optional< SamplerDescriptor > &sampler_descriptor=std::nullopt, bool msaa_enabled=true, int32_t mip_count=1, std::string_view label="Snapshot") const
| Render this contents to a snapshot, respecting the entity's transform, path, clip depth, and blend mode. The result texture size is always the size of `GetCoverage(entity)`. More...
std::optional< Size > | GetColorSourceSize () const
| Return the color source's intrinsic size, if available. More...
void | SetColorSourceSize (Size size)
virtual std::optional< Color > | AsBackgroundColor (const Entity &entity, ISize target_size) const
| Returns a color if this Contents will flood the given `target_size` with a color. This output color is the "Source" color that will be used for the Entity's blend operation. More...
virtual bool | ApplyColorFilter (const ColorFilterProc &color_filter_proc)
| If possible, applies a color filter to this contents inputs on the CPU. More...

## Static Public Member Functions
static void | ComputeVertexData (GlyphAtlasPipeline::VertexShader::PerVertexData *vtx_contents, const std::shared_ptr< TextFrame > &frame, Scalar scale, const Matrix &entity_transform, Vector2 offset, std::optional< GlyphProperties > glyph_properties, const std::shared_ptr< GlyphAtlas > &atlas)
Static Public Member Functions inherited from impeller::Contents
static std::shared_ptr< Contents > | MakeAnonymous (RenderProc render_proc, CoverageProc coverage_proc)

## Additional Inherited Members
Public Types inherited from impeller::Contents
using | ColorFilterProc = std::function< Color(Color)>
using | RenderProc = std::function< bool(const ContentContext &renderer, const Entity &entity, RenderPass &pass)>
using | CoverageProc = std::function< std::optional< Rect >(const Entity &entity)>

## Detailed Description

Definition at line 22 of file text_contents.h.

## Constructor & Destructor Documentation

## ◆ TextContents()

impeller::TextContents::TextContents | ( |  | ) |
| default

## ◆ ~TextContents()

impeller::TextContents::~TextContents | ( |  | ) |
| default

## Member Function Documentation

## ◆ ComputeVertexData()

void impeller::TextContents::ComputeVertexData | ( | GlyphAtlasPipeline::VertexShader::PerVertexData * | vtx_contents,
|  | const std::shared_ptr< TextFrame > & | frame,
|  | Scalar | scale,
|  | const Matrix & | entity_transform,
|  | Vector2 | offset,
|  | std::optional< GlyphProperties > | glyph_properties,
|  | const std::shared_ptr< GlyphAtlas > & | atlas
| ) |  |
| static

Definition at line 96 of file text_contents.cc.

103 {
104 // Common vertex information for all glyphs.
105 // All glyphs are given the same vertex information in the form of a
106 // unit-sized quad. The size of the glyph is specified in per instance data
107 // and the vertex shader uses this to size the glyph correctly. The
108 // interpolated vertex information is also used in the fragment shader to
109 // sample from the glyph atlas.
110
111 constexpr std::array<Point, 4> unit_points = {Point{0, 0}, Point{1, 0},
112 Point{0, 1}, Point{1, 1}};
113
114 ISize atlas_size = atlas->GetTexture()->GetSize();
115 bool is_translation_scale = entity_transform.IsTranslationScaleOnly();
116 Matrix basis_transform = entity_transform.Basis();
117
118 VS::PerVertexData vtx;
119 size_t i = 0u;
120 size_t bounds_offset = 0u;
121 Rational rounded_scale = frame->GetScale();
122 Scalar inverted_rounded_scale = static_cast<Scalar>(rounded_scale.Invert());
123 Matrix unscaled_basis =
124 basis_transform *
125 Matrix::MakeScale({inverted_rounded_scale, inverted_rounded_scale, 1});
126
127 // In typical scales < 48x these values should be -1 or 1. We round to
128 // those to avoid inaccuracies.
129 unscaled_basis.m[0] = AttractToOne(unscaled_basis.m[0]);
130 unscaled_basis.m[5] = AttractToOne(unscaled_basis.m[5]);
131
132 for (const TextRun& run : frame->GetRuns()) {
133 const Font& font = run.GetFont();
134 const Matrix transform = frame->GetOffsetTransform();
135 FontGlyphAtlas* font_atlas = nullptr;
136
137 // Adjust glyph position based on the subpixel rounding
138 // used by the font.
139 Point subpixel_adjustment(0.5, 0.5);
140 switch (font.GetAxisAlignment()) {
141 case AxisAlignment::kNone:
142 break;
143 case AxisAlignment::kX:
144 subpixel_adjustment.x = 0.125;
145 break;
146 case AxisAlignment::kY:
147 subpixel_adjustment.y = 0.125;
148 break;
149 case AxisAlignment::kAll:
150 subpixel_adjustment.x = 0.125;
151 subpixel_adjustment.y = 0.125;
152 break;
153 }
154
155 Point screen_offset = (entity_transform * Point(0, 0));
156 for (const TextRun::GlyphPosition& glyph_position :
157 run.GetGlyphPositions()) {
158 const FrameBounds& frame_bounds = frame->GetFrameBounds(bounds_offset);
159 bounds_offset++;
160 auto atlas_glyph_bounds = frame_bounds.atlas_bounds;
161 auto glyph_bounds = frame_bounds.glyph_bounds;
162
163 // If frame_bounds.is_placeholder is true, this is the first frame
164 // the glyph has been rendered and so its atlas position was not
165 // known when the glyph was recorded. Perform a slow lookup into the
166 // glyph atlas hash table.
167 if (frame_bounds.is_placeholder) {
168 if (!font_atlas) {
169 font_atlas =
170 atlas->GetOrCreateFontGlyphAtlas(ScaledFont{font, rounded_scale});
171 }
172
173 if (!font_atlas) {
174 VALIDATION_LOG << "Could not find font in the atlas.";
175 continue;
176 }
177 SubpixelPosition subpixel = TextFrame::ComputeSubpixelPosition(
178 glyph_position, font.GetAxisAlignment(), transform);
179
180 std::optional<FrameBounds> maybe_atlas_glyph_bounds =
181 font_atlas->FindGlyphBounds(SubpixelGlyph{
182 glyph_position.glyph, //
183 subpixel, //
184 glyph_properties //
185 });
186 if (!maybe_atlas_glyph_bounds.has_value()) {
187 VALIDATION_LOG << "Could not find glyph position in the atlas.";
188 continue;
189 }
190 atlas_glyph_bounds = maybe_atlas_glyph_bounds.value().atlas_bounds;
191 }
192
193 Rect scaled_bounds = glyph_bounds.Scale(inverted_rounded_scale);
194 // For each glyph, we compute two rectangles. One for the vertex
195 // positions and one for the texture coordinates (UVs). The atlas
196 // glyph bounds are used to compute UVs in cases where the
197 // destination and source sizes may differ due to clamping the sizes
198 // of large glyphs.
199 Point uv_origin = atlas_glyph_bounds.GetLeftTop() / atlas_size;
200 Point uv_size = SizeToPoint(atlas_glyph_bounds.GetSize()) / atlas_size;
201
202 Point unrounded_glyph_position =
203 // This is for RTL text.
204 unscaled_basis * glyph_bounds.GetLeftTop() +
205 (basis_transform * glyph_position.position);
206
207 Point screen_glyph_position =
208 (screen_offset + unrounded_glyph_position + subpixel_adjustment)
209 .Floor();
210 for (const Point& point : unit_points) {
211 Point position;
212 if (is_translation_scale) {
213 position = (screen_glyph_position +
214 (unscaled_basis * point * glyph_bounds.GetSize()))
215 .Round();
216 } else {
217 position = entity_transform *
218 (glyph_position.position + scaled_bounds.GetLeftTop() +
219 point * scaled_bounds.GetSize());
220 }
221 vtx.uv = uv_origin + (uv_size * point);
222 vtx.position = position;
223 vtx_contents[i++] = vtx;
224 }
225 }
226 }
227 }
impeller::TextFrame::ComputeSubpixelPosition
static SubpixelPosition ComputeSubpixelPosition(const TextRun::GlyphPosition &glyph_position, AxisAlignment alignment, const Matrix &transform)
Definition: text_frame.cc:94
transform
Matrix transform
Definition: gaussian_blur_filter_contents.cc:214
impeller::Scalar
float Scalar
Definition: scalar.h:18
impeller::Rect
TRect< Scalar > Rect
Definition: rect.h:792
impeller::Point
TPoint< Scalar > Point
Definition: point.h:327
impeller::AxisAlignment::kX
@ kX
impeller::AxisAlignment::kAll
@ kAll
impeller::AxisAlignment::kNone
@ kNone
impeller::AxisAlignment::kY
@ kY
impeller::SizeToPoint
Point SizeToPoint(Size size)
Definition: text_contents.cc:21
impeller::SubpixelPosition
SubpixelPosition
Definition: font_glyph_pair.h:61
impeller::ISize
ISize64 ISize
Definition: size.h:162
vtx
SolidFillVertexShader::PerVertexData vtx
Definition: stroke_path_geometry.cc:323
impeller::Matrix::m
Scalar m[16]
Definition: matrix.h:39
impeller::Matrix::MakeScale
static constexpr Matrix MakeScale(const Vector3 &s)
Definition: matrix.h:104
impeller::TPoint::Round
static constexpr TPoint Round(const TPoint< U > &other)
Definition: point.h:49
impeller::TRect::Scale
constexpr TRect Scale(Type scale) const
Definition: rect.h:206
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:91

References impeller::FrameBounds::atlas_bounds, impeller::Matrix::Basis(), impeller::TextFrame::ComputeSubpixelPosition(), impeller::FontGlyphAtlas::FindGlyphBounds(), impeller::Font::GetAxisAlignment(), impeller::TRect< T >::GetLeftTop(), impeller::TRect< T >::GetSize(), impeller::SubpixelGlyph::glyph, impeller::FrameBounds::glyph_bounds, impeller::Rational::Invert(), impeller::FrameBounds::is_placeholder, impeller::Matrix::IsTranslationScaleOnly(), impeller::kAll, impeller::kNone, impeller::kX, impeller::kY, impeller::Matrix::m, impeller::Matrix::MakeScale(), impeller::TPoint< T >::Round(), impeller::TRect< T >::Scale(), impeller::SizeToPoint(), transform, VALIDATION_LOG, vtx, impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

Referenced by Render(), and impeller::testing::TEST_P().

## ◆ GetColor()

Color impeller::TextContents::GetColor | ( |  | ) | const

Definition at line 40 of file text_contents.cc.

40 {
41 return color_.WithAlpha(color_.alpha * inherited_opacity_);
42 }
impeller::Color::alpha
Scalar alpha
Definition: color.h:143
impeller::Color::WithAlpha
constexpr Color WithAlpha(Scalar new_alpha) const
Definition: color.h:278

References impeller::Color::alpha, and impeller::Color::WithAlpha().

Referenced by Render().

## ◆ GetCoverage()

std::optional< Rect > impeller::TextContents::GetCoverage | ( | const Entity & | entity | ) | const
| override virtual

Get the area of the render pass that will be affected when this contents is rendered.

During rendering, coverage coordinates count pixels from the top left corner of the framebuffer.

Returns
  The coverage rectangle. An `std::nullopt` result means that rendering this contents has no effect on the output color.

Implements impeller::Contents.

Definition at line 56 of file text_contents.cc.

56 {
57 return frame_->GetBounds().TransformBounds(entity.GetTransform());
58 }

References impeller::Entity::GetTransform().

## ◆ GetTextFrameBounds()

std::optional<Rect> impeller::TextContents::GetTextFrameBounds | ( |  | ) | const

## ◆ Render()

bool impeller::TextContents::Render | ( | const ContentContext & | renderer,
|  | const Entity & | entity,
|  | RenderPass & | pass
| ) |  | const
| override virtual

Implements impeller::Contents.

Definition at line 229 of file text_contents.cc.

231 {
232 Color color = GetColor();
233 if (color.IsTransparent()) {
234 return true;
235 }
236
237 GlyphAtlas::Type type = frame_->GetAtlasType();
238 const std::shared_ptr<GlyphAtlas>& atlas =
239 renderer.GetLazyGlyphAtlas()->CreateOrGetGlyphAtlas(
240 *renderer.GetContext(), renderer.GetTransientsBuffer(), type);
241
242 if (!atlas || !atlas->IsValid()) {
243 VALIDATION_LOG << "Cannot render glyphs without prepared atlas.";
244 return false;
245 }
246 if (!frame_->IsFrameComplete()) {
247 VALIDATION_LOG << "Failed to find font glyph bounds.";
248 return false;
249 }
250
251 // Information shared by all glyph draw calls.
252 pass.SetCommandLabel("TextFrame");
253 auto opts = OptionsFromPassAndEntity(pass, entity);
254 opts.primitive_type = PrimitiveType::kTriangle;
255 pass.SetPipeline(renderer.GetGlyphAtlasPipeline(opts));
256
257 // Common vertex uniforms for all glyphs.
258 VS::FrameInfo frame_info;
259 frame_info.mvp =
260 Entity::GetShaderTransform(entity.GetShaderClipDepth(), pass, Matrix());
261 bool is_translation_scale = entity.GetTransform().IsTranslationScaleOnly();
262 Matrix entity_transform = entity.GetTransform();
263
264 VS::BindFrameInfo(pass,
265 renderer.GetTransientsBuffer().EmplaceUniform(frame_info));
266
267 FS::FragInfo frag_info;
268 frag_info.use_text_color = force_text_color_ ? 1.0 : 0.0;
269 frag_info.text_color = ToVector(color.Premultiply());
270 frag_info.is_color_glyph = type == GlyphAtlas::Type::kColorBitmap;
271
272 FS::BindFragInfo(pass,
273 renderer.GetTransientsBuffer().EmplaceUniform(frag_info));
274
275 SamplerDescriptor sampler_desc;
276 if (is_translation_scale) {
277 sampler_desc.min_filter = MinMagFilter::kNearest;
278 sampler_desc.mag_filter = MinMagFilter::kNearest;
279 } else {
280 // Currently, we only propagate the scale of the transform to the atlas
281 // renderer, so if the transform has more than just a translation, we turn
282 // on linear sampling to prevent crunchiness caused by the pixel grid not
283 // being perfectly aligned.
284 // The downside is that this slightly over-blurs rotated/skewed text.
285 sampler_desc.min_filter = MinMagFilter::kLinear;
286 sampler_desc.mag_filter = MinMagFilter::kLinear;
287 }
288
289 // No mipmaps for glyph atlas (glyphs are generated at exact scales).
290 sampler_desc.mip_filter = MipFilter::kBase;
291
292 FS::BindGlyphAtlasSampler(
293 pass, // command
294 atlas->GetTexture(), // texture
295 renderer.GetContext()->GetSamplerLibrary()->GetSampler(
296 sampler_desc) // sampler
297 );
298
299 HostBuffer& host_buffer = renderer.GetTransientsBuffer();
300 size_t glyph_count = 0;
301 for (const auto& run : frame_->GetRuns()) {
302 glyph_count += run.GetGlyphPositions().size();
303 }
304 size_t vertex_count = glyph_count * 4;
305 size_t index_count = glyph_count * 6;
306
307 BufferView buffer_view = host_buffer.Emplace(
308 vertex_count * sizeof(VS::PerVertexData), alignof(VS::PerVertexData),
309 [&](uint8_t* data) {
310 VS::PerVertexData* vtx_contents =
311 reinterpret_cast<VS::PerVertexData*>(data);
312 ComputeVertexData(/*vtx_contents=*/vtx_contents,
313 /*frame=*/frame_,
314 /*scale=*/scale_,
315 /*entity_transform=*/entity_transform,
316 /*offset=*/offset_,
317 /*glyph_properties=*/GetGlyphProperties(),
318 /*atlas=*/atlas);
319 });
320 BufferView index_buffer_view = host_buffer.Emplace(
321 index_count * sizeof(uint16_t), alignof(uint16_t), [&](uint8_t* data) {
322 uint16_t* indices = reinterpret_cast<uint16_t*>(data);
323 size_t j = 0;
324 for (auto i = 0u; i < glyph_count; i++) {
325 size_t base = i * 4;
326 indices[j++] = base + 0;
327 indices[j++] = base + 1;
328 indices[j++] = base + 2;
329 indices[j++] = base + 1;
330 indices[j++] = base + 2;
331 indices[j++] = base + 3;
332 }
333 });
334
335 pass.SetVertexBuffer(std::move(buffer_view));
336 pass.SetIndexBuffer(index_buffer_view, IndexType::k16bit);
337 pass.SetElementCount(index_count);
338
339 return pass.Draw().ok();
340 }
type
GLenum type
Definition: blit_command_gles.cc:151
buffer_view
BufferView buffer_view
Definition: blit_command_gles.cc:152
impeller::Entity::GetShaderTransform
Matrix GetShaderTransform(const RenderPass &pass) const
Get the vertex shader transform used for drawing this Entity.
Definition: entity.cc:48
impeller::GlyphAtlas::Type
Type
Describes how the glyphs are represented in the texture.
Definition: glyph_atlas.h:74
impeller::GlyphAtlas::Type::kColorBitmap
@ kColorBitmap
impeller::TextContents::ComputeVertexData
static void ComputeVertexData(GlyphAtlasPipeline::VertexShader::PerVertexData *vtx_contents, const std::shared_ptr< TextFrame > &frame, Scalar scale, const Matrix &entity_transform, Vector2 offset, std::optional< GlyphProperties > glyph_properties, const std::shared_ptr< GlyphAtlas > &atlas)
Definition: text_contents.cc:96
impeller::TextContents::GetColor
Color GetColor() const
Definition: text_contents.cc:40
impeller::IndexType::k16bit
@ k16bit
impeller::PrimitiveType::kTriangle
@ kTriangle
impeller::MipFilter::kBase
@ kBase
The texture is sampled as if it only had a single mipmap level.
impeller::ToVector
constexpr Vector4 ToVector(Color color)
Definition: shader_types.h:190
impeller::OptionsFromPassAndEntity
ContentContextOptions OptionsFromPassAndEntity(const RenderPass &pass, const Entity &entity)
Definition: contents.cc:34
impeller::MinMagFilter::kLinear
@ kLinear
impeller::MinMagFilter::kNearest
@ kNearest
Select nearest to the sample point. Most widely supported.
data
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:67

References buffer_view, ComputeVertexData(), data, impeller::RenderPass::Draw(), impeller::HostBuffer::Emplace(), impeller::HostBuffer::EmplaceUniform(), GetColor(), impeller::ContentContext::GetContext(), impeller::ContentContext::GetGlyphAtlasPipeline(), impeller::ContentContext::GetLazyGlyphAtlas(), impeller::Entity::GetShaderClipDepth(), impeller::Entity::GetShaderTransform(), impeller::Entity::GetTransform(), impeller::ContentContext::GetTransientsBuffer(), impeller::Matrix::IsTranslationScaleOnly(), impeller::Color::IsTransparent(), impeller::k16bit, impeller::kBase, impeller::GlyphAtlas::kColorBitmap, impeller::kLinear, impeller::kNearest, impeller::kTriangle, impeller::SamplerDescriptor::mag_filter, impeller::SamplerDescriptor::min_filter, impeller::SamplerDescriptor::mip_filter, impeller::OptionsFromPassAndEntity(), impeller::Color::Premultiply(), impeller::RenderPass::SetCommandLabel(), impeller::RenderPass::SetElementCount(), impeller::RenderPass::SetIndexBuffer(), impeller::RenderPass::SetPipeline(), impeller::RenderPass::SetVertexBuffer(), impeller::ToVector(), type, and VALIDATION_LOG.

Referenced by impeller::testing::TEST_P().

## ◆ SetColor()

void impeller::TextContents::SetColor | ( | Color | color | ) |

Definition at line 36 of file text_contents.cc.

36 {
37 color_ = color;
38 }

Referenced by impeller::testing::TEST_P().

## ◆ SetForceTextColor()

void impeller::TextContents::SetForceTextColor | ( | bool | value | ) |

Force the text color to apply to the rendered glyphs, even if those glyphs are bitmaps.

This is used to ensure that mask blurs work correctly on emoji.

Definition at line 52 of file text_contents.cc.

52 {
53 force_text_color_ = value;
54 }
value
int32_t value
Definition: dl_golden_unittests.cc:459

References value.

## ◆ SetInheritedOpacity()

void impeller::TextContents::SetInheritedOpacity | ( | Scalar | opacity | ) |
| override virtual

Inherit the provided opacity.

       Use of this method is invalid if CanAcceptOpacity returns false.

Reimplemented from impeller::Contents.

Definition at line 44 of file text_contents.cc.

44 {
45 inherited_opacity_ = opacity;
46 }

## ◆ SetOffset()

void impeller::TextContents::SetOffset | ( | Vector2 | offset | ) |

Definition at line 48 of file text_contents.cc.

48 {
49 offset_ = offset;
50 }
offset
SeparatedVector2 offset
Definition: stroke_path_geometry.cc:322

References offset.

Referenced by impeller::testing::TEST_P().

## ◆ SetScale()

void impeller::TextContents::SetScale | ( | Scalar | scale | ) |
| inline

Definition at line 59 of file text_contents.h.

59 { scale_ = scale; }
scale
const Scalar scale
Definition: stroke_path_geometry.cc:319

References scale.

Referenced by impeller::testing::TEST_P().

## ◆ SetTextFrame()

void impeller::TextContents::SetTextFrame | ( | const std::shared_ptr< TextFrame > & | frame | ) |

Definition at line 32 of file text_contents.cc.

32 {
33 frame_ = frame;
34 }

Referenced by impeller::testing::TEST_P().

## ◆ SetTextProperties()

void impeller::TextContents::SetTextProperties | ( | Color | color,
|  | bool | stroke,
|  | Scalar | stroke_width,
|  | Cap | stroke_cap,
|  | Join | stroke_join,
|  | Scalar | stroke_miter
| ) |  |

Must be set after text frame.

Definition at line 60 of file text_contents.cc.

65 {
66 if (frame_->HasColor()) {
67 // Alpha is always applied when rendering, remove it here so
68 // we do not double-apply the alpha.
69 properties_.color = color.WithAlpha(1.0);
70 }
71 if (stroke) {
72 properties_.stroke = true;
73 properties_.stroke_width = stroke_width;
74 properties_.stroke_cap = stroke_cap;
75 properties_.stroke_join = stroke_join;
76 properties_.stroke_miter = stroke_miter;
77 }
78 }
stroke_width
const Scalar stroke_width
Definition: stroke_path_geometry.cc:315
impeller::GlyphProperties::color
Color color
Definition: font_glyph_pair.h:18
impeller::GlyphProperties::stroke_cap
Cap stroke_cap
Definition: font_glyph_pair.h:20
impeller::GlyphProperties::stroke_width
Scalar stroke_width
Definition: font_glyph_pair.h:19
impeller::GlyphProperties::stroke_join
Join stroke_join
Definition: font_glyph_pair.h:21
impeller::GlyphProperties::stroke_miter
Scalar stroke_miter
Definition: font_glyph_pair.h:22
impeller::GlyphProperties::stroke
bool stroke
Definition: font_glyph_pair.h:23

References impeller::GlyphProperties::color, impeller::GlyphProperties::stroke, impeller::GlyphProperties::stroke_cap, impeller::GlyphProperties::stroke_join, impeller::GlyphProperties::stroke_miter, stroke_width, impeller::GlyphProperties::stroke_width, and impeller::Color::WithAlpha().

The documentation for this class was generated from the following files:

- impeller/entity/contents/text_contents.h
- impeller/entity/contents/text_contents.cc