Skip to content

Commit 1a21291

Browse files
author
bors-servo
authored
Auto merge of #1816 - lsalzman:font-instance-options, r=glennw
add more per-platform font options to FontInstancePlatformOptions This fleshes out FontInstancePlatformOptions in the ways previously discussed with Glenn: Mainly that now FontInstancePlatformOptions actually has varying sets of options per-platform. Revised FontInstanceOptions to rather implement Default trait instead of using Option all over the place to make Gecko integration simpler and saner. Especially notable is that I heavily revised the set of FreeType options to be sufficient for Gecko to pass in all of its Fontconfig options. As part of this, there was a lot of reworking of how bitmap fonts are managed with FreeType, and to allow them to be scaled in the shader from fixed-size strikes. To support bitmap fonts, I also needed to migrate us from using BlendMode::Alpha to using BlendMode::PremultipliedAlpha to avoid decode hell in FreeType (this also better agreeing with our image handling too). This required some heavy revision of the FreeType backend, and I optimized some decoding there while I was at it. I cleaned up the FontInstance mechanics so that they are only really normalized once they are ready for lookup into the cache. This prevents us having to litter code everywhere to zero out the color, the subpixel direction, etc. This also slims down TextRunPrimitiveCpu by letting us remove some options that were only there because they were getting overwritten in FontInstance. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/webrender/1816) <!-- Reviewable:end -->
2 parents c0948fa + e11297a commit 1a21291

19 files changed

+596
-289
lines changed

Cargo.lock

+4-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

webrender/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "webrender"
3-
version = "0.52.0"
3+
version = "0.52.1"
44
authors = ["Glenn Watson <[email protected]>"]
55
license = "MPL-2.0"
66
repository = "https://github.com/servo/webrender"

