зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1575258 - Make text rasterize, render and snap glyphs consistently. r=lsalzman
The glyph pixel space in which we rasterized glyphs differed from how we rendered the rasterized glyphs in the shader. They need to be in agreement because the glyph subpixel offset selected during rasterization depends on it. This patch should make the paths consistent with each other. Additionally, during animations, we now snap the reference frame relative offset ignoring the impact of any animated transforms. This helps with minimizing glyph wiggling during the transition. Differential Revision: https://phabricator.services.mozilla.com/D51305 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
a5506dd31a
Коммит
7243a387ca
|
@ -75,66 +75,40 @@ TextRun fetch_text_run(int address) {
|
|||
|
||||
VertexInfo write_text_vertex(RectWithSize local_clip_rect,
|
||||
float z,
|
||||
int raster_space,
|
||||
#ifdef WR_FEATURE_GLYPH_TRANSFORM
|
||||
mat2 glyph_transform,
|
||||
#else
|
||||
float glyph_scale,
|
||||
#endif
|
||||
Transform transform,
|
||||
PictureTask task,
|
||||
vec2 text_offset,
|
||||
vec2 glyph_offset,
|
||||
RectWithSize glyph_rect,
|
||||
vec2 snap_bias) {
|
||||
// The offset to snap the glyph rect to a device pixel
|
||||
vec2 snap_offset = vec2(0.0);
|
||||
// Transform from glyph space to local space
|
||||
mat2 glyph_transform_inv = mat2(1.0);
|
||||
|
||||
// Glyph space refers to the pixel space used by glyph rasterization during frame
|
||||
// building. If a non-identity transform was used, WR_FEATURE_GLYPH_TRANSFORM will
|
||||
// be set. Otherwise, regardless of whether the raster space is LOCAL or SCREEN,
|
||||
// we ignored the transform during glyph rasterization, and need to snap just using
|
||||
// the device pixel scale and the raster scale.
|
||||
#ifdef WR_FEATURE_GLYPH_TRANSFORM
|
||||
bool remove_subpx_offset = true;
|
||||
#else
|
||||
bool remove_subpx_offset = transform.is_axis_aligned;
|
||||
#endif
|
||||
// Compute the snapping offset only if the scroll node transform is axis-aligned.
|
||||
if (remove_subpx_offset) {
|
||||
// Be careful to only snap with the transform when in screen raster space.
|
||||
switch (raster_space) {
|
||||
case RASTER_SCREEN: {
|
||||
// Transform from local space to glyph space.
|
||||
float device_scale = task.device_pixel_scale / transform.m[3].w;
|
||||
mat2 glyph_transform = mat2(transform.m) * device_scale;
|
||||
// Transform from glyph space back to local space.
|
||||
mat2 glyph_transform_inv = inverse(glyph_transform);
|
||||
|
||||
// Ensure the transformed text offset does not contain a subpixel translation
|
||||
// such that glyph snapping is stable for equivalent glyph subpixel positions.
|
||||
vec2 device_text_pos = glyph_transform * text_offset + transform.m[3].xy * device_scale;
|
||||
snap_offset = floor(device_text_pos + 0.5) - device_text_pos;
|
||||
// Glyph raster pixels include the impact of the transform. This path can only be
|
||||
// entered for 3d transforms that can be coerced into a 2d transform; they have no
|
||||
// perspective, and have a 2d inverse. This is a looser condition than axis aligned
|
||||
// transforms because it also allows 2d rotations.
|
||||
vec2 raster_glyph_offset = glyph_transform * glyph_offset;
|
||||
vec2 raster_snap_offset = floor(raster_glyph_offset + snap_bias) - raster_glyph_offset;
|
||||
vec2 local_snap_offset = glyph_transform_inv * raster_snap_offset;
|
||||
|
||||
// Snap the glyph offset to a device pixel, using an appropriate bias depending
|
||||
// on whether subpixel positioning is required.
|
||||
vec2 device_glyph_offset = glyph_transform * glyph_offset;
|
||||
snap_offset += floor(device_glyph_offset + snap_bias) - device_glyph_offset;
|
||||
// We want to eliminate any subpixel translation in device space to ensure glyph
|
||||
// snapping is stable for equivalent glyph subpixel positions. Note that we must use
|
||||
// device pixels, and not glyph raster pixels for this purpose.
|
||||
vec2 device_text_pos = (transform.m * vec4(text_offset, 0.0, 1.0)).xy * task.device_pixel_scale;
|
||||
vec2 device_snap_offset = floor(device_text_pos + 0.5) - device_text_pos;
|
||||
|
||||
// Transform from glyph space back to local space.
|
||||
glyph_transform_inv = inverse(glyph_transform);
|
||||
|
||||
#ifndef WR_FEATURE_GLYPH_TRANSFORM
|
||||
// If not using transformed subpixels, the glyph rect is actually in local space.
|
||||
// So convert the snap offset back to local space.
|
||||
snap_offset = glyph_transform_inv * snap_offset;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// Otherwise, when in local raster space, the transform may be animated, so avoid
|
||||
// snapping with the transform to avoid oscillation.
|
||||
snap_offset = floor(text_offset + 0.5) - text_offset;
|
||||
snap_offset += floor(glyph_offset + snap_bias) - glyph_offset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Actually translate the glyph rect to a device pixel using the snap offset.
|
||||
glyph_rect.p0 += snap_offset;
|
||||
|
||||
#ifdef WR_FEATURE_GLYPH_TRANSFORM
|
||||
// The glyph rect is in device space, so transform it back to local space.
|
||||
RectWithSize local_rect = transform_rect(glyph_rect, glyph_transform_inv);
|
||||
|
||||
|
@ -148,6 +122,29 @@ VertexInfo write_text_vertex(RectWithSize local_clip_rect,
|
|||
local_pos = glyph_transform_inv * (glyph_rect.p0 + glyph_rect.size * aPosition.xy);
|
||||
}
|
||||
#else
|
||||
// Glyph raster pixels do not include the impact of the transform. Instead it was
|
||||
// replaced with an identity transform during glyph rasterization. As such only the
|
||||
// impact of the raster scale (if in local space) and the device pixel scale (for both
|
||||
// local and screen space) are included.
|
||||
//
|
||||
// This implies one or more of the following conditions:
|
||||
// - The transform is an identity. In that case, setting WR_FEATURE_GLYPH_TRANSFORM
|
||||
// should have the same output result as not. We just distingush which path to use
|
||||
// based on the transform used during glyph rasterization. (Screen space).
|
||||
// - The transform contains an animation. We will imply local raster space in such
|
||||
// cases to avoid constantly rerasterizing the glyphs.
|
||||
// - The transform has perspective or does not have a 2d inverse (Screen or local space).
|
||||
// - The transform's scale will result in result in very large rasterized glyphs and
|
||||
// we clamped the size. This will imply local raster space.
|
||||
vec2 raster_glyph_offset = glyph_offset * glyph_scale;
|
||||
vec2 raster_snap_offset = floor(raster_glyph_offset + snap_bias) - raster_glyph_offset;
|
||||
vec2 local_snap_offset = raster_snap_offset / glyph_scale;
|
||||
|
||||
// The transform may be animated, so we don't want to do any snapping here for the
|
||||
// text offset to avoid glyphs wiggling. The text offset should have been snapped
|
||||
// already for axis aligned transforms excluding any animations during frame building.
|
||||
vec2 device_snap_offset = vec2(0.0);
|
||||
|
||||
// Select the corner of the glyph rect that we are processing.
|
||||
vec2 local_pos = glyph_rect.p0 + glyph_rect.size * aPosition.xy;
|
||||
#endif
|
||||
|
@ -158,15 +155,17 @@ VertexInfo write_text_vertex(RectWithSize local_clip_rect,
|
|||
// Map the clamped local space corner into device space.
|
||||
vec4 world_pos = transform.m * vec4(local_pos, 0.0, 1.0);
|
||||
vec2 device_pos = world_pos.xy * task.device_pixel_scale;
|
||||
vec4 snapped_world_pos = transform.m * vec4(local_pos + local_snap_offset, 0.0, 1.0);
|
||||
vec2 snapped_device_pos = snapped_world_pos.xy * task.device_pixel_scale + device_snap_offset * snapped_world_pos.w;
|
||||
|
||||
// Apply offsets for the render task to get correct screen location.
|
||||
vec2 final_offset = -task.content_origin + task.common_data.task_rect.p0;
|
||||
|
||||
gl_Position = uTransform * vec4(device_pos + final_offset * world_pos.w, z * world_pos.w, world_pos.w);
|
||||
gl_Position = uTransform * vec4(snapped_device_pos + final_offset * world_pos.w, z * world_pos.w, world_pos.w);
|
||||
|
||||
VertexInfo vi = VertexInfo(
|
||||
local_pos,
|
||||
snap_offset,
|
||||
snapped_device_pos - device_pos,
|
||||
world_pos
|
||||
);
|
||||
|
||||
|
@ -186,8 +185,6 @@ void main(void) {
|
|||
ClipArea clip_area = fetch_clip_area(instance.clip_address);
|
||||
PictureTask task = fetch_picture_task(instance.picture_task_address);
|
||||
|
||||
int raster_space = ph.user_data.w;
|
||||
|
||||
TextRun text = fetch_text_run(ph.specific_prim_address);
|
||||
vec2 text_offset = vec2(ph.user_data.xy) / 256.0;
|
||||
|
||||
|
@ -211,11 +208,12 @@ void main(void) {
|
|||
float raster_scale = float(ph.user_data.z) / 65535.0;
|
||||
|
||||
// Scale from glyph space to local space.
|
||||
float scale = res.scale / (raster_scale * task.device_pixel_scale);
|
||||
float glyph_scale_inv = res.scale / (raster_scale * task.device_pixel_scale);
|
||||
float glyph_scale = 1.0 / glyph_scale_inv;
|
||||
|
||||
// Compute the glyph rect in local space.
|
||||
RectWithSize glyph_rect = RectWithSize(scale * res.offset + text_offset + glyph.offset,
|
||||
scale * (res.uv_rect.zw - res.uv_rect.xy));
|
||||
RectWithSize glyph_rect = RectWithSize(glyph_scale_inv * res.offset + text_offset + glyph.offset,
|
||||
glyph_scale_inv * (res.uv_rect.zw - res.uv_rect.xy));
|
||||
#endif
|
||||
|
||||
vec2 snap_bias;
|
||||
|
@ -245,14 +243,17 @@ void main(void) {
|
|||
|
||||
VertexInfo vi = write_text_vertex(ph.local_clip_rect,
|
||||
ph.z,
|
||||
raster_space,
|
||||
#ifdef WR_FEATURE_GLYPH_TRANSFORM
|
||||
glyph_transform,
|
||||
#else
|
||||
glyph_scale,
|
||||
#endif
|
||||
transform,
|
||||
task,
|
||||
text_offset,
|
||||
glyph.offset,
|
||||
glyph_rect,
|
||||
snap_bias);
|
||||
glyph_rect.p0 += vi.snap_offset;
|
||||
|
||||
#ifdef WR_FEATURE_GLYPH_TRANSFORM
|
||||
vec2 f = (glyph_transform * vi.local_pos - glyph_rect.p0) / glyph_rect.size;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use api::{AlphaType, ClipMode, ExternalImageType, ImageRendering};
|
||||
use api::{YuvColorSpace, YuvFormat, ColorDepth, ColorRange, PremultipliedColorF, RasterSpace};
|
||||
use api::{YuvColorSpace, YuvFormat, ColorDepth, ColorRange, PremultipliedColorF};
|
||||
use api::units::*;
|
||||
use crate::clip::{ClipDataStore, ClipNodeFlags, ClipNodeRange, ClipItemKind, ClipStore};
|
||||
use crate::clip_scroll_tree::{ClipScrollTree, ROOT_SPATIAL_NODE_INDEX, SpatialNodeIndex, CoordinateSystemId};
|
||||
|
@ -879,19 +879,15 @@ impl BatchBuilder {
|
|||
};
|
||||
|
||||
let glyph_keys = &ctx.scratch.glyph_keys[run.glyph_keys_range];
|
||||
let rasterization_space = match run.raster_space {
|
||||
RasterSpace::Screen => RasterizationSpace::Screen,
|
||||
RasterSpace::Local(..) => RasterizationSpace::Local,
|
||||
};
|
||||
let raster_scale = run.raster_space.local_scale().unwrap_or(1.0).max(0.001);
|
||||
let prim_header_index = prim_headers.push(
|
||||
&prim_header,
|
||||
z_id,
|
||||
[
|
||||
(run.reference_frame_relative_offset.x * 256.0) as i32,
|
||||
(run.reference_frame_relative_offset.y * 256.0) as i32,
|
||||
(run.snapped_reference_frame_relative_offset.x * 256.0) as i32,
|
||||
(run.snapped_reference_frame_relative_offset.y * 256.0) as i32,
|
||||
(raster_scale * 65535.0).round() as i32,
|
||||
(rasterization_space as i32),
|
||||
0,
|
||||
],
|
||||
);
|
||||
let base_instance = GlyphInstance::new(
|
||||
|
|
|
@ -16,7 +16,7 @@ use crate::clip::{ClipDataStore, ClipNodeFlags, ClipChainId, ClipChainInstance,
|
|||
use crate::debug_colors;
|
||||
use crate::debug_render::DebugItem;
|
||||
use crate::scene_building::{CreateShadow, IsVisible};
|
||||
use euclid::{SideOffsets2D, Transform3D, Rect, Scale, Size2D, Point2D};
|
||||
use euclid::{SideOffsets2D, Transform3D, Rect, Scale, Size2D, Point2D, Vector2D};
|
||||
use euclid::approxeq::ApproxEq;
|
||||
use crate::frame_builder::{FrameBuildingContext, FrameBuildingState, PictureContext, PictureState};
|
||||
use crate::frame_builder::{FrameVisibilityContext, FrameVisibilityState};
|
||||
|
@ -52,7 +52,7 @@ use std::{cmp, fmt, hash, ops, u32, usize, mem};
|
|||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use crate::storage;
|
||||
use crate::texture_cache::TEXTURE_REGION_DIMENSIONS;
|
||||
use crate::util::{MatrixHelpers, MaxRect, Recycler, ScaleOffset, RectHelpers};
|
||||
use crate::util::{MatrixHelpers, MaxRect, Recycler, ScaleOffset, RectHelpers, VectorHelpers};
|
||||
use crate::util::{clamp_to_scale_factor, pack_as_float, project_rect, raster_rect_to_device_pixels};
|
||||
use crate::internal_types::{LayoutPrimitiveInfo, Filter};
|
||||
use smallvec::SmallVec;
|
||||
|
@ -205,6 +205,17 @@ impl SpaceSnapper {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn snap_vector<F>(&self, vector: &Vector2D<f32, F>) -> Vector2D<f32, F> where F: fmt::Debug {
|
||||
debug_assert!(self.current_target_spatial_node_index != SpatialNodeIndex::INVALID);
|
||||
match self.snapping_transform {
|
||||
Some(ref scale_offset) => {
|
||||
let snapped_device_vector : DeviceVector2D = scale_offset.map_vector(&vector).snap();
|
||||
scale_offset.unmap_vector(&snapped_device_vector)
|
||||
}
|
||||
None => *vector,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn snap_size<F>(&self, size: &Size2D<f32, F>) -> Size2D<f32, F> where F: fmt::Debug {
|
||||
debug_assert!(self.current_target_spatial_node_index != SpatialNodeIndex::INVALID);
|
||||
match self.snapping_transform {
|
||||
|
@ -2911,11 +2922,13 @@ impl PrimitiveStore {
|
|||
&prim_data.glyphs,
|
||||
&transform.to_transform().with_destination::<_>(),
|
||||
surface,
|
||||
prim_spatial_node_index,
|
||||
raster_space,
|
||||
pic_context.subpixel_mode,
|
||||
frame_state.resource_cache,
|
||||
frame_state.gpu_cache,
|
||||
frame_state.render_tasks,
|
||||
frame_context.clip_scroll_tree,
|
||||
scratch,
|
||||
);
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use api::{ColorF, GlyphInstance, RasterSpace, Shadow};
|
||||
use api::units::{DevicePixelScale, LayoutToWorldTransform, LayoutVector2D};
|
||||
use api::units::{LayoutToWorldTransform, LayoutVector2D};
|
||||
use crate::scene_building::{CreateShadow, IsVisible};
|
||||
use crate::frame_builder::FrameBuildingState;
|
||||
use crate::glyph_rasterizer::{FontInstance, FontTransform, GlyphKey, FONT_SIZE_LIMIT};
|
||||
|
@ -17,7 +17,8 @@ use crate::render_task_graph::RenderTaskGraph;
|
|||
use crate::renderer::{MAX_VERTEX_TEXTURE_WIDTH};
|
||||
use crate::resource_cache::{ResourceCache};
|
||||
use crate::util::{MatrixHelpers};
|
||||
use crate::prim_store::{InternablePrimitive, PrimitiveInstanceKind};
|
||||
use crate::prim_store::{InternablePrimitive, PrimitiveInstanceKind, SpaceSnapper};
|
||||
use crate::clip_scroll_tree::{ClipScrollTree, SpatialNodeIndex};
|
||||
use std::ops;
|
||||
use std::sync::Arc;
|
||||
use crate::storage;
|
||||
|
@ -174,6 +175,7 @@ impl InternablePrimitive for TextRun {
|
|||
used_font: key.font.clone(),
|
||||
glyph_keys_range: storage::Range::empty(),
|
||||
reference_frame_relative_offset,
|
||||
snapped_reference_frame_relative_offset: reference_frame_relative_offset,
|
||||
shadow: key.shadow,
|
||||
raster_space: RasterSpace::Screen,
|
||||
});
|
||||
|
@ -212,6 +214,7 @@ pub struct TextRunPrimitive {
|
|||
pub used_font: FontInstance,
|
||||
pub glyph_keys_range: storage::Range<GlyphKey>,
|
||||
pub reference_frame_relative_offset: LayoutVector2D,
|
||||
pub snapped_reference_frame_relative_offset: LayoutVector2D,
|
||||
pub shadow: bool,
|
||||
pub raster_space: RasterSpace,
|
||||
}
|
||||
|
@ -220,10 +223,12 @@ impl TextRunPrimitive {
|
|||
pub fn update_font_instance(
|
||||
&mut self,
|
||||
specified_font: &FontInstance,
|
||||
device_pixel_scale: DevicePixelScale,
|
||||
surface: &SurfaceInfo,
|
||||
spatial_node_index: SpatialNodeIndex,
|
||||
transform: &LayoutToWorldTransform,
|
||||
subpixel_mode: SubpixelMode,
|
||||
raster_space: RasterSpace,
|
||||
clip_scroll_tree: &ClipScrollTree,
|
||||
) -> bool {
|
||||
// If local raster space is specified, include that in the scale
|
||||
// of the glyphs that get rasterized.
|
||||
|
@ -235,7 +240,7 @@ impl TextRunPrimitive {
|
|||
let raster_scale = raster_space.local_scale().unwrap_or(1.0).max(0.001);
|
||||
|
||||
// Get the current font size in device pixels
|
||||
let mut device_font_size = specified_font.size.scale_by(device_pixel_scale.0 * raster_scale);
|
||||
let mut device_font_size = specified_font.size.scale_by(surface.device_pixel_scale.0 * raster_scale);
|
||||
|
||||
// Determine if rasterizing glyphs in local or screen space.
|
||||
let transform_glyphs = if raster_space != RasterSpace::Screen {
|
||||
|
@ -266,6 +271,30 @@ impl TextRunPrimitive {
|
|||
// Record the raster space the text needs to be snapped in.
|
||||
self.raster_space = raster_space;
|
||||
|
||||
// TODO(aosmond): Snapping really ought to happen during scene building
|
||||
// as much as possible. This will allow clips to be already adjusted
|
||||
// based on the snapping requirements of the primitive. This may affect
|
||||
// complex clips that create a different task, and when we rasterize
|
||||
// glyphs without the transform (because the shader doesn't have the
|
||||
// snap offsets to adjust its clip). These rects are fairly conservative
|
||||
// to begin with and do not appear to be causing significant issues at
|
||||
// this time.
|
||||
self.snapped_reference_frame_relative_offset = if !font_transform.is_identity() {
|
||||
// Don't touch the reference frame relative offset. We'll let the
|
||||
// shader do the snapping in device pixels.
|
||||
self.reference_frame_relative_offset
|
||||
} else {
|
||||
// There may be an animation, so snap the reference frame relative
|
||||
// offset such that it excludes the impact, if any.
|
||||
let snap_to_device = SpaceSnapper::new_with_target(
|
||||
surface.raster_spatial_node_index,
|
||||
spatial_node_index,
|
||||
surface.device_pixel_scale,
|
||||
clip_scroll_tree,
|
||||
);
|
||||
snap_to_device.snap_vector(&self.reference_frame_relative_offset)
|
||||
};
|
||||
|
||||
// If the transform or device size is different, then the caller of
|
||||
// this method needs to know to rebuild the glyphs.
|
||||
let cache_dirty =
|
||||
|
@ -299,21 +328,23 @@ impl TextRunPrimitive {
|
|||
glyphs: &[GlyphInstance],
|
||||
transform: &LayoutToWorldTransform,
|
||||
surface: &SurfaceInfo,
|
||||
spatial_node_index: SpatialNodeIndex,
|
||||
raster_space: RasterSpace,
|
||||
subpixel_mode: SubpixelMode,
|
||||
resource_cache: &mut ResourceCache,
|
||||
gpu_cache: &mut GpuCache,
|
||||
render_tasks: &mut RenderTaskGraph,
|
||||
clip_scroll_tree: &ClipScrollTree,
|
||||
scratch: &mut PrimitiveScratchBuffer,
|
||||
) {
|
||||
let device_pixel_scale = surface.device_pixel_scale;
|
||||
|
||||
let cache_dirty = self.update_font_instance(
|
||||
specified_font,
|
||||
device_pixel_scale,
|
||||
surface,
|
||||
spatial_node_index,
|
||||
transform,
|
||||
subpixel_mode,
|
||||
raster_space,
|
||||
clip_scroll_tree,
|
||||
);
|
||||
|
||||
if self.glyph_keys_range.is_empty() || cache_dirty {
|
||||
|
@ -323,7 +354,7 @@ impl TextRunPrimitive {
|
|||
glyphs.iter().map(|src| {
|
||||
let src_point = src.point + prim_offset;
|
||||
let world_offset = self.used_font.transform.transform(&src_point);
|
||||
let device_offset = device_pixel_scale.transform_point(world_offset);
|
||||
let device_offset = surface.device_pixel_scale.transform_point(world_offset);
|
||||
GlyphKey::new(src.index, device_offset, subpx_dir)
|
||||
}));
|
||||
}
|
||||
|
@ -351,5 +382,5 @@ fn test_struct_sizes() {
|
|||
assert_eq!(mem::size_of::<TextRun>(), 56, "TextRun size changed");
|
||||
assert_eq!(mem::size_of::<TextRunTemplate>(), 72, "TextRunTemplate size changed");
|
||||
assert_eq!(mem::size_of::<TextRunKey>(), 64, "TextRunKey size changed");
|
||||
assert_eq!(mem::size_of::<TextRunPrimitive>(), 72, "TextRunPrimitive size changed");
|
||||
assert_eq!(mem::size_of::<TextRunPrimitive>(), 80, "TextRunPrimitive size changed");
|
||||
}
|
||||
|
|
|
@ -1114,6 +1114,12 @@ impl<'a> SceneBuilder<'a> {
|
|||
);
|
||||
}
|
||||
DisplayItem::Text(ref info) => {
|
||||
// TODO(aosmond): Snapping text primitives does not make much sense, given the
|
||||
// primitive bounds and clip are supposed to be conservative, not definitive.
|
||||
// E.g. they should be able to grow and not impact the output. However there
|
||||
// are subtle interactions between the primitive origin and the glyph offset
|
||||
// which appear to be significant (presumably due to some sort of accumulated
|
||||
// error throughout the layers). We should fix this at some point.
|
||||
let (layout, _, clip_and_scroll) = self.process_common_properties_with_bounds(
|
||||
&info.common,
|
||||
&info.bounds,
|
||||
|
|
|
@ -246,6 +246,20 @@ impl ScaleOffset {
|
|||
)
|
||||
}
|
||||
|
||||
pub fn map_vector<F, T>(&self, vector: &Vector2D<f32, F>) -> Vector2D<f32, T> {
|
||||
Vector2D::new(
|
||||
vector.x * self.scale.x + self.offset.x,
|
||||
vector.y * self.scale.y + self.offset.y,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn unmap_vector<F, T>(&self, vector: &Vector2D<f32, F>) -> Vector2D<f32, T> {
|
||||
Vector2D::new(
|
||||
(vector.x - self.offset.x) / self.scale.x,
|
||||
(vector.y - self.offset.y) / self.scale.y,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn to_transform<F, T>(&self) -> Transform3D<f32, F, T> {
|
||||
Transform3D::row_major(
|
||||
self.scale.x,
|
||||
|
|
|
@ -65,7 +65,7 @@ fuzzy(1,113) platform(linux) == raster-space.yaml raster-space.png
|
|||
skip_on(android) skip_on(mac,>=10.14) != allow-subpixel.yaml allow-subpixel-ref.yaml # Android: we don't enable sub-px aa on this platform.
|
||||
skip_on(android,device) == bg-color.yaml bg-color-ref.yaml # Fails on Pixel2
|
||||
!= large-glyphs.yaml blank.yaml
|
||||
== snap-text-offset.yaml snap-text-offset-ref.yaml
|
||||
skip_on(android,device) == snap-text-offset.yaml snap-text-offset-ref.yaml
|
||||
fuzzy(5,4435) == shadow-border.yaml shadow-solid-ref.yaml
|
||||
fuzzy(5,4435) == shadow-image.yaml shadow-solid-ref.yaml
|
||||
options(disable-aa) == snap-clip.yaml snap-clip-ref.yaml
|
||||
|
|
|
@ -98,8 +98,8 @@ fuzzy-if(webrender,0-52,0-14) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu
|
|||
== 503957-1.html 503957-1-ref.html
|
||||
== 525740-1.html 525740-1-ref.html
|
||||
== 536963-1.html 536963-1-ref.html
|
||||
fuzzy-if(webrender,0-122,0-1) == 562169-1.html 562169-1-ref.html
|
||||
fuzzy-if(webrender,0-122,0-1) == 562169-1a.html 562169-1-ref.html
|
||||
fuzzy-if(webrender,0-137,0-1) == 562169-1.html 562169-1-ref.html
|
||||
fuzzy-if(webrender,0-137,0-1) == 562169-1a.html 562169-1-ref.html
|
||||
== 562169-2.html 562169-2-ref.html
|
||||
== 562169-2a.html 562169-2-ref.html
|
||||
== 562169-3.html 562169-3-ref.html
|
||||
|
@ -158,7 +158,7 @@ random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == brackets-1a-ltr.html bra
|
|||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == brackets-1a-rtl.html brackets-1a-rtl-ref.html # Bug 1392106
|
||||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == brackets-1b-ltr.html brackets-1b-ltr-ref.html # Bug 1392106
|
||||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == brackets-1b-rtl.html brackets-1b-rtl-ref.html # Bug 1392106
|
||||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == brackets-1c-ltr.html brackets-1c-ltr-ref.html # Bug 1392106
|
||||
fuzzy-if(geckoview&&webrender,22-22,44-46) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == brackets-1c-ltr.html brackets-1c-ltr-ref.html # Bug 1392106
|
||||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == brackets-1c-rtl.html brackets-1c-rtl-ref.html # Bug 1392106
|
||||
fuzzy-if(Android,0-1,0-6) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == brackets-2a-ltr.html brackets-2a-ltr-ref.html # Bug 1392106
|
||||
fuzzy-if(cocoaWidget,0-1,0-2) fuzzy-if(Android,0-254,0-557) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == brackets-2a-rtl.html brackets-2a-rtl-ref.html # Bug 1392106
|
||||
|
|
|
@ -1789,7 +1789,7 @@ fuzzy-if(skiaContent,0-1,0-5) == 956513-1.svg 956513-1-ref.svg
|
|||
fuzzy-if(skiaContent,0-1,0-80) == 961887-1.html 961887-1-ref.html
|
||||
== 961887-2.html 961887-2-ref.html
|
||||
== 961887-3.html 961887-3-ref.html
|
||||
pref(layout.css.overflow-clip-box.enabled,true) fuzzy(0-50,0-145) fuzzy-if(asyncPan&&!layersGPUAccelerated,0-102,0-3712) fuzzy-if(webrender,0-255,0-51) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 966992-1.html 966992-1-ref.html # Bug 1392106
|
||||
pref(layout.css.overflow-clip-box.enabled,true) fuzzy(0-50,0-145) fuzzy-if(asyncPan&&!layersGPUAccelerated,0-102,0-3712) fuzzy-if(webrender,0-255,0-180) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 966992-1.html 966992-1-ref.html # Bug 1392106
|
||||
== 966510-1.html 966510-1-ref.html
|
||||
== 966510-2.html 966510-2-ref.html
|
||||
fuzzy-if(skiaContent,0-1,0-123) == 978911-1.svg 978911-1-ref.svg
|
||||
|
@ -2081,7 +2081,7 @@ pref(image.downscale-during-decode.enabled,true) == 1553571-1.html 1553571-1-ref
|
|||
== 1558937-1.html 1558937-1-ref.html
|
||||
!= 1563484.html 1563484-notref.html
|
||||
== 1563484.html 1563484-ref.html
|
||||
fuzzy-if(!webrender||!winWidget,251-255,464-1613) fuzzy-if(geckoview&&webrender,251-253,1392-1401) == 1562733-rotated-nastaliq-1.html 1562733-rotated-nastaliq-1-ref.html
|
||||
fuzzy-if(!webrender||!winWidget,251-255,464-1613) fuzzy-if(webrender&&winWidget,255-255,6-6) fuzzy-if(geckoview&&webrender,251-255,1392-1401) == 1562733-rotated-nastaliq-1.html 1562733-rotated-nastaliq-1-ref.html
|
||||
fuzzy-if(winWidget&&webrender,0-31,0-3) fuzzy-if(geckoview&&webrender,0-93,0-87) == 1562733-rotated-nastaliq-2.html 1562733-rotated-nastaliq-2-ref.html
|
||||
test-pref(plain_text.wrap_long_lines,false) != 1565129.txt 1565129.txt
|
||||
fuzzy(0-32,0-8) fuzzy-if(Android&&webrender,0-32,0-1458) == 1576553-1.html 1576553-1-ref.html
|
||||
|
|
|
@ -288,7 +288,7 @@ pref(privacy.reduceTimerPrecision,false) == anim-display-in-g-element.svg lime.s
|
|||
== anim-change-display-none-for-dynamically-appended-elem.html lime.html
|
||||
== anim-change-display-block-for-dynamically-appended-elem.html anim-standard-ref.html
|
||||
|
||||
fuzzy(0-63,0-146) fuzzy-if(skiaContent,0-31,0-308) fuzzy-if(webrender,0-7,0-240) == anim-clipPath-viewBox.svg anim-clipPath-viewBox-ref.svg
|
||||
fuzzy(0-63,0-146) fuzzy-if(skiaContent,0-31,0-308) fuzzy-if(webrender,0-7,0-241) == anim-clipPath-viewBox.svg anim-clipPath-viewBox-ref.svg
|
||||
|
||||
# Test animations for overflow.
|
||||
== anim-overflow-shorthand.svg anim-overflow-shorthand-ref.svg
|
||||
|
|
|
@ -28,14 +28,14 @@ fuzzy-if(webrender,35-70,699-715) == clip-path-circle-009.html clip-path-circle-
|
|||
fuzzy-if(webrender,35-70,699-735) == clip-path-circle-010.html clip-path-circle-004-ref.html
|
||||
fuzzy-if(webrender,35-70,699-725) == clip-path-circle-011.html clip-path-circle-005-ref.html
|
||||
fuzzy-if(webrender,35-70,699-715) == clip-path-circle-012.html clip-path-circle-006-ref.html
|
||||
fuzzy-if(webrender,35-70,699-715) == clip-path-circle-013.html clip-path-circle-002-ref.html
|
||||
fuzzy-if(webrender,35-70,699-733) == clip-path-circle-013.html clip-path-circle-002-ref.html
|
||||
fuzzy-if(webrender,34-70,699-885) == clip-path-circle-014.html clip-path-circle-007-ref.html
|
||||
fuzzy-if(webrender,34-70,699-905) == clip-path-circle-015.html clip-path-circle-008-ref.html
|
||||
fuzzy-if(webrender,34-70,699-840) == clip-path-circle-016.html clip-path-circle-009-ref.html
|
||||
fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu),0-16,0-9) fuzzy-if(webrender,34-70,699-885) == clip-path-circle-017.html clip-path-circle-007-ref.html
|
||||
fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu),0-16,0-9) fuzzy-if(webrender,34-70,699-893) == clip-path-circle-017.html clip-path-circle-007-ref.html
|
||||
fuzzy-if(webrender,35-70,699-725) == clip-path-circle-018.html clip-path-circle-010-ref.html
|
||||
fuzzy-if(webrender,35-70,699-715) == clip-path-circle-019.html clip-path-circle-002-ref.html
|
||||
fuzzy-if(webrender,35-70,699-715) == clip-path-circle-020.html clip-path-circle-002-ref.html
|
||||
fuzzy-if(webrender,35-70,699-733) == clip-path-circle-019.html clip-path-circle-002-ref.html
|
||||
fuzzy-if(webrender,35-70,699-733) == clip-path-circle-020.html clip-path-circle-002-ref.html
|
||||
fuzzy-if(webrender&&(winWidget||cocoaWidget),0-1,0-5) == clip-path-circle-021.html clip-path-circle-021-ref.html
|
||||
|
||||
fuzzy-if(webrender,36-36,1099-1100) == clip-path-ellipse-001.html clip-path-ellipse-001-ref.html
|
||||
|
|
|
@ -5,7 +5,7 @@ fuzzy-if(Android,0-16,0-244) fuzzy-if(webrender,0-47,0-6) == marker-basic.html m
|
|||
fuzzy-if(webrender,0-47,0-18) == bidi-simple.html bidi-simple-ref.html
|
||||
skip-if(!gtkWidget) fuzzy-if(gtkWidget,0-124,0-289) == bidi-simple-scrolled.html bidi-simple-scrolled-ref.html # Fails on Windows and OSX due to anti-aliasing
|
||||
fuzzy-if(Android,0-24,0-4000) fuzzy-if(cocoaWidget,0-1,0-40) fuzzy-if(asyncPan&&!layersGPUAccelerated,0-149,0-1836) == scroll-rounding.html scroll-rounding-ref.html # bug 760264
|
||||
fuzzy(0-16,0-454) fails-if(gtkWidget) fuzzy-if(webrender&&winWidget,50-85,454-499) fuzzy-if(webrender&&OSX,7-7,143-143) skip-if(OSX&&!isDebugBuild&&verify) == anonymous-block.html anonymous-block-ref.html # gtkWidget:bug 1309103, fuzzy: subpixel aa
|
||||
fuzzy(0-16,0-454) fails-if(gtkWidget) fuzzy-if(webrender&&winWidget,50-85,454-499) fuzzy-if(webrender&&OSX,15-15,145-145) skip-if(OSX&&!isDebugBuild&&verify) == anonymous-block.html anonymous-block-ref.html # gtkWidget:bug 1309103, fuzzy: subpixel aa
|
||||
fuzzy-if(webrender,0-47,0-3) == false-marker-overlap.html false-marker-overlap-ref.html
|
||||
== visibility-hidden.html visibility-hidden-ref.html
|
||||
fuzzy-if(asyncPan&&!layersGPUAccelerated,0-102,0-1724) fuzzy-if(gtkWidget,0-10,0-8) fuzzy-if(webrender,0-47,0-24) == block-padding.html block-padding-ref.html
|
||||
|
|
|
@ -186,7 +186,7 @@ random-if(!winWidget) == arial-bold-lam-alef-1.html arial-bold-lam-alef-1-ref.ht
|
|||
fails-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 1320665-cmap-format-13.html 1320665-cmap-format-13-ref.html # see bug 1320665 comments 8-9
|
||||
== 1331339-script-extensions-shaping-1.html 1331339-script-extensions-shaping-1-ref.html
|
||||
skip-if(!cocoaWidget) != 1349308-1.html 1349308-notref.html # macOS-specific test for -apple-system glyph metrics
|
||||
fuzzy-if(Android,0-128,0-230) fails-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)) == 1463020-letter-spacing-text-transform-1.html 1463020-letter-spacing-text-transform-1-ref.html # Win10: regional indicators not supported by system emoji font
|
||||
fuzzy-if(Android,0-128,0-233) fails-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)) == 1463020-letter-spacing-text-transform-1.html 1463020-letter-spacing-text-transform-1-ref.html # Win10: regional indicators not supported by system emoji font
|
||||
fails-if(Android) == 1463020-letter-spacing-text-transform-2.html 1463020-letter-spacing-text-transform-2-ref.html # missing font coverage on Android
|
||||
== 1507661-spurious-hyphenation-after-explicit.html 1507661-spurious-hyphenation-after-explicit-ref.html
|
||||
fuzzy-if(!webrender,12-66,288-1660) fails-if(gtkWidget&&!webrender) == 1522857-1.html 1522857-1-ref.html # antialiasing fuzz in non-webrender cases
|
||||
|
|
|
@ -16,7 +16,7 @@ random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == descriptor-negative.html
|
|||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == descriptor-prefix.html descriptor-prefix-ref.html # Bug 1392106
|
||||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == descriptor-suffix.html descriptor-suffix-ref.html # Bug 1392106
|
||||
== descriptor-range.html descriptor-range-ref.html
|
||||
fuzzy-if(webrender,0-22,0-3) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == descriptor-pad.html descriptor-pad-ref.html # Bug 1392106
|
||||
fuzzy-if(webrender,0-92,0-3) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == descriptor-pad.html descriptor-pad-ref.html # Bug 1392106
|
||||
== descriptor-fallback.html descriptor-fallback-ref.html
|
||||
== descriptor-symbols.html descriptor-symbols-ref.html
|
||||
== descriptor-negative-invalid.html descriptor-negative-invalid-ref.html
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
needs-focus == focus-within-1.html focus-within-1-ref.html
|
||||
needs-focus == focus-within-2.html focus-within-2-ref.html
|
||||
needs-focus == focus-within-3.html focus-within-3-ref.html
|
||||
fuzzy-if(webrender,0-122,0-1) == dir-style-01a.html dir-style-01-ref.html
|
||||
fuzzy-if(webrender,0-122,0-1) == dir-style-01b.html dir-style-01-ref.html
|
||||
fuzzy-if(webrender,0-137,0-1) == dir-style-01a.html dir-style-01-ref.html
|
||||
fuzzy-if(webrender,0-137,0-1) == dir-style-01b.html dir-style-01-ref.html
|
||||
== dir-style-02a.html dir-style-02-ref.html
|
||||
== dir-style-02b.html dir-style-02-ref.html
|
||||
== dir-style-03a.html dir-style-03-ref.html
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
# rendering.) We could probably make them pass by implementing some quirks, if
|
||||
# it turns out that the web depends on WebKit/Blink's behavior in these cases.
|
||||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == webkit-box-anon-flex-items-1a.html webkit-box-anon-flex-items-1-ref.html # Bug 1392106
|
||||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == webkit-box-anon-flex-items-1b.html webkit-box-anon-flex-items-1-ref.html # Bug 1392106
|
||||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fuzzy-if(geckoview&&webrender,150-150,7-7) == webkit-box-anon-flex-items-1b.html webkit-box-anon-flex-items-1-ref.html # Bug 1392106
|
||||
fails == webkit-box-anon-flex-items-2.html webkit-box-anon-flex-items-2-ref.html
|
||||
fails == webkit-box-anon-flex-items-3.html webkit-box-anon-flex-items-3-ref.html
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 1102175-1b.html 1102175-
|
|||
== 1105268-2-min-max-dimensions.html 1105268-2-min-max-dimensions-ref.html
|
||||
== 1106669-1-intrinsic-for-container.html 1106669-1-intrinsic-for-container-ref.html
|
||||
== 1108923-1-percentage-margins.html 1108923-1-percentage-margins-ref.html
|
||||
fuzzy-if(Android,0-128,0-78) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 1111944-1-list-marker.html 1111944-1-list-marker-ref.html # Bug 1392106
|
||||
fuzzy-if(Android,0-128,0-94) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 1111944-1-list-marker.html 1111944-1-list-marker-ref.html # Bug 1392106
|
||||
fuzzy(0-116,0-94) fuzzy-if(winWidget,0-135,0-124) == 1115916-1-vertical-metrics.html 1115916-1-vertical-metrics-ref.html
|
||||
== 1117210-1-vertical-baseline-snap.html 1117210-1-vertical-baseline-snap-ref.html
|
||||
== 1117227-1-text-overflow.html 1117227-1-text-overflow-ref.html
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
[list-style-type-string-002.html]
|
||||
fuzzy:
|
||||
if webrender and (os == "win"): maxDifference=137;totalPixels=2
|
|
@ -0,0 +1,3 @@
|
|||
[webkit-line-clamp-024.html]
|
||||
fuzzy:
|
||||
if webrender and (os == "win"): maxDifference=47;totalPixels=1
|
|
@ -0,0 +1,3 @@
|
|||
[webkit-line-clamp-027.html]
|
||||
fuzzy:
|
||||
if webrender and (os == "win"): maxDifference=47;totalPixels=1
|
|
@ -0,0 +1,3 @@
|
|||
[webkit-line-clamp-029.html]
|
||||
fuzzy:
|
||||
if webrender and (os == "win"): maxDifference=47;totalPixels=1
|
|
@ -0,0 +1,3 @@
|
|||
[webkit-line-clamp-030.html]
|
||||
fuzzy:
|
||||
if webrender and (os == "win"): maxDifference=47;totalPixels=1
|
|
@ -0,0 +1,3 @@
|
|||
[text-overflow-026.html]
|
||||
fuzzy:
|
||||
if webrender and (os == "win"): maxDifference=47;totalPixels=3
|
|
@ -0,0 +1,3 @@
|
|||
[descriptor-pad.html]
|
||||
fuzzy:
|
||||
if webrender and (os == "win"): maxDifference=92;totalPixels=3
|
|
@ -0,0 +1,3 @@
|
|||
[dir-style-01a.html]
|
||||
fuzzy:
|
||||
if webrender and (os == "win"): maxDifference=137;totalPixels=1
|
|
@ -0,0 +1,3 @@
|
|||
[dir-style-01b.html]
|
||||
fuzzy:
|
||||
if webrender and (os == "win"): maxDifference=137;totalPixels=1
|
Загрузка…
Ссылка в новой задаче