-
Notifications
You must be signed in to change notification settings - Fork 6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Loading status checks…
[Impeller] Use scaled font to determine bounds, match Skia position r…
…ounding behavior, add subpixel X/Y/All/None positioning. (#53042) Multiple fixes to text rendering that match skia behavior on almost all bugs I've found, except for the glyphs are still _slightly_ too fine for some CJK text. The fixes are: 1. Compute the gylph size in the typographer context, using text size * scale factor text, instead of computing smaller bounds and scaling it up. This was not accurate and as a result we would positon glyphs incorrect by multiple pixels sometimes, causing uneven rows. 2. Match Skia's rounding behavior. previously we were rounding in multiple places, Skia rounds once. This is important to prevent jumping. 3. Use 4 subpixel X positions for rendering. This is the big one that ensures the visible layout matches exactly. Adds support for Y, both, and none positioning too. I couldn't find any examples of just Y or both. Some fonts may specify that have no subpixel positioning. So we don't bother to compute it for those. Fixes flutter/flutter#138386 / mostly, except slightly not bold enough. Fixes flutter/flutter#147577 / mostly, except slightly not bold enough. Fixes flutter/flutter#140475 Fixes flutter/flutter#141467 Fixes flutter/flutter#135523 Fixes flutter/flutter#127815
1 parent
b175108
commit 9f448d3
Showing
26 changed files
with
512 additions
and
378 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,81 +1,20 @@ | ||
// Copyright 2013 The Flutter Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#include <impeller/transform.glsl> | ||
#include <impeller/types.glsl> | ||
|
||
uniform FrameInfo { | ||
mat4 mvp; | ||
mat4 entity_transform; | ||
vec2 atlas_size; | ||
vec2 offset; | ||
float is_translation_scale; | ||
} | ||
frame_info; | ||
|
||
// XYWH. | ||
in vec4 atlas_glyph_bounds; | ||
// XYWH | ||
in vec4 glyph_bounds; | ||
|
||
in vec2 unit_position; | ||
in vec2 glyph_position; | ||
in vec2 uv; | ||
in vec2 position; | ||
|
||
out vec2 v_uv; | ||
|
||
mat4 basis(mat4 m) { | ||
return mat4(m[0][0], m[0][1], m[0][2], 0.0, // | ||
m[1][0], m[1][1], m[1][2], 0.0, // | ||
m[2][0], m[2][1], m[2][2], 0.0, // | ||
0.0, 0.0, 0.0, 1.0 // | ||
); | ||
} | ||
|
||
vec2 project(mat4 m, vec2 v) { | ||
float w = v.x * m[0][3] + v.y * m[1][3] + m[3][3]; | ||
vec2 result = vec2(v.x * m[0][0] + v.y * m[1][0] + m[3][0], | ||
v.x * m[0][1] + v.y * m[1][1] + m[3][1]); | ||
|
||
// This is Skia's behavior, but it may be reasonable to allow UB for the w=0 | ||
// case. | ||
if (w != 0) { | ||
w = 1 / w; | ||
} | ||
return result * w; | ||
} | ||
|
||
void main() { | ||
vec2 screen_offset = | ||
round(project(frame_info.entity_transform, frame_info.offset)); | ||
|
||
// For each glyph, we compute two rectangles. One for the vertex positions | ||
// and one for the texture coordinates (UVs). | ||
vec2 uv_origin = (atlas_glyph_bounds.xy - vec2(0.5)) / frame_info.atlas_size; | ||
vec2 uv_size = (atlas_glyph_bounds.zw + vec2(1)) / frame_info.atlas_size; | ||
|
||
// Rounding here prevents most jitter between glyphs in the run when | ||
// nearest sampling. | ||
mat4 basis_transform = basis(frame_info.entity_transform); | ||
vec2 screen_glyph_position = | ||
screen_offset + | ||
round(project(basis_transform, (glyph_position + glyph_bounds.xy))); | ||
|
||
vec4 position; | ||
if (frame_info.is_translation_scale == 1.0) { | ||
// Rouding up here prevents the bounds from becoming 1 pixel too small | ||
// when nearest sampling. This path breaks down for projections. | ||
position = vec4( | ||
screen_glyph_position + | ||
ceil(project(basis_transform, unit_position * glyph_bounds.zw)), | ||
0.0, 1.0); | ||
} else { | ||
position = frame_info.entity_transform * | ||
vec4(frame_info.offset + glyph_position + glyph_bounds.xy + | ||
unit_position * glyph_bounds.zw, | ||
0.0, 1.0); | ||
} | ||
|
||
gl_Position = frame_info.mvp * position; | ||
v_uv = uv_origin + unit_position * uv_size; | ||
gl_Position = frame_info.mvp * vec4(position, 0, 1); | ||
v_uv = uv; | ||
} |
Oops, something went wrong.
There is no "s" in this sentence. The sentence should contain "jumps" instead of "jumped"