webrender/res/cs_text_run.glsl

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ void main(void) {
3838
// Glyphs size is already in device-pixels.
3939
// The render task origin is in device-pixels. Offset that by
4040
// the glyph offset, relative to its primitive bounding rect.
41-
vec2 size = res.uv_rect.zw - res.uv_rect.xy;
41+
vec2 size = (res.uv_rect.zw - res.uv_rect.xy) * res.scale;
4242
vec2 local_pos = glyph.offset + vec2(res.offset.x, -res.offset.y) / uDevicePixelRatio;
4343
vec2 origin = prim.task.render_target_origin +
4444
uDevicePixelRatio * (local_pos + shadow.offset - shadow_geom.local_rect.p0);

webrender/res/prim_shared.glsl

+2-1
Original file line numberDiff line numberDiff line change
@@ -627,11 +627,12 @@ struct GlyphResource {
627627
vec4 uv_rect;
628628
float layer;
629629
vec2 offset;
630+
float scale;
630631
};
631632

632633
GlyphResource fetch_glyph_resource(int address) {
633634
vec4 data[2] = fetch_from_resource_cache_2(address);
634-
return GlyphResource(data[0], data[1].x, data[1].yz);
635+
return GlyphResource(data[0], data[1].x, data[1].yz, data[1].w);
635636
}
636637

637638
struct ImageResource {

webrender/res/ps_text_run.glsl

+6-5
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ void main(void) {
3030
vec2(res.offset.x, -res.offset.y) / uDevicePixelRatio;
3131

3232
RectWithSize local_rect = RectWithSize(local_pos,
33-
(res.uv_rect.zw - res.uv_rect.xy) / uDevicePixelRatio);
33+
(res.uv_rect.zw - res.uv_rect.xy) * res.scale / uDevicePixelRatio);
3434

3535
#ifdef WR_FEATURE_TRANSFORM
3636
TransformVertexInfo vi = write_transform_vertex(local_rect,
@@ -57,7 +57,7 @@ void main(void) {
5757
vec2 st0 = res.uv_rect.xy / texture_size;
5858
vec2 st1 = res.uv_rect.zw / texture_size;
5959

60-
vColor = text.color;
60+
vColor = vec4(text.color.rgb * text.color.a, text.color.a);
6161
vUv = vec3(mix(st0, st1, f), res.layer);
6262
vUvBorder = (res.uv_rect + vec4(0.5, 0.5, -0.5, -0.5)) / texture_size.xyxy;
6363
}
@@ -71,13 +71,14 @@ void main(void) {
7171
oFragColor = texture(sColor0, tc);
7272
#else
7373
vec4 color = texture(sColor0, tc) * vColor;
74+
float alpha = 1.0;
7475
#ifdef WR_FEATURE_TRANSFORM
7576
float a = 0.0;
7677
init_transform_fs(vLocalPos, a);
77-
color.a *= a;
78+
alpha *= a;
7879
#endif
79-
color.a = min(color.a, do_clip());
80-
oFragColor = color;
80+
alpha = min(alpha, do_clip());
81+
oFragColor = color * alpha;
8182
#endif
8283
}
8384
#endif

webrender/src/frame_builder.rs

+10-35
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use api::{GlyphInstance, GlyphOptions, GradientStop, HitTestFlags, HitTestItem,
1010
use api::{ImageKey, ImageRendering, ItemRange, ItemTag, LayerPoint, LayerPrimitiveInfo, LayerRect};
1111
use api::{LayerSize, LayerToScrollTransform, LayerVector2D, LayoutVector2D, LineOrientation};
1212
use api::{LineStyle, LocalClip, POINT_RELATIVE_TO_PIPELINE_VIEWPORT, PipelineId, RepeatMode};
13-
use api::{ScrollSensitivity, SubpixelDirection, Shadow, TileOffset, TransformStyle};
13+
use api::{ScrollSensitivity, Shadow, TileOffset, TransformStyle};
1414
use api::{WorldPixel, WorldPoint, YuvColorSpace, YuvData, device_length};
1515
use app_units::Au;
1616
use border::ImageBorderSegment;
@@ -1132,19 +1132,18 @@ impl FrameBuilder {
11321132
// TODO(gw): Use a proper algorithm to select
11331133
// whether this item should be rendered with
11341134
// subpixel AA!
1135-
let mut default_render_mode = self.config
1135+
let mut render_mode = self.config
11361136
.default_font_render_mode
11371137
.limit_by(font.render_mode);
11381138
if let Some(options) = glyph_options {
1139-
default_render_mode = default_render_mode.limit_by(options.render_mode);
1139+
render_mode = render_mode.limit_by(options.render_mode);
11401140
}
11411141

11421142
// There are some conditions under which we can't use
11431143
// subpixel text rendering, even if enabled.
1144-
let mut normal_render_mode = default_render_mode;
1145-
if normal_render_mode == FontRenderMode::Subpixel {
1144+
if render_mode == FontRenderMode::Subpixel {
11461145
if color.a != 1.0 {
1147-
normal_render_mode = FontRenderMode::Alpha;
1146+
render_mode = FontRenderMode::Alpha;
11481147
}
11491148

11501149
// text on a stacking context that has filters
@@ -1155,36 +1154,17 @@ impl FrameBuilder {
11551154
if let Some(sc_index) = self.stacking_context_stack.last() {
11561155
let stacking_context = &self.stacking_context_store[sc_index.0];
11571156
if stacking_context.composite_ops.count() > 0 {
1158-
normal_render_mode = FontRenderMode::Alpha;
1157+
render_mode = FontRenderMode::Alpha;
11591158
}
11601159
}
11611160
}
11621161

1163-
let color = match font.render_mode {
1164-
FontRenderMode::Bitmap => ColorF::new(1.0, 1.0, 1.0, 1.0),
1165-
FontRenderMode::Subpixel |
1166-
FontRenderMode::Alpha |
1167-
FontRenderMode::Mono => *color,
1168-
};
1169-
1170-
// Shadows never use subpixel AA, but need to respect the alpha/mono flag
1171-
// for reftests.
1172-
let (shadow_render_mode, subpx_dir) = match default_render_mode {
1173-
FontRenderMode::Subpixel | FontRenderMode::Alpha => {
1174-
// TODO(gw): Expose subpixel direction in API once WR supports
1175-
// vertical text runs.
1176-
(FontRenderMode::Alpha, font.subpx_dir)
1177-
}
1178-
FontRenderMode::Mono => (FontRenderMode::Mono, SubpixelDirection::None),
1179-
FontRenderMode::Bitmap => (FontRenderMode::Bitmap, font.subpx_dir),
1180-
};
1181-
11821162
let prim_font = FontInstance::new(
11831163
font.font_key,
11841164
font.size,
1185-
color,
1186-
normal_render_mode,
1187-
subpx_dir,
1165+
*color,
1166+
render_mode,
1167+
font.subpx_dir,
11881168
font.platform_options,
11891169
font.variations.clone(),
11901170
font.synthetic_italics,
@@ -1195,9 +1175,7 @@ impl FrameBuilder {
11951175
glyph_count,
11961176
glyph_gpu_blocks: Vec::new(),
11971177
glyph_keys: Vec::new(),
1198-
shadow_render_mode,
11991178
offset: run_offset,
1200-
color: color,
12011179
};
12021180

12031181
// Text shadows that have a blur radius of 0 need to be rendered as normal
@@ -1215,16 +1193,13 @@ impl FrameBuilder {
12151193
let shadow = picture_prim.as_shadow();
12161194
if shadow.blur_radius == 0.0 {
12171195
let mut text_prim = prim.clone();
1218-
if font.render_mode != FontRenderMode::Bitmap {
1219-
text_prim.font.color = shadow.color.into();
1220-
}
1196+
text_prim.font.color = shadow.color.into();
12211197
// If we have translucent text, we need to ensure it won't go
12221198
// through the subpixel blend mode, which doesn't work with
12231199
// traditional alpha blending.
12241200
if shadow.color.a != 1.0 {
12251201
text_prim.font.render_mode = text_prim.font.render_mode.limit_by(FontRenderMode::Alpha);
12261202
}
1227-
text_prim.color = shadow.color;
12281203
text_prim.offset += shadow.offset;
12291204
fast_shadow_prims.push(text_prim);
12301205
}

webrender/src/glyph_cache.rs

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ pub struct CachedGlyphInfo {
1313
pub glyph_bytes: Arc<Vec<u8>>,
1414
pub size: DeviceUintSize,
1515
pub offset: DevicePoint,
16+
pub scale: f32,
1617
}
1718

1819
pub type GlyphKeyCache = ResourceClassCache<GlyphKey, Option<CachedGlyphInfo>>;

webrender/src/glyph_rasterizer.rs

+31-7
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
44

55
#[cfg(test)]
6-
use api::{ColorF, FontRenderMode, IdNamespace, LayoutPoint, SubpixelDirection};
6+
use api::{ColorF, IdNamespace, LayoutPoint};
77
use api::{DevicePoint, DeviceUintSize, FontInstance};
8-
use api::{FontKey, FontTemplate};
9-
use api::{GlyphDimensions, GlyphKey};
8+
use api::{FontKey, FontTemplate, FontRenderMode, ColorU};
9+
use api::{GlyphDimensions, GlyphKey, SubpixelDirection};
1010
use api::{ImageData, ImageDescriptor, ImageFormat};
1111
#[cfg(test)]
1212
use app_units::Au;
@@ -144,6 +144,29 @@ impl GlyphRasterizer {
144144
self.fonts_to_remove.push(font_key);
145145
}
146146

147+
pub fn prepare_font(&self, font: &mut FontInstance) {
148+
// In alpha/mono mode, the color of the font is irrelevant.
149+
// Forcing it to black in those cases saves rasterizing glyphs
150+
// of different colors when not needed.
151+
match font.render_mode {
152+
FontRenderMode::Mono | FontRenderMode::Bitmap => {
153+
font.color = ColorU::new(255, 255, 255, 255);
154+
// Subpixel positioning is disabled in mono and bitmap modes.
155+
font.subpx_dir = SubpixelDirection::None;
156+
}
157+
FontRenderMode::Alpha => {
158+
font.color = ColorU::new(255, 255, 255, 255);
159+
}
160+
FontRenderMode::Subpixel => {
161+
// In subpixel mode, we only actually need the color if preblending
162+
// is used in the font backend.
163+
if !FontContext::has_gamma_correct_subpixel_aa() {
164+
font.color = ColorU::new(255, 255, 255, 255);
165+
}
166+
}
167+
}
168+
}
169+
147170
pub fn request_glyphs(
148171
&mut self,
149172
glyph_cache: &mut GlyphCache,
@@ -183,7 +206,7 @@ impl GlyphRasterizer {
183206
},
184207
TextureFilter::Linear,
185208
ImageData::Raw(glyph_info.glyph_bytes.clone()),
186-
[glyph_info.offset.x, glyph_info.offset.y],
209+
[glyph_info.offset.x, glyph_info.offset.y, glyph_info.scale],
187210
None,
188211
gpu_cache,
189212
);
@@ -246,10 +269,10 @@ impl GlyphRasterizer {
246269
.get_glyph_dimensions(font, glyph_key)
247270
}
248271

249-
pub fn is_bitmap_font(&self, font_key: FontKey) -> bool {
272+
pub fn is_bitmap_font(&self, font: &FontInstance) -> bool {
250273
self.font_contexts
251274
.lock_shared_context()
252-
.is_bitmap_font(font_key)
275+
.is_bitmap_font(font)
253276
}
254277

255278
pub fn get_glyph_index(&mut self, font_key: FontKey, ch: char) -> Option<u32> {
@@ -312,7 +335,7 @@ impl GlyphRasterizer {
312335
},
313336
TextureFilter::Linear,
314337
ImageData::Raw(glyph_bytes.clone()),
315-
[glyph.left, glyph.top],
338+
[glyph.left, glyph.top, glyph.scale],
316339
None,
317340
gpu_cache,
318341
);
@@ -321,6 +344,7 @@ impl GlyphRasterizer {
321344
glyph_bytes,
322345
size: DeviceUintSize::new(glyph.width, glyph.height),
323346
offset: DevicePoint::new(glyph.left, glyph.top),
347+
scale: glyph.scale,
324348
})
325349
} else {
326350
None

webrender/src/platform/macos/font.rs

+10-5
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ pub struct RasterizedGlyph {
4242
pub left: f32,
4343
pub width: u32,
4444
pub height: u32,
45+
pub scale: f32,
4546
pub bytes: Vec<u8>,
4647
}
4748

@@ -52,6 +53,7 @@ impl RasterizedGlyph {
5253
left: 0.0,
5354
width: 0,
5455
height: 0,
56+
scale: 1.0,
5557
bytes: vec![],
5658
}
5759
}
@@ -422,18 +424,20 @@ impl FontContext {
422424
}
423425
}
424426

425-
pub fn is_bitmap_font(&mut self, font_key: FontKey) -> bool {
426-
match self.get_ct_font(font_key, Au(16 * 60), &[]) {
427+
pub fn is_bitmap_font(&mut self, font: &FontInstance) -> bool {
428+
match self.get_ct_font(font.font_key, font.size, &font.variations) {
427429
Some(ref ct_font) => {
428430
let traits = ct_font.symbolic_traits();
429431
(traits & kCTFontColorGlyphsTrait) != 0
430432
}
431-
None => {
432-
false
433-
}
433+
None => false,
434434
}
435435
}
436436

437+
pub fn has_gamma_correct_subpixel_aa() -> bool {
438+
true
439+
}
440+
437441
pub fn rasterize_glyph(
438442
&mut self,
439443
font: &FontInstance,
@@ -585,6 +589,7 @@ impl FontContext {
585589
top: metrics.rasterized_ascent as f32,
586590
width: metrics.rasterized_width,
587591
height: metrics.rasterized_height,
592+
scale: 1.0,
588593
bytes: rasterized_pixels,
589594
})
590595
}

0 commit comments

Comments
 (0)