Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] svg: support <circle> element #17681

Closed
wants to merge 10 commits into from

layout: generate geometries for SVG

Add SvgDisplayItem to display list, and generate geometries for SVG.
  • Loading branch information
stshine committed Sep 11, 2017
commit 516cffad5aeb762d8b3e1e3223bfd9365aadd5a8
@@ -19,3 +19,5 @@ opt-level = 3
# crate, add that here. Use the form:
#
# <crate> = { path = "/path/to/local/checkout" }
"webrender" = { path = '../webrender/webrender/' }
"webrender_api" = { path = '../webrender/webrender_api/' }
@@ -600,6 +600,7 @@ pub enum DisplayItem {
SolidColor(Box<SolidColorDisplayItem>),
Text(Box<TextDisplayItem>),
Image(Box<ImageDisplayItem>),
Svg(Box<SvgDisplayItem>),
Border(Box<BorderDisplayItem>),
Gradient(Box<GradientDisplayItem>),
RadialGradient(Box<RadialGradientDisplayItem>),
@@ -906,6 +907,13 @@ pub enum TextOrientation {
SidewaysRight,
}

/// Paints an svg.
#[derive(Clone, HeapSizeOf, Deserialize, Serialize)]
pub struct SvgDisplayItem {
pub base: BaseDisplayItem,
pub key: webrender_api::GeometryKey,
}

/// Paints an image.
#[derive(Clone, Deserialize, HeapSizeOf, Serialize)]
pub struct ImageDisplayItem {
@@ -1242,6 +1250,7 @@ impl DisplayItem {
DisplayItem::SolidColor(ref solid_color) => &solid_color.base,
DisplayItem::Text(ref text) => &text.base,
DisplayItem::Image(ref image_item) => &image_item.base,
DisplayItem::Svg(ref svg_item) => &svg_item.base,
DisplayItem::Border(ref border) => &border.base,
DisplayItem::Gradient(ref gradient) => &gradient.base,
DisplayItem::RadialGradient(ref gradient) => &gradient.base,
@@ -1367,6 +1376,7 @@ impl fmt::Debug for DisplayItem {
text.range.begin().0 as usize..(text.range.begin().0 + text.range.length().0) as usize])
}
DisplayItem::Image(_) => "Image".to_owned(),
DisplayItem::Svg(_) => "SVG".to_owned(),
DisplayItem::Border(_) => "Border".to_owned(),
DisplayItem::Gradient(_) => "Gradient".to_owned(),
DisplayItem::RadialGradient(_) => "RadialGradient".to_owned(),
@@ -14,13 +14,14 @@ use app_units::{AU_PER_PX, Au};
use block::{BlockFlow, BlockStackingContextType};
use canvas_traits::canvas::{CanvasMsg, FromLayoutMsg};
use context::LayoutContext;
use core::f32::consts::PI;
use euclid::{Point2D, Rect, SideOffsets2D, Size2D, Transform3D, TypedSize2D};
use euclid::Vector2D;
use flex::FlexFlow;
use flow::{BaseFlow, Flow, IS_ABSOLUTELY_POSITIONED};
use flow_ref::FlowRef;
use fragment::{CanvasFragmentSource, CoordinateSystem, Fragment, ImageFragmentInfo, ScannedTextFragmentInfo};
use fragment::{SpecificFragmentInfo, TruncatedFragmentInfo};
use fragment::{SpecificFragmentInfo, SVGData, SVGItem, TruncatedFragmentInfo};
use gfx::display_list;
use gfx::display_list::{BLUR_INFLATION_FACTOR, BaseDisplayItem, BorderDetails, BorderDisplayItem};
use gfx::display_list::{BorderRadii, BoxShadowClipMode, BoxShadowDisplayItem, ClippingRegion};
@@ -29,7 +30,7 @@ use gfx::display_list::{GradientDisplayItem, IframeDisplayItem, ImageBorder, Ima
use gfx::display_list::{LineDisplayItem, NormalBorder, OpaqueNode, PushTextShadowDisplayItem};
use gfx::display_list::{PopTextShadowDisplayItem, RadialGradientDisplayItem, ScrollRoot};
use gfx::display_list::{ScrollRootType, SolidColorDisplayItem, StackingContext, StackingContextType};
use gfx::display_list::{TextDisplayItem, TextOrientation, WebRenderImageInfo};
use gfx::display_list::{SvgDisplayItem, TextDisplayItem, TextOrientation, WebRenderImageInfo};
use gfx_traits::{combine_id_with_fragment_type, FragmentType, StackingContextId};
use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFlow, LAST_FRAGMENT_OF_ELEMENT};
use ipc_channel::ipc;
@@ -60,7 +61,9 @@ use style::values::{Either, RGBA};
use style::values::computed::{Angle, Gradient, GradientItem, LengthOrPercentage, Percentage};
use style::values::computed::{LengthOrPercentageOrAuto, NumberOrPercentage, Position};
use style::values::computed::effects::SimpleShadow;
// use style::values::computed::SVGPaint;
use style::values::computed::image::{EndingShape, LineDirection};
use style::values::generics::SVGPaintKind;
use style::values::generics::background::BackgroundSize;
use style::values::generics::effects::Filter;
use style::values::generics::image::{Circle, Ellipse, EndingShape as GenericEndingShape};
@@ -72,10 +75,11 @@ use style_traits::CSSPixel;
use style_traits::ToCss;
use style_traits::cursor::Cursor;
use table_cell::CollapsedBordersForCell;
use webrender_api::{ClipAndScrollInfo, ClipId, ColorF, ComplexClipRegion, GradientStop, LineStyle};
use webrender_api::{ClipAndScrollInfo, ClipId, ColorF, ColorU, ComplexClipRegion, GradientStop, LineStyle};
use webrender_api::{LocalClip, RepeatMode, ScrollPolicy, ScrollSensitivity, StickyFrameInfo};
use webrender_api::StickySideConstraint;
use webrender_helpers::{ToBorderRadius, ToMixBlendMode, ToRectF, ToTransformStyle};
use webrender_api::{Command, Geometry, GeometryItem, Shape};

trait ResolvePercentage {
fn resolve(&self, length: u32) -> u32;
@@ -110,6 +114,54 @@ fn establishes_containing_block_for_absolute(can_establish_containing_block: Est
position::T::static_ != positioning
}

fn to_geometry(items: &[SVGItem], width: Au, height: Au) -> Geometry {
let mut geometry = Vec::new();
for item in items {
match item.data {
SVGData::Circle => {
let fill_style = match item.style.get_inheritedsvg().fill.kind {
SVGPaintKind::Color(color) =>

This comment has been minimized.

Copy link
@emilio

emilio Jul 12, 2017

Member

nit: Indentation here looks weird, without a wrapping block.

ColorU {
r: color.red,
g: color.green,
b: color.blue,
a: color.alpha,
},
_ =>
ColorU {
r: 0,
g: 0,
b: 0,
a: 255,
}

};
let cx = item.style.get_svg().cx.to_used_value(width).to_f32_px();
let cy = item.style.get_svg().cy.to_used_value(height).to_f32_px();
let diagonal = Au::from_f32_px(((width.0 * width.0 + height.0 * height.0) as f32).sqrt());
let radius = item.style.get_svg().r.to_used_value(diagonal).to_f32_px();
let center = Point2D::new(cx, cy);
// Mathematically, a ‘circle’ element is mapped to an equivalent
// ‘path’ element that consists of four elliptical arc segments,
// each covering a quarter of the circle. The path begins at the
// "3 o'clock" point on the radius and proceeds in a clock-wise
// direction (before any transformations).
let mut path = Vec::with_capacity(4);
path.push(Command::Arc(center, radius, PI / 2.0, PI));
path.push(Command::Arc(center, radius, PI, PI * 1.5));
path.push(Command::Arc(center, radius, PI * 1.5, PI * 2.0));
path.push(Command::Arc(center, radius, 0.0, PI / 2.0));
geometry.push(GeometryItem::Shape(Shape {
path: path,
fill: fill_style
}));
}
_ => {}
}
}
geometry
}

trait RgbColor {
fn rgb(r: u8, g: u8, b: u8) -> Self;
}
@@ -1940,8 +1992,7 @@ impl FragmentDisplayListBuilding for Fragment {
SpecificFragmentInfo::InlineBlock(_) |
SpecificFragmentInfo::InlineAbsoluteHypothetical(_) |
SpecificFragmentInfo::InlineAbsolute(_) |
SpecificFragmentInfo::TruncatedFragment(_) |
SpecificFragmentInfo::Svg(_) => {
SpecificFragmentInfo::TruncatedFragment(_) => {
if opts::get().show_debug_fragment_borders {
self.build_debug_borders_around_fragment(state,
stacking_relative_border_box,
@@ -1988,6 +2039,26 @@ impl FragmentDisplayListBuilding for Fragment {
}));
}
}
SpecificFragmentInfo::Svg(ref mut info) => {
let base = state.create_base_display_item(
&stacking_relative_content_box,
LocalClip::from(clip.to_rectf()),
self.node,
self.style.get_cursor(Cursor::Default),
DisplayListSection::Content);
let geometry = to_geometry(&info.items,
stacking_relative_content_box.size.width,
stacking_relative_content_box.size.height);
state
.layout_context
.image_cache
.update_geometry(info.geometry_key, geometry);

state.add_display_item(DisplayItem::Svg(box SvgDisplayItem {
base: base,
key: info.geometry_key,
}));
}
SpecificFragmentInfo::Canvas(ref canvas_fragment_info) => {
let computed_width = canvas_fragment_info.dom_width.to_px();
let computed_height = canvas_fragment_info.dom_height.to_px();
@@ -304,6 +304,11 @@ impl WebRenderDisplayItemConverter for DisplayItem {
}
}
}
DisplayItem::Svg(ref item) => {
builder.push_geometry(item.base.bounds.to_rectf(),
Some(item.base.local_clip),
item.key);
}
DisplayItem::Border(ref item) => {
let rect = item.base.bounds.to_rectf();
let widths = item.border_widths.to_border_widths();
@@ -811,12 +811,8 @@ impl<T> DeclaredValueOwned<T> {
}

/// An unparsed property value that contains `var()` functions.
<<<<<<< 433b0ba3bfba657b9544a09ab338f21591bf5333
#[derive(Debug, Eq, PartialEq)]
=======
#[derive(PartialEq, Eq, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
>>>>>>> style: Derive HeapSizeOf for PropertyDeclarationBlock
pub struct UnparsedValue {
/// The css serialization for this value.
css: String,
@@ -1278,12 +1274,8 @@ impl PropertyParserContext {
}

/// Servo's representation for a property declaration.
<<<<<<< 433b0ba3bfba657b9544a09ab338f21591bf5333
#[derive(Clone, PartialEq)]
=======
#[derive(PartialEq, Clone)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
>>>>>>> style: Derive HeapSizeOf for PropertyDeclarationBlock
pub enum PropertyDeclaration {
% for property in data.longhands:
/// ${property.name}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.