--- a/gfx/webrender/examples/basic.rs
+++ b/gfx/webrender/examples/basic.rs
@@ -285,17 +285,16 @@ fn body(api: &RenderApi,
];
builder.push_text(text_bounds,
None,
&glyphs,
font_key,
ColorF::new(1.0, 1.0, 0.0, 1.0),
Au::from_px(32),
- 0.0,
None);
}
if false { // draw box shadow?
let rect = LayoutRect::zero();
let simple_box_bounds = (20, 200).by(50, 50);
let offset = vec2(10.0, 10.0);
let color = ColorF::new(1.0, 1.0, 1.0, 1.0);
--- a/gfx/webrender/src/frame.rs
+++ b/gfx/webrender/src/frame.rs
@@ -578,17 +578,16 @@ impl Frame {
info.image_rendering);
}
SpecificDisplayItem::Text(ref text_info) => {
context.builder.add_text(clip_and_scroll,
item.rect(),
item.local_clip(),
text_info.font_key,
text_info.size,
- text_info.blur_radius,
&text_info.color,
item.glyphs(),
item.display_list().get(item.glyphs()).count(),
text_info.glyph_options);
}
SpecificDisplayItem::Rectangle(ref info) => {
if !self.try_to_add_rectangle_splitting_on_clip(context,
&item.rect(),
@@ -713,16 +712,22 @@ impl Frame {
}
SpecificDisplayItem::PopNestedDisplayList => context.pop_nested_display_list_ids(),
// Do nothing; these are dummy items for the display list parser
SpecificDisplayItem::SetGradientStops => { }
SpecificDisplayItem::PopStackingContext =>
unreachable!("Should have returned in parent method."),
+ SpecificDisplayItem::PushTextShadow(shadow) => {
+ context.builder.push_text_shadow(shadow);
+ }
+ SpecificDisplayItem::PopTextShadow => {
+ context.builder.pop_text_shadow();
+ }
}
None
}
/// Try to optimize the rendering of a solid rectangle that is clipped by a single
/// rounded rectangle, by only masking the parts of the rectangle that intersect
/// the rounded parts of the clip. This is pretty simple now, so has a lot of
/// potential for further optimizations.
--- a/gfx/webrender/src/frame_builder.rs
+++ b/gfx/webrender/src/frame_builder.rs
@@ -1,18 +1,18 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use api::{BorderDetails, BorderDisplayItem, BoxShadowClipMode, ClipAndScrollInfo, ClipId, ColorF};
use api::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DeviceUintRect, DeviceUintSize};
use api::{ExtendMode, FontKey, FontRenderMode, GlyphInstance, GlyphOptions, GradientStop};
use api::{ImageKey, ImageRendering, ItemRange, LayerPoint, LayerRect, LayerSize};
-use api::{LayerToScrollTransform, LayerVector2D, LocalClip, PipelineId, RepeatMode, TileOffset};
-use api::{TransformStyle, WebGLContextId, WorldPixel, YuvColorSpace, YuvData};
+use api::{LayerToScrollTransform, LayerVector2D, LocalClip, PipelineId, RepeatMode, TextShadow};
+use api::{TileOffset, TransformStyle, WebGLContextId, WorldPixel, YuvColorSpace, YuvData};
use app_units::Au;
use frame::FrameId;
use gpu_cache::GpuCache;
use internal_types::HardwareCompositeOp;
use mask_cache::{ClipMode, ClipRegion, ClipSource, MaskCacheInfo};
use plane_split::{BspSplitter, Polygon, Splitter};
use prim_store::{GradientPrimitiveCpu, ImagePrimitiveCpu};
use prim_store::{ImagePrimitiveKind, PrimitiveContainer, PrimitiveIndex};
@@ -111,16 +111,17 @@ pub struct FrameBuilder {
background_color: Option<ColorF>,
prim_store: PrimitiveStore,
cmds: Vec<PrimitiveRunCmd>,
config: FrameBuilderConfig,
stacking_context_store: Vec<StackingContext>,
clip_scroll_group_store: Vec<ClipScrollGroup>,
packed_layers: Vec<PackedLayer>,
+ text_shadows: Vec<TextShadow>,
scrollbar_prims: Vec<ScrollbarPrimitive>,
/// A stack of scroll nodes used during display list processing to properly
/// parent new scroll nodes.
reference_frame_stack: Vec<ClipId>,
/// A stack of stacking contexts used for creating ClipScrollGroups as
@@ -139,32 +140,34 @@ impl FrameBuilder {
config: FrameBuilderConfig) -> FrameBuilder {
match previous {
Some(prev) => {
FrameBuilder {
stacking_context_store: recycle_vec(prev.stacking_context_store),
clip_scroll_group_store: recycle_vec(prev.clip_scroll_group_store),
cmds: recycle_vec(prev.cmds),
packed_layers: recycle_vec(prev.packed_layers),
+ text_shadows: recycle_vec(prev.text_shadows),
scrollbar_prims: recycle_vec(prev.scrollbar_prims),
reference_frame_stack: recycle_vec(prev.reference_frame_stack),
stacking_context_stack: recycle_vec(prev.stacking_context_stack),
prim_store: prev.prim_store.recycle(),
screen_size,
background_color,
config,
has_root_stacking_context: false,
}
}
None => {
FrameBuilder {
stacking_context_store: Vec::new(),
clip_scroll_group_store: Vec::new(),
cmds: Vec::new(),
packed_layers: Vec::new(),
+ text_shadows: Vec::new(),
scrollbar_prims: Vec::new(),
reference_frame_stack: Vec::new(),
stacking_context_stack: Vec::new(),
prim_store: PrimitiveStore::new(),
screen_size,
background_color,
config,
has_root_stacking_context: false,
@@ -282,16 +285,18 @@ impl FrameBuilder {
self.has_root_stacking_context = true;
self.cmds.push(PrimitiveRunCmd::PushStackingContext(stacking_context_index));
self.stacking_context_stack.push(stacking_context_index);
}
pub fn pop_stacking_context(&mut self) {
self.cmds.push(PrimitiveRunCmd::PopStackingContext);
self.stacking_context_stack.pop();
+ assert!(self.text_shadows.is_empty(),
+ "Found unpopped text shadows when popping stacking context!");
}
pub fn push_reference_frame(&mut self,
parent_id: Option<ClipId>,
pipeline_id: PipelineId,
rect: &LayerRect,
transform: &LayerToScrollTransform,
clip_scroll_tree: &mut ClipScrollTree)
@@ -387,16 +392,24 @@ impl FrameBuilder {
clip_scroll_tree.add_node(node, new_node_id);
}
pub fn pop_reference_frame(&mut self) {
self.reference_frame_stack.pop();
}
+ pub fn push_text_shadow(&mut self, shadow: TextShadow) {
+ self.text_shadows.push(shadow);
+ }
+
+ pub fn pop_text_shadow(&mut self) {
+ self.text_shadows.pop().expect("Too many PopTextShadows?");
+ }
+
pub fn add_solid_rectangle(&mut self,
clip_and_scroll: ClipAndScrollInfo,
rect: &LayerRect,
local_clip: &LocalClip,
color: &ColorF,
flags: PrimitiveFlags) {
if color.a == 0.0 {
return;
@@ -727,29 +740,30 @@ impl FrameBuilder {
}
pub fn add_text(&mut self,
clip_and_scroll: ClipAndScrollInfo,
rect: LayerRect,
local_clip: &LocalClip,
font_key: FontKey,
size: Au,
- blur_radius: f32,
color: &ColorF,
glyph_range: ItemRange<GlyphInstance>,
glyph_count: usize,
glyph_options: Option<GlyphOptions>) {
if color.a == 0.0 {
return
}
if size.0 <= 0 {
return
}
+ let mut blur_radius = 0.0; // TODO: remove this in favour of PushTextShadow handling
+
// Expand the rectangle of the text run by the blur radius.
let rect = rect.inflate(blur_radius, blur_radius);
// TODO(gw): Use a proper algorithm to select
// whether this item should be rendered with
// subpixel AA!
let mut render_mode = self.config.default_font_render_mode;
--- a/gfx/webrender_api/src/display_item.rs
+++ b/gfx/webrender_api/src/display_item.rs
@@ -60,16 +60,18 @@ pub enum SpecificDisplayItem {
Gradient(GradientDisplayItem),
RadialGradient(RadialGradientDisplayItem),
Iframe(IframeDisplayItem),
PushStackingContext(PushStackingContextDisplayItem),
PopStackingContext,
SetGradientStops,
PushNestedDisplayList,
PopNestedDisplayList,
+ PushTextShadow(TextShadow),
+ PopTextShadow,
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct ClipDisplayItem {
pub id: ClipId,
pub parent_id: ClipId,
pub image_mask: Option<ImageMask>,
}
@@ -79,17 +81,16 @@ pub struct RectangleDisplayItem {
pub color: ColorF,
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
pub struct TextDisplayItem {
pub font_key: FontKey,
pub size: Au,
pub color: ColorF,
- pub blur_radius: f32,
pub glyph_options: Option<GlyphOptions>,
} // IMPLICIT: glyphs: Vec<GlyphInstance>
#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, PartialEq, PartialOrd, Ord, Serialize)]
pub struct GlyphOptions {
// These are currently only used on windows for dwrite fonts.
pub use_embedded_bitmap: bool,
pub force_gdi_rendering: bool,
@@ -219,16 +220,23 @@ pub struct BoxShadowDisplayItem {
pub offset: LayoutVector2D,
pub color: ColorF,
pub blur_radius: f32,
pub spread_radius: f32,
pub border_radius: f32,
pub clip_mode: BoxShadowClipMode,
}
+#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
+pub struct TextShadow {
+ pub offset: LayoutVector2D,
+ pub color: ColorF,
+ pub blur_radius: f32,
+}
+
#[repr(u32)]
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Ord, PartialOrd)]
pub enum ExtendMode {
Clamp,
Repeat,
}
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
--- a/gfx/webrender_api/src/display_list.rs
+++ b/gfx/webrender_api/src/display_list.rs
@@ -9,17 +9,17 @@ use serde::ser::{SerializeSeq, Serialize
use time::precise_time_ns;
use {BorderDetails, BorderDisplayItem, BorderWidths, BoxShadowClipMode, BoxShadowDisplayItem};
use {ClipAndScrollInfo, ClipDisplayItem, ClipId, ColorF, ComplexClipRegion, DisplayItem};
use {ExtendMode, FilterOp, FontKey, GlyphInstance, GlyphOptions, Gradient, GradientDisplayItem};
use {GradientStop, IframeDisplayItem, ImageDisplayItem, ImageKey, ImageMask, ImageRendering};
use {LayoutPoint, LayoutRect, LayoutSize, LayoutTransform, LayoutVector2D, LocalClip};
use {MixBlendMode, PipelineId, PropertyBinding, PushStackingContextDisplayItem, RadialGradient};
use {RadialGradientDisplayItem, RectangleDisplayItem, ScrollPolicy, SpecificDisplayItem};
-use {StackingContext, TextDisplayItem, TransformStyle, WebGLContextId, WebGLDisplayItem};
+use {StackingContext, TextDisplayItem, TextShadow, TransformStyle, WebGLContextId, WebGLDisplayItem};
use {YuvColorSpace, YuvData, YuvImageDisplayItem};
use std::marker::PhantomData;
#[repr(C)]
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct ItemRange<T> {
start: usize,
length: usize,
@@ -538,30 +538,28 @@ impl DisplayListBuilder {
pub fn push_text(&mut self,
rect: LayoutRect,
local_clip: Option<LocalClip>,
glyphs: &[GlyphInstance],
font_key: FontKey,
color: ColorF,
size: Au,
- blur_radius: f32,
glyph_options: Option<GlyphOptions>) {
// Sanity check - anything with glyphs bigger than this
// is probably going to consume too much memory to render
// efficiently anyway. This is specifically to work around
// the font_advance.html reftest, which creates a very large
// font as a crash test - the rendering is also ignored
// by the azure renderer.
if size < Au::from_px(4096) {
let item = SpecificDisplayItem::Text(TextDisplayItem {
color,
font_key,
size,
- blur_radius,
glyph_options,
});
self.push_item(item, rect, local_clip);
self.push_iter(glyphs);
}
}
@@ -909,16 +907,24 @@ impl DisplayListBuilder {
// will replace references to the root scroll frame id with the current scroll frame
// id.
pub fn push_nested_display_list(&mut self, built_display_list: &BuiltDisplayList) {
self.push_new_empty_item(SpecificDisplayItem::PushNestedDisplayList);
self.data.extend_from_slice(&built_display_list.data);
self.push_new_empty_item(SpecificDisplayItem::PopNestedDisplayList);
}
+ pub fn push_text_shadow(&mut self, shadow: TextShadow) {
+ self.push_new_empty_item(SpecificDisplayItem::PushTextShadow(shadow));
+ }
+
+ pub fn pop_text_shadow(&mut self) {
+ self.push_new_empty_item(SpecificDisplayItem::PopTextShadow);
+ }
+
pub fn finalize(self) -> (PipelineId, LayoutSize, BuiltDisplayList) {
let end_time = precise_time_ns();
(self.pipeline_id,
self.content_size,
BuiltDisplayList {
descriptor: BuiltDisplayListDescriptor {
builder_start_time: self.builder_start_time,
--- a/gfx/webrender_bindings/webrender_ffi_generated.h
+++ b/gfx/webrender_bindings/webrender_ffi_generated.h
@@ -455,16 +455,28 @@ struct WrGlyphInstance {
WrPoint point;
bool operator==(const WrGlyphInstance& aOther) const {
return index == aOther.index &&
point == aOther.point;
}
};
+struct WrTextShadow {
+ WrPoint offset;
+ WrColor color;
+ float blur_radius;
+
+ bool operator==(const WrTextShadow& aOther) const {
+ return offset == aOther.offset &&
+ color == aOther.color &&
+ blur_radius == aOther.blur_radius;
+ }
+};
+
struct MutByteSlice {
uint8_t *buffer;
size_t len;
bool operator==(const MutByteSlice& aOther) const {
return buffer == aOther.buffer &&
len == aOther.len;
}
@@ -668,16 +680,20 @@ WR_INLINE
void wr_dp_pop_scroll_layer(WrState *aState)
WR_FUNC;
WR_INLINE
void wr_dp_pop_stacking_context(WrState *aState)
WR_FUNC;
WR_INLINE
+void wr_dp_pop_text_shadow(WrState *aState)
+WR_FUNC;
+
+WR_INLINE
void wr_dp_push_border(WrState *aState,
WrRect aRect,
WrRect aClip,
WrBorderWidths aWidths,
WrBorderSide aTop,
WrBorderSide aRight,
WrBorderSide aBottom,
WrBorderSide aLeft,
@@ -830,16 +846,21 @@ void wr_dp_push_text(WrState *aState,
WrColor aColor,
WrFontKey aFontKey,
const WrGlyphInstance *aGlyphs,
uint32_t aGlyphCount,
float aGlyphSize)
WR_FUNC;
WR_INLINE
+void wr_dp_push_text_shadow(WrState *aState,
+ WrTextShadow aShadow)
+WR_FUNC;
+
+WR_INLINE
void wr_dp_push_yuv_NV12_image(WrState *aState,
WrRect aBounds,
WrRect aClip,
WrImageKey aImageKey0,
WrImageKey aImageKey1,
WrYuvColorSpace aColorSpace,
WrImageRendering aImageRendering)
WR_FUNC;