Bug 1571974: Make prim_store::get_line_decoration_sizes return an oriented LayoutSize. r=kvark

Without this change, get_line_decoration_sizes returns an (inline_size,
block_size) pair, where inline_size is parallel to the line being decorated, and
block_size perpendicular. However, these values are generally used as the
dimensions of an axis-aligned bounding box for the line, not as specific
parameters to the rendering process, so it makes sense to arrange them into a
LayoutSize value in this function, since it is already taking the orientation
into account anyway.

The caller, SceneBuilder::add_line, then doesn't need to swap the components,
and the adjustment of the clipping rectangle to avoid partial dots looks a bit
more natural: widths with widths, heights with heights.

Differential Revision: https://phabricator.services.mozilla.com/D60925

--HG--
extra : rebase_source : 093d572a7a35bddc6e070fc08d511f7f164a4d89
extra : source : 3549dd471446c291864822736f4587c81741cd56
This commit is contained in:
Jim Blandy 2020-02-03 09:31:22 +00:00
parent 3d5caced73
commit 3e1f7b939b
2 changed files with 38 additions and 20 deletions

View File

@ -4129,14 +4129,32 @@ pub fn get_raster_rects(
Some((clipped.to_i32(), unclipped))
}
/// Get the inline (horizontal) and block (vertical) sizes
/// for a given line decoration.
pub fn get_line_decoration_sizes(
/// Choose the decoration mask tile size for a given line.
///
/// Given a line with overall size `rect_size` and the given `orientation`,
/// return the dimensions of a single mask tile for the decoration pattern
/// described by `style` and `wavy_line_thickness`.
///
/// If `style` is `Solid`, no mask tile is necessary; return `None`. The other
/// styles each have their own characteristic periods of repetition, so for each
/// one, this function returns a `LayoutSize` with the right aspect ratio and
/// whose specific size is convenient for the `cs_line_decoration.glsl` fragment
/// shader to work with. The shader uses a local coordinate space in which the
/// tile fills a rectangle with one corner at the origin, and with the size this
/// function returns.
///
/// The returned size is not necessarily in pixels; device scaling and other
/// concerns can still affect the actual task size.
///
/// Regardless of whether `orientation` is `Vertical` or `Horizontal`, the
/// `width` and `height` of the returned size are always horizontal and
/// vertical, respectively.
pub fn get_line_decoration_size(
rect_size: &LayoutSize,
orientation: LineOrientation,
style: LineStyle,
wavy_line_thickness: f32,
) -> Option<(f32, f32)> {
) -> Option<LayoutSize> {
let h = match orientation {
LineOrientation::Horizontal => rect_size.height,
LineOrientation::Vertical => rect_size.width,
@ -4148,20 +4166,20 @@ pub fn get_line_decoration_sizes(
// quality on a wider range of inputs!
// See nsCSSRendering::PaintDecorationLine in Gecko.
match style {
let (parallel, perpendicular) = match style {
LineStyle::Solid => {
None
return None;
}
LineStyle::Dashed => {
let dash_length = (3.0 * h).min(64.0).max(1.0);
Some((2.0 * dash_length, 4.0))
(2.0 * dash_length, 4.0)
}
LineStyle::Dotted => {
let diameter = h.min(64.0).max(1.0);
let period = 2.0 * diameter;
Some((period, diameter))
(period, diameter)
}
LineStyle::Wavy => {
let line_thickness = wavy_line_thickness.max(1.0);
@ -4169,9 +4187,14 @@ pub fn get_line_decoration_sizes(
let flat_length = ((line_thickness - 1.0) * 2.0).max(1.0);
let approx_period = 2.0 * (slope_length + flat_length);
Some((approx_period, h))
(approx_period, h)
}
}
};
Some(match orientation {
LineOrientation::Horizontal => LayoutSize::new(parallel, perpendicular),
LineOrientation::Vertical => LayoutSize::new(perpendicular, parallel),
})
}
fn update_opacity_binding(

View File

@ -27,7 +27,7 @@ use crate::prim_store::{PrimitiveInstance, PrimitiveSceneData};
use crate::prim_store::{PrimitiveInstanceKind, NinePatchDescriptor, PrimitiveStore};
use crate::prim_store::{ScrollNodeAndClipChain, PictureIndex};
use crate::prim_store::{InternablePrimitive, SegmentInstanceIndex};
use crate::prim_store::{register_prim_chase_id, get_line_decoration_sizes};
use crate::prim_store::{register_prim_chase_id, get_line_decoration_size};
use crate::prim_store::{SpaceSnapper};
use crate::prim_store::backdrop::Backdrop;
use crate::prim_store::borders::{ImageBorder, NormalBorderPrim};
@ -2749,33 +2749,28 @@ impl<'a> SceneBuilder<'a> {
// pixel ratio or transform.
let mut info = info.clone();
let size = get_line_decoration_sizes(
let size = get_line_decoration_size(
&info.rect.size,
orientation,
style,
wavy_line_thickness,
);
let cache_key = size.map(|(inline_size, block_size)| {
let size = match orientation {
LineOrientation::Horizontal => LayoutSize::new(inline_size, block_size),
LineOrientation::Vertical => LayoutSize::new(block_size, inline_size),
};
let cache_key = size.map(|size| {
// If dotted, adjust the clip rect to ensure we don't draw a final
// partial dot.
if style == LineStyle::Dotted {
let clip_size = match orientation {
LineOrientation::Horizontal => {
LayoutSize::new(
inline_size * (info.rect.size.width / inline_size).floor(),
size.width * (info.rect.size.width / size.width).floor(),
info.rect.size.height,
)
}
LineOrientation::Vertical => {
LayoutSize::new(
info.rect.size.width,
inline_size * (info.rect.size.height / inline_size).floor(),
size.height * (info.rect.size.height / size.height).floor(),
)
}
};