mirror of
https://github.com/servo/servo.git
synced 2025-08-04 05:00:08 +01:00
auto merge of #4137 : ebalint/servo/canvas, r=jdm
Content of the canvas is drawn, tests/html/test_canvas.html now works.
This commit is contained in:
commit
da400a7a45
11 changed files with 359 additions and 130 deletions
|
@ -9,13 +9,15 @@ use geom::size::Size2D;
|
||||||
use servo_util::task::spawn_named;
|
use servo_util::task::spawn_named;
|
||||||
|
|
||||||
use std::comm;
|
use std::comm;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
#[deriving(Copy)]
|
#[deriving(Clone)]
|
||||||
pub enum CanvasMsg {
|
pub enum CanvasMsg {
|
||||||
FillRect(Rect<f32>),
|
FillRect(Rect<f32>),
|
||||||
ClearRect(Rect<f32>),
|
ClearRect(Rect<f32>),
|
||||||
StrokeRect(Rect<f32>),
|
StrokeRect(Rect<f32>),
|
||||||
Recreate(Size2D<i32>),
|
Recreate(Size2D<i32>),
|
||||||
|
SendPixelContents(Sender<Arc<Vec<u8>>>),
|
||||||
Close,
|
Close,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +31,7 @@ pub struct CanvasPaintTask {
|
||||||
impl CanvasPaintTask {
|
impl CanvasPaintTask {
|
||||||
fn new(size: Size2D<i32>) -> CanvasPaintTask {
|
fn new(size: Size2D<i32>) -> CanvasPaintTask {
|
||||||
CanvasPaintTask {
|
CanvasPaintTask {
|
||||||
drawtarget: CanvasPaintTask::create(size),
|
drawtarget: CanvasPaintTask::create_with_data(size),
|
||||||
fill_color: ColorPattern::new(Color::new(0., 0., 0., 1.)),
|
fill_color: ColorPattern::new(Color::new(0., 0., 0., 1.)),
|
||||||
stroke_color: ColorPattern::new(Color::new(0., 0., 0., 1.)),
|
stroke_color: ColorPattern::new(Color::new(0., 0., 0., 1.)),
|
||||||
stroke_opts: StrokeOptions::new(1.0, 1.0),
|
stroke_opts: StrokeOptions::new(1.0, 1.0),
|
||||||
|
@ -47,6 +49,7 @@ impl CanvasPaintTask {
|
||||||
CanvasMsg::StrokeRect(ref rect) => painter.stroke_rect(rect),
|
CanvasMsg::StrokeRect(ref rect) => painter.stroke_rect(rect),
|
||||||
CanvasMsg::ClearRect(ref rect) => painter.clear_rect(rect),
|
CanvasMsg::ClearRect(ref rect) => painter.clear_rect(rect),
|
||||||
CanvasMsg::Recreate(size) => painter.recreate(size),
|
CanvasMsg::Recreate(size) => painter.recreate(size),
|
||||||
|
CanvasMsg::SendPixelContents(chan) => painter.send_pixel_contents(chan),
|
||||||
CanvasMsg::Close => break,
|
CanvasMsg::Close => break,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,11 +71,20 @@ impl CanvasPaintTask {
|
||||||
self.drawtarget.stroke_rect(rect, &self.stroke_color, &self.stroke_opts, &drawopts);
|
self.drawtarget.stroke_rect(rect, &self.stroke_color, &self.stroke_opts, &drawopts);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create(size: Size2D<i32>) -> DrawTarget {
|
fn create_with_data(size: Size2D<i32>) -> DrawTarget {
|
||||||
DrawTarget::new(BackendType::Skia, size, SurfaceFormat::B8G8R8A8)
|
DrawTarget::new_with_data(BackendType::Skia,
|
||||||
|
Vec::from_elem((size.width * size.height * 4) as uint, 0u8),
|
||||||
|
0,
|
||||||
|
size,
|
||||||
|
size.width * 4,
|
||||||
|
SurfaceFormat::B8G8R8A8)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn recreate(&mut self, size: Size2D<i32>) {
|
fn recreate(&mut self, size: Size2D<i32>) {
|
||||||
self.drawtarget = CanvasPaintTask::create(size);
|
self.drawtarget = CanvasPaintTask::create_with_data(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn send_pixel_contents(&mut self, chan: Sender<Arc<Vec<u8>>>) {
|
||||||
|
chan.send(self.drawtarget.data.clone().unwrap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ use flow;
|
||||||
use flow_ref::FlowRef;
|
use flow_ref::FlowRef;
|
||||||
use fragment::{Fragment, IframeFragmentInfo};
|
use fragment::{Fragment, IframeFragmentInfo};
|
||||||
use fragment::ImageFragmentInfo;
|
use fragment::ImageFragmentInfo;
|
||||||
|
use fragment::CanvasFragmentInfo;
|
||||||
use fragment::InlineAbsoluteHypotheticalFragmentInfo;
|
use fragment::InlineAbsoluteHypotheticalFragmentInfo;
|
||||||
use fragment::{InlineBlockFragmentInfo, SpecificFragmentInfo};
|
use fragment::{InlineBlockFragmentInfo, SpecificFragmentInfo};
|
||||||
use fragment::TableColumnFragmentInfo;
|
use fragment::TableColumnFragmentInfo;
|
||||||
|
@ -272,6 +273,9 @@ impl<'a> FlowConstructor<'a> {
|
||||||
Some(NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableRowElement))) |
|
Some(NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableRowElement))) |
|
||||||
Some(NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableSectionElement))) => SpecificFragmentInfo::TableRow,
|
Some(NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableSectionElement))) => SpecificFragmentInfo::TableRow,
|
||||||
Some(NodeTypeId::Text) => SpecificFragmentInfo::UnscannedText(UnscannedTextFragmentInfo::new(node)),
|
Some(NodeTypeId::Text) => SpecificFragmentInfo::UnscannedText(UnscannedTextFragmentInfo::new(node)),
|
||||||
|
Some(NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLCanvasElement))) => {
|
||||||
|
SpecificFragmentInfo::Canvas(box CanvasFragmentInfo::new(node))
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
// This includes pseudo-elements.
|
// This includes pseudo-elements.
|
||||||
SpecificFragmentInfo::Generic
|
SpecificFragmentInfo::Generic
|
||||||
|
@ -1145,7 +1149,7 @@ impl<'a> PostorderNodeMutTraversal for FlowConstructor<'a> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
debug!("building flow for node: {} {}", display, float);
|
debug!("building flow for node: {} {} {}", display, float, node.type_id());
|
||||||
|
|
||||||
// Switch on display and floatedness.
|
// Switch on display and floatedness.
|
||||||
match (display, float, positioning) {
|
match (display, float, positioning) {
|
||||||
|
@ -1288,6 +1292,7 @@ impl<'ln> NodeUtils for ThreadSafeLayoutNode<'ln> {
|
||||||
None |
|
None |
|
||||||
Some(NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLImageElement))) => true,
|
Some(NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLImageElement))) => true,
|
||||||
Some(NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLObjectElement))) => self.has_object_data(),
|
Some(NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLObjectElement))) => self.has_object_data(),
|
||||||
|
Some(NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLCanvasElement))) => true,
|
||||||
Some(NodeTypeId::Element(_)) => false,
|
Some(NodeTypeId::Element(_)) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#![deny(unsafe_blocks)]
|
#![deny(unsafe_blocks)]
|
||||||
|
|
||||||
use block::BlockFlow;
|
use block::BlockFlow;
|
||||||
|
use canvas::canvas_paint_task::CanvasMsg::SendPixelContents;
|
||||||
use context::LayoutContext;
|
use context::LayoutContext;
|
||||||
use flow::{mod, Flow, IS_ABSOLUTELY_POSITIONED, NEEDS_LAYER};
|
use flow::{mod, Flow, IS_ABSOLUTELY_POSITIONED, NEEDS_LAYER};
|
||||||
use fragment::{CoordinateSystem, Fragment, IframeFragmentInfo, ImageFragmentInfo};
|
use fragment::{CoordinateSystem, Fragment, IframeFragmentInfo, ImageFragmentInfo};
|
||||||
|
@ -32,12 +33,14 @@ use gfx::display_list::TextOrientation;
|
||||||
use gfx::display_list::{SolidColorDisplayItem};
|
use gfx::display_list::{SolidColorDisplayItem};
|
||||||
use gfx::display_list::{StackingContext, TextDisplayItem};
|
use gfx::display_list::{StackingContext, TextDisplayItem};
|
||||||
use gfx::paint_task::PaintLayer;
|
use gfx::paint_task::PaintLayer;
|
||||||
|
use png;
|
||||||
|
use png::PixelsByColorType;
|
||||||
use servo_msg::compositor_msg::ScrollPolicy;
|
use servo_msg::compositor_msg::ScrollPolicy;
|
||||||
use servo_msg::constellation_msg::Msg as ConstellationMsg;
|
use servo_msg::constellation_msg::Msg as ConstellationMsg;
|
||||||
use servo_msg::constellation_msg::ConstellationChan;
|
use servo_msg::constellation_msg::ConstellationChan;
|
||||||
use servo_net::image::holder::ImageHolder;
|
use servo_net::image::holder::ImageHolder;
|
||||||
use servo_util::cursor::Cursor;
|
use servo_util::cursor::Cursor;
|
||||||
use servo_util::geometry::{mod, Au};
|
use servo_util::geometry::{mod, Au, to_px};
|
||||||
use servo_util::logical_geometry::{LogicalPoint, LogicalRect, LogicalSize};
|
use servo_util::logical_geometry::{LogicalPoint, LogicalRect, LogicalSize};
|
||||||
use servo_util::opts;
|
use servo_util::opts;
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
|
@ -862,6 +865,37 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
debug!("(building display list) no image :(");
|
debug!("(building display list) no image :(");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
SpecificFragmentInfo::Canvas(ref canvas_fragment_info) => {
|
||||||
|
let width = canvas_fragment_info.replaced_image_fragment_info
|
||||||
|
.computed_inline_size.map_or(0, |w| to_px(w) as uint);
|
||||||
|
let height = canvas_fragment_info.replaced_image_fragment_info
|
||||||
|
.computed_block_size.map_or(0, |h| to_px(h) as uint);
|
||||||
|
|
||||||
|
let (sender, receiver) = channel::<Arc<Vec<u8>>>();
|
||||||
|
let canvas_data = match canvas_fragment_info.renderer {
|
||||||
|
Some(ref renderer) => {
|
||||||
|
renderer.deref().lock().send(SendPixelContents(sender));
|
||||||
|
(*receiver.recv()).clone()
|
||||||
|
},
|
||||||
|
None => Vec::from_elem(width * height * 4, 0xFFu8)
|
||||||
|
};
|
||||||
|
|
||||||
|
let canvas_display_item = box ImageDisplayItem {
|
||||||
|
base: BaseDisplayItem::new(stacking_relative_content_box,
|
||||||
|
DisplayItemMetadata::new(self.node,
|
||||||
|
&*self.style,
|
||||||
|
Cursor::DefaultCursor),
|
||||||
|
(*clip).clone()),
|
||||||
|
image: Arc::new(box png::Image {
|
||||||
|
width: width as u32,
|
||||||
|
height: height as u32,
|
||||||
|
pixels: PixelsByColorType::RGBA8(canvas_data),
|
||||||
|
}),
|
||||||
|
stretch_size: stacking_relative_content_box.size,
|
||||||
|
};
|
||||||
|
|
||||||
|
display_list.content.push_back(DisplayItem::ImageClass(canvas_display_item));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#![deny(unsafe_blocks)]
|
#![deny(unsafe_blocks)]
|
||||||
|
|
||||||
|
use canvas::canvas_paint_task::CanvasMsg;
|
||||||
use css::node_style::StyledNode;
|
use css::node_style::StyledNode;
|
||||||
use construct::FlowConstructor;
|
use construct::FlowConstructor;
|
||||||
use context::LayoutContext;
|
use context::LayoutContext;
|
||||||
|
@ -128,6 +129,7 @@ pub enum SpecificFragmentInfo {
|
||||||
Generic,
|
Generic,
|
||||||
Iframe(Box<IframeFragmentInfo>),
|
Iframe(Box<IframeFragmentInfo>),
|
||||||
Image(Box<ImageFragmentInfo>),
|
Image(Box<ImageFragmentInfo>),
|
||||||
|
Canvas(Box<CanvasFragmentInfo>),
|
||||||
|
|
||||||
/// A hypothetical box (see CSS 2.1 § 10.3.7) for an absolutely-positioned block that was
|
/// A hypothetical box (see CSS 2.1 § 10.3.7) for an absolutely-positioned block that was
|
||||||
/// declared with `display: inline;`.
|
/// declared with `display: inline;`.
|
||||||
|
@ -156,6 +158,7 @@ impl SpecificFragmentInfo {
|
||||||
| SpecificFragmentInfo::TableRow
|
| SpecificFragmentInfo::TableRow
|
||||||
| SpecificFragmentInfo::TableWrapper
|
| SpecificFragmentInfo::TableWrapper
|
||||||
| SpecificFragmentInfo::UnscannedText(_)
|
| SpecificFragmentInfo::UnscannedText(_)
|
||||||
|
| SpecificFragmentInfo::Canvas(_)
|
||||||
| SpecificFragmentInfo::Generic => return RestyleDamage::empty(),
|
| SpecificFragmentInfo::Generic => return RestyleDamage::empty(),
|
||||||
SpecificFragmentInfo::InlineAbsoluteHypothetical(ref info) => &info.flow_ref,
|
SpecificFragmentInfo::InlineAbsoluteHypothetical(ref info) => &info.flow_ref,
|
||||||
SpecificFragmentInfo::InlineBlock(ref info) => &info.flow_ref,
|
SpecificFragmentInfo::InlineBlock(ref info) => &info.flow_ref,
|
||||||
|
@ -166,6 +169,7 @@ impl SpecificFragmentInfo {
|
||||||
|
|
||||||
pub fn get_type(&self) -> &'static str {
|
pub fn get_type(&self) -> &'static str {
|
||||||
match *self {
|
match *self {
|
||||||
|
SpecificFragmentInfo::Canvas(_) => "SpecificFragmentInfo::Canvas",
|
||||||
SpecificFragmentInfo::Generic => "SpecificFragmentInfo::Generic",
|
SpecificFragmentInfo::Generic => "SpecificFragmentInfo::Generic",
|
||||||
SpecificFragmentInfo::Iframe(_) => "SpecificFragmentInfo::Iframe",
|
SpecificFragmentInfo::Iframe(_) => "SpecificFragmentInfo::Iframe",
|
||||||
SpecificFragmentInfo::Image(_) => "SpecificFragmentInfo::Image",
|
SpecificFragmentInfo::Image(_) => "SpecificFragmentInfo::Image",
|
||||||
|
@ -217,17 +221,40 @@ impl InlineBlockFragmentInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deriving(Clone)]
|
||||||
|
pub struct CanvasFragmentInfo {
|
||||||
|
pub replaced_image_fragment_info: ReplacedImageFragmentInfo,
|
||||||
|
pub renderer: Option<Arc<Mutex<Sender<CanvasMsg>>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CanvasFragmentInfo {
|
||||||
|
pub fn new(node: &ThreadSafeLayoutNode) -> CanvasFragmentInfo {
|
||||||
|
CanvasFragmentInfo {
|
||||||
|
replaced_image_fragment_info: ReplacedImageFragmentInfo::new(node,
|
||||||
|
Some(Au::from_px(node.get_canvas_width() as int)),
|
||||||
|
Some(Au::from_px(node.get_canvas_height() as int))),
|
||||||
|
renderer: node.get_renderer().map(|rec| Arc::new(Mutex::new(rec))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the original inline-size of the canvas.
|
||||||
|
pub fn canvas_inline_size(&self) -> Au {
|
||||||
|
self.replaced_image_fragment_info.dom_inline_size.unwrap_or(Au(0))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the original block-size of the canvas.
|
||||||
|
pub fn canvas_block_size(&self) -> Au {
|
||||||
|
self.replaced_image_fragment_info.dom_block_size.unwrap_or(Au(0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// A fragment that represents a replaced content image and its accompanying borders, shadows, etc.
|
/// A fragment that represents a replaced content image and its accompanying borders, shadows, etc.
|
||||||
#[deriving(Clone)]
|
#[deriving(Clone)]
|
||||||
pub struct ImageFragmentInfo {
|
pub struct ImageFragmentInfo {
|
||||||
/// The image held within this fragment.
|
/// The image held within this fragment.
|
||||||
|
pub replaced_image_fragment_info: ReplacedImageFragmentInfo,
|
||||||
pub image: ImageHolder<UntrustedNodeAddress>,
|
pub image: ImageHolder<UntrustedNodeAddress>,
|
||||||
pub for_node: UntrustedNodeAddress,
|
|
||||||
pub computed_inline_size: Option<Au>,
|
|
||||||
pub computed_block_size: Option<Au>,
|
|
||||||
pub dom_inline_size: Option<Au>,
|
|
||||||
pub dom_block_size: Option<Au>,
|
|
||||||
pub writing_mode_is_vertical: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImageFragmentInfo {
|
impl ImageFragmentInfo {
|
||||||
|
@ -247,15 +274,60 @@ impl ImageFragmentInfo {
|
||||||
}).and_then(|pixels| Some(Au::from_px(pixels)))
|
}).and_then(|pixels| Some(Au::from_px(pixels)))
|
||||||
}
|
}
|
||||||
|
|
||||||
let is_vertical = node.style().writing_mode.is_vertical();
|
ImageFragmentInfo {
|
||||||
let dom_width = convert_length(node, &atom!("width"));
|
replaced_image_fragment_info: ReplacedImageFragmentInfo::new(node,
|
||||||
let dom_height = convert_length(node, &atom!("height"));
|
convert_length(node, &atom!("width")),
|
||||||
|
convert_length(node, &atom!("height"))),
|
||||||
|
image: ImageHolder::new(image_url, local_image_cache)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the original inline-size of the image.
|
||||||
|
pub fn image_inline_size(&mut self) -> Au {
|
||||||
|
let size = self.image.get_size(self.replaced_image_fragment_info.for_node).unwrap_or(Size2D::zero());
|
||||||
|
Au::from_px(if self.replaced_image_fragment_info.writing_mode_is_vertical { size.height }
|
||||||
|
else { size.width })
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the original block-size of the image.
|
||||||
|
pub fn image_block_size(&mut self) -> Au {
|
||||||
|
let size = self.image.get_size(self.replaced_image_fragment_info.for_node).unwrap_or(Size2D::zero());
|
||||||
|
Au::from_px(if self.replaced_image_fragment_info.writing_mode_is_vertical { size.width }
|
||||||
|
else { size.height })
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Tile an image
|
||||||
|
pub fn tile_image(position: &mut Au, size: &mut Au,
|
||||||
|
virtual_position: Au, image_size: u32) {
|
||||||
|
let image_size = image_size as int;
|
||||||
|
let delta_pixels = geometry::to_px(virtual_position - *position);
|
||||||
|
let tile_count = (delta_pixels + image_size - 1) / image_size;
|
||||||
|
let offset = Au::from_px(image_size * tile_count);
|
||||||
|
let new_position = virtual_position - offset;
|
||||||
|
*size = *position - new_position + *size;
|
||||||
|
*position = new_position;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[deriving(Clone)]
|
||||||
|
pub struct ReplacedImageFragmentInfo {
|
||||||
|
pub for_node: UntrustedNodeAddress,
|
||||||
|
pub computed_inline_size: Option<Au>,
|
||||||
|
pub computed_block_size: Option<Au>,
|
||||||
|
pub dom_inline_size: Option<Au>,
|
||||||
|
pub dom_block_size: Option<Au>,
|
||||||
|
pub writing_mode_is_vertical: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ReplacedImageFragmentInfo {
|
||||||
|
pub fn new(node: &ThreadSafeLayoutNode,
|
||||||
|
dom_width: Option<Au>,
|
||||||
|
dom_height: Option<Au>) -> ReplacedImageFragmentInfo {
|
||||||
|
let is_vertical = node.style().writing_mode.is_vertical();
|
||||||
let opaque_node: OpaqueNode = OpaqueNodeMethods::from_thread_safe_layout_node(node);
|
let opaque_node: OpaqueNode = OpaqueNodeMethods::from_thread_safe_layout_node(node);
|
||||||
let untrusted_node: UntrustedNodeAddress = opaque_node.to_untrusted_node_address();
|
let untrusted_node: UntrustedNodeAddress = opaque_node.to_untrusted_node_address();
|
||||||
|
|
||||||
ImageFragmentInfo {
|
ReplacedImageFragmentInfo {
|
||||||
image: ImageHolder::new(image_url, local_image_cache),
|
|
||||||
for_node: untrusted_node,
|
for_node: untrusted_node,
|
||||||
computed_inline_size: None,
|
computed_inline_size: None,
|
||||||
computed_block_size: None,
|
computed_block_size: None,
|
||||||
|
@ -275,18 +347,6 @@ impl ImageFragmentInfo {
|
||||||
self.computed_block_size.expect("image block_size is not computed yet!")
|
self.computed_block_size.expect("image block_size is not computed yet!")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the original inline-size of the image.
|
|
||||||
pub fn image_inline_size(&mut self) -> Au {
|
|
||||||
let size = self.image.get_size(self.for_node).unwrap_or(Size2D::zero());
|
|
||||||
Au::from_px(if self.writing_mode_is_vertical { size.height } else { size.width })
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the original block-size of the image.
|
|
||||||
pub fn image_block_size(&mut self) -> Au {
|
|
||||||
let size = self.image.get_size(self.for_node).unwrap_or(Size2D::zero());
|
|
||||||
Au::from_px(if self.writing_mode_is_vertical { size.width } else { size.height })
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return used value for inline-size or block-size.
|
// Return used value for inline-size or block-size.
|
||||||
//
|
//
|
||||||
// `dom_length`: inline-size or block-size as specified in the `img` tag.
|
// `dom_length`: inline-size or block-size as specified in the `img` tag.
|
||||||
|
@ -319,16 +379,101 @@ impl ImageFragmentInfo {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tile an image
|
pub fn calculate_replaced_inline_size(&mut self,
|
||||||
pub fn tile_image(position: &mut Au, size: &mut Au,
|
style: ComputedValues,
|
||||||
virtual_position: Au, image_size: u32) {
|
noncontent_inline_size: Au,
|
||||||
let image_size = image_size as int;
|
container_inline_size: Au,
|
||||||
let delta_pixels = geometry::to_px(virtual_position - *position);
|
fragment_inline_size: Au,
|
||||||
let tile_count = (delta_pixels + image_size - 1) / image_size;
|
fragment_block_size: Au) -> Au {
|
||||||
let offset = Au::from_px(image_size * tile_count);
|
|
||||||
let new_position = virtual_position - offset;
|
let style_inline_size = style.content_inline_size();
|
||||||
*size = *position - new_position + *size;
|
let style_block_size = style.content_block_size();
|
||||||
*position = new_position;
|
let style_min_inline_size = style.min_inline_size();
|
||||||
|
let style_max_inline_size = style.max_inline_size();
|
||||||
|
let style_min_block_size = style.min_block_size();
|
||||||
|
let style_max_block_size = style.max_block_size();
|
||||||
|
|
||||||
|
// TODO(ksh8281): compute border,margin
|
||||||
|
let inline_size = ReplacedImageFragmentInfo::style_length(
|
||||||
|
style_inline_size,
|
||||||
|
self.dom_inline_size,
|
||||||
|
container_inline_size);
|
||||||
|
|
||||||
|
let inline_size = match inline_size {
|
||||||
|
MaybeAuto::Auto => {
|
||||||
|
let intrinsic_width = fragment_inline_size;
|
||||||
|
let intrinsic_height = fragment_block_size;
|
||||||
|
if intrinsic_height == Au(0) {
|
||||||
|
intrinsic_width
|
||||||
|
} else {
|
||||||
|
let ratio = intrinsic_width.to_f32().unwrap() /
|
||||||
|
intrinsic_height.to_f32().unwrap();
|
||||||
|
|
||||||
|
let specified_height = ReplacedImageFragmentInfo::style_length(
|
||||||
|
style_block_size,
|
||||||
|
self.dom_block_size,
|
||||||
|
Au(0));
|
||||||
|
let specified_height = match specified_height {
|
||||||
|
MaybeAuto::Auto => intrinsic_height,
|
||||||
|
MaybeAuto::Specified(h) => h,
|
||||||
|
};
|
||||||
|
let specified_height = ReplacedImageFragmentInfo::clamp_size(
|
||||||
|
specified_height,
|
||||||
|
style_min_block_size,
|
||||||
|
style_max_block_size,
|
||||||
|
Au(0));
|
||||||
|
Au((specified_height.to_f32().unwrap() * ratio) as i32)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
MaybeAuto::Specified(w) => w,
|
||||||
|
};
|
||||||
|
|
||||||
|
let inline_size = ReplacedImageFragmentInfo::clamp_size(inline_size,
|
||||||
|
style_min_inline_size,
|
||||||
|
style_max_inline_size,
|
||||||
|
container_inline_size);
|
||||||
|
|
||||||
|
self.computed_inline_size = Some(inline_size);
|
||||||
|
inline_size + noncontent_inline_size
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn calculate_replaced_block_size(&mut self,
|
||||||
|
style: ComputedValues,
|
||||||
|
noncontent_block_size: Au,
|
||||||
|
containing_block_block_size: Au,
|
||||||
|
fragment_inline_size: Au,
|
||||||
|
fragment_block_size: Au) -> Au {
|
||||||
|
|
||||||
|
// TODO(ksh8281): compute border,margin,padding
|
||||||
|
let style_block_size = style.content_block_size();
|
||||||
|
let style_min_block_size = style.min_block_size();
|
||||||
|
let style_max_block_size = style.max_block_size();
|
||||||
|
|
||||||
|
let inline_size = self.computed_inline_size();
|
||||||
|
let block_size = ReplacedImageFragmentInfo::style_length(
|
||||||
|
style_block_size,
|
||||||
|
self.dom_block_size,
|
||||||
|
containing_block_block_size);
|
||||||
|
|
||||||
|
let block_size = match block_size {
|
||||||
|
MaybeAuto::Auto => {
|
||||||
|
let intrinsic_width = fragment_inline_size;
|
||||||
|
let intrinsic_height = fragment_block_size;
|
||||||
|
let scale = intrinsic_width.to_f32().unwrap() / inline_size.to_f32().unwrap();
|
||||||
|
Au((intrinsic_height.to_f32().unwrap() / scale) as i32)
|
||||||
|
},
|
||||||
|
MaybeAuto::Specified(h) => {
|
||||||
|
h
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let block_size = ReplacedImageFragmentInfo::clamp_size(block_size,
|
||||||
|
style_min_block_size,
|
||||||
|
style_max_block_size,
|
||||||
|
Au(0));
|
||||||
|
|
||||||
|
self.computed_block_size = Some(block_size);
|
||||||
|
block_size + noncontent_block_size
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -667,6 +812,7 @@ impl Fragment {
|
||||||
fn quantities_included_in_intrinsic_inline_size(&self)
|
fn quantities_included_in_intrinsic_inline_size(&self)
|
||||||
-> QuantitiesIncludedInIntrinsicInlineSizes {
|
-> QuantitiesIncludedInIntrinsicInlineSizes {
|
||||||
match self.specific {
|
match self.specific {
|
||||||
|
SpecificFragmentInfo::Canvas(_) |
|
||||||
SpecificFragmentInfo::Generic |
|
SpecificFragmentInfo::Generic |
|
||||||
SpecificFragmentInfo::Iframe(_) |
|
SpecificFragmentInfo::Iframe(_) |
|
||||||
SpecificFragmentInfo::Image(_) |
|
SpecificFragmentInfo::Image(_) |
|
||||||
|
@ -1000,6 +1146,13 @@ impl Fragment {
|
||||||
preferred_inline_size: image_inline_size,
|
preferred_inline_size: image_inline_size,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
SpecificFragmentInfo::Canvas(ref mut canvas_fragment_info) => {
|
||||||
|
let canvas_inline_size = canvas_fragment_info.canvas_inline_size();
|
||||||
|
result.union_block(&IntrinsicISizes {
|
||||||
|
minimum_inline_size: canvas_inline_size,
|
||||||
|
preferred_inline_size: canvas_inline_size,
|
||||||
|
})
|
||||||
|
}
|
||||||
SpecificFragmentInfo::ScannedText(ref text_fragment_info) => {
|
SpecificFragmentInfo::ScannedText(ref text_fragment_info) => {
|
||||||
let range = &text_fragment_info.range;
|
let range = &text_fragment_info.range;
|
||||||
let min_line_inline_size = text_fragment_info.run.min_width_for_range(range);
|
let min_line_inline_size = text_fragment_info.run.min_width_for_range(range);
|
||||||
|
@ -1046,8 +1199,11 @@ impl Fragment {
|
||||||
SpecificFragmentInfo::Generic | SpecificFragmentInfo::Iframe(_) | SpecificFragmentInfo::Table | SpecificFragmentInfo::TableCell |
|
SpecificFragmentInfo::Generic | SpecificFragmentInfo::Iframe(_) | SpecificFragmentInfo::Table | SpecificFragmentInfo::TableCell |
|
||||||
SpecificFragmentInfo::TableRow | SpecificFragmentInfo::TableWrapper | SpecificFragmentInfo::InlineBlock(_) |
|
SpecificFragmentInfo::TableRow | SpecificFragmentInfo::TableWrapper | SpecificFragmentInfo::InlineBlock(_) |
|
||||||
SpecificFragmentInfo::InlineAbsoluteHypothetical(_) => Au(0),
|
SpecificFragmentInfo::InlineAbsoluteHypothetical(_) => Au(0),
|
||||||
|
SpecificFragmentInfo::Canvas(ref canvas_fragment_info) => {
|
||||||
|
canvas_fragment_info.replaced_image_fragment_info.computed_inline_size()
|
||||||
|
}
|
||||||
SpecificFragmentInfo::Image(ref image_fragment_info) => {
|
SpecificFragmentInfo::Image(ref image_fragment_info) => {
|
||||||
image_fragment_info.computed_inline_size()
|
image_fragment_info.replaced_image_fragment_info.computed_inline_size()
|
||||||
}
|
}
|
||||||
SpecificFragmentInfo::ScannedText(ref text_fragment_info) => {
|
SpecificFragmentInfo::ScannedText(ref text_fragment_info) => {
|
||||||
let (range, run) = (&text_fragment_info.range, &text_fragment_info.run);
|
let (range, run) = (&text_fragment_info.range, &text_fragment_info.run);
|
||||||
|
@ -1066,7 +1222,10 @@ impl Fragment {
|
||||||
SpecificFragmentInfo::TableRow | SpecificFragmentInfo::TableWrapper | SpecificFragmentInfo::InlineBlock(_) |
|
SpecificFragmentInfo::TableRow | SpecificFragmentInfo::TableWrapper | SpecificFragmentInfo::InlineBlock(_) |
|
||||||
SpecificFragmentInfo::InlineAbsoluteHypothetical(_) => Au(0),
|
SpecificFragmentInfo::InlineAbsoluteHypothetical(_) => Au(0),
|
||||||
SpecificFragmentInfo::Image(ref image_fragment_info) => {
|
SpecificFragmentInfo::Image(ref image_fragment_info) => {
|
||||||
image_fragment_info.computed_block_size()
|
image_fragment_info.replaced_image_fragment_info.computed_block_size()
|
||||||
|
}
|
||||||
|
SpecificFragmentInfo::Canvas(ref canvas_fragment_info) => {
|
||||||
|
canvas_fragment_info.replaced_image_fragment_info.computed_block_size()
|
||||||
}
|
}
|
||||||
SpecificFragmentInfo::ScannedText(_) => {
|
SpecificFragmentInfo::ScannedText(_) => {
|
||||||
// Compute the block-size based on the line-block-size and font size.
|
// Compute the block-size based on the line-block-size and font size.
|
||||||
|
@ -1097,7 +1256,7 @@ impl Fragment {
|
||||||
pub fn find_split_info_by_new_line(&self)
|
pub fn find_split_info_by_new_line(&self)
|
||||||
-> Option<(SplitInfo, Option<SplitInfo>, Arc<Box<TextRun>> /* TODO(bjz): remove */)> {
|
-> Option<(SplitInfo, Option<SplitInfo>, Arc<Box<TextRun>> /* TODO(bjz): remove */)> {
|
||||||
match self.specific {
|
match self.specific {
|
||||||
SpecificFragmentInfo::Generic | SpecificFragmentInfo::Iframe(_) | SpecificFragmentInfo::Image(_) | SpecificFragmentInfo::Table | SpecificFragmentInfo::TableCell |
|
SpecificFragmentInfo::Canvas(_) | SpecificFragmentInfo::Generic | SpecificFragmentInfo::Iframe(_) | SpecificFragmentInfo::Image(_) | SpecificFragmentInfo::Table | SpecificFragmentInfo::TableCell |
|
||||||
SpecificFragmentInfo::TableRow | SpecificFragmentInfo::TableWrapper => None,
|
SpecificFragmentInfo::TableRow | SpecificFragmentInfo::TableWrapper => None,
|
||||||
SpecificFragmentInfo::TableColumn(_) => panic!("Table column fragments do not need to split"),
|
SpecificFragmentInfo::TableColumn(_) => panic!("Table column fragments do not need to split"),
|
||||||
SpecificFragmentInfo::UnscannedText(_) => panic!("Unscanned text fragments should have been scanned by now!"),
|
SpecificFragmentInfo::UnscannedText(_) => panic!("Unscanned text fragments should have been scanned by now!"),
|
||||||
|
@ -1300,7 +1459,7 @@ impl Fragment {
|
||||||
|
|
||||||
/// Assigns replaced inline-size, padding, and margins for this fragment only if it is replaced
|
/// Assigns replaced inline-size, padding, and margins for this fragment only if it is replaced
|
||||||
/// content per CSS 2.1 § 10.3.2.
|
/// content per CSS 2.1 § 10.3.2.
|
||||||
pub fn assign_replaced_inline_size_if_necessary(&mut self, container_inline_size: Au) {
|
pub fn assign_replaced_inline_size_if_necessary<'a>(&'a mut self, container_inline_size: Au) {
|
||||||
match self.specific {
|
match self.specific {
|
||||||
SpecificFragmentInfo::Generic | SpecificFragmentInfo::Iframe(_) | SpecificFragmentInfo::Table | SpecificFragmentInfo::TableCell |
|
SpecificFragmentInfo::Generic | SpecificFragmentInfo::Iframe(_) | SpecificFragmentInfo::Table | SpecificFragmentInfo::TableCell |
|
||||||
SpecificFragmentInfo::TableRow | SpecificFragmentInfo::TableWrapper => return,
|
SpecificFragmentInfo::TableRow | SpecificFragmentInfo::TableWrapper => return,
|
||||||
|
@ -1308,16 +1467,11 @@ impl Fragment {
|
||||||
SpecificFragmentInfo::UnscannedText(_) => {
|
SpecificFragmentInfo::UnscannedText(_) => {
|
||||||
panic!("Unscanned text fragments should have been scanned by now!")
|
panic!("Unscanned text fragments should have been scanned by now!")
|
||||||
}
|
}
|
||||||
SpecificFragmentInfo::Image(_) | SpecificFragmentInfo::ScannedText(_) | SpecificFragmentInfo::InlineBlock(_) |
|
SpecificFragmentInfo::Canvas(_) | SpecificFragmentInfo::Image(_) | SpecificFragmentInfo::ScannedText(_) | SpecificFragmentInfo::InlineBlock(_) |
|
||||||
SpecificFragmentInfo::InlineAbsoluteHypothetical(_) => {}
|
SpecificFragmentInfo::InlineAbsoluteHypothetical(_) => {}
|
||||||
};
|
};
|
||||||
|
|
||||||
let style_inline_size = self.style().content_inline_size();
|
let style = self.style().clone();
|
||||||
let style_block_size = self.style().content_block_size();
|
|
||||||
let style_min_inline_size = self.style().min_inline_size();
|
|
||||||
let style_max_inline_size = self.style().max_inline_size();
|
|
||||||
let style_min_block_size = self.style().min_block_size();
|
|
||||||
let style_max_block_size = self.style().max_block_size();
|
|
||||||
let noncontent_inline_size = self.border_padding.inline_start_end();
|
let noncontent_inline_size = self.border_padding.inline_start_end();
|
||||||
|
|
||||||
match self.specific {
|
match self.specific {
|
||||||
|
@ -1341,49 +1495,24 @@ impl Fragment {
|
||||||
self.border_box.size.inline = info.content_size.inline + noncontent_inline_size
|
self.border_box.size.inline = info.content_size.inline + noncontent_inline_size
|
||||||
}
|
}
|
||||||
SpecificFragmentInfo::Image(ref mut image_fragment_info) => {
|
SpecificFragmentInfo::Image(ref mut image_fragment_info) => {
|
||||||
// TODO(ksh8281): compute border,margin
|
let fragment_inline_size = image_fragment_info.image_inline_size();
|
||||||
let inline_size = ImageFragmentInfo::style_length(
|
let fragment_block_size = image_fragment_info.image_block_size();
|
||||||
style_inline_size,
|
self.border_box.size.inline = image_fragment_info.replaced_image_fragment_info.
|
||||||
image_fragment_info.dom_inline_size,
|
calculate_replaced_inline_size(style,
|
||||||
container_inline_size);
|
noncontent_inline_size,
|
||||||
|
container_inline_size,
|
||||||
let inline_size = match inline_size {
|
fragment_inline_size,
|
||||||
MaybeAuto::Auto => {
|
fragment_block_size);
|
||||||
let intrinsic_width = image_fragment_info.image_inline_size();
|
}
|
||||||
let intrinsic_height = image_fragment_info.image_block_size();
|
SpecificFragmentInfo::Canvas(ref mut canvas_fragment_info) => {
|
||||||
|
let fragment_inline_size = canvas_fragment_info.canvas_inline_size();
|
||||||
if intrinsic_height == Au(0) {
|
let fragment_block_size = canvas_fragment_info.canvas_block_size();
|
||||||
intrinsic_width
|
self.border_box.size.inline = canvas_fragment_info.replaced_image_fragment_info.
|
||||||
} else {
|
calculate_replaced_inline_size(style,
|
||||||
let ratio = intrinsic_width.to_f32().unwrap() /
|
noncontent_inline_size,
|
||||||
intrinsic_height.to_f32().unwrap();
|
container_inline_size,
|
||||||
|
fragment_inline_size,
|
||||||
let specified_height = ImageFragmentInfo::style_length(
|
fragment_block_size);
|
||||||
style_block_size,
|
|
||||||
image_fragment_info.dom_block_size,
|
|
||||||
Au(0));
|
|
||||||
let specified_height = match specified_height {
|
|
||||||
MaybeAuto::Auto => intrinsic_height,
|
|
||||||
MaybeAuto::Specified(h) => h,
|
|
||||||
};
|
|
||||||
let specified_height = ImageFragmentInfo::clamp_size(
|
|
||||||
specified_height,
|
|
||||||
style_min_block_size,
|
|
||||||
style_max_block_size,
|
|
||||||
Au(0));
|
|
||||||
Au((specified_height.to_f32().unwrap() * ratio) as i32)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
MaybeAuto::Specified(w) => w,
|
|
||||||
};
|
|
||||||
|
|
||||||
let inline_size = ImageFragmentInfo::clamp_size(inline_size,
|
|
||||||
style_min_inline_size,
|
|
||||||
style_max_inline_size,
|
|
||||||
container_inline_size);
|
|
||||||
|
|
||||||
self.border_box.size.inline = inline_size + noncontent_inline_size;
|
|
||||||
image_fragment_info.computed_inline_size = Some(inline_size);
|
|
||||||
}
|
}
|
||||||
_ => panic!("this case should have been handled above"),
|
_ => panic!("this case should have been handled above"),
|
||||||
}
|
}
|
||||||
|
@ -1401,42 +1530,33 @@ impl Fragment {
|
||||||
SpecificFragmentInfo::UnscannedText(_) => {
|
SpecificFragmentInfo::UnscannedText(_) => {
|
||||||
panic!("Unscanned text fragments should have been scanned by now!")
|
panic!("Unscanned text fragments should have been scanned by now!")
|
||||||
}
|
}
|
||||||
SpecificFragmentInfo::Image(_) | SpecificFragmentInfo::ScannedText(_) | SpecificFragmentInfo::InlineBlock(_) |
|
SpecificFragmentInfo::Canvas(_) | SpecificFragmentInfo::Image(_) | SpecificFragmentInfo::ScannedText(_) | SpecificFragmentInfo::InlineBlock(_) |
|
||||||
SpecificFragmentInfo::InlineAbsoluteHypothetical(_) => {}
|
SpecificFragmentInfo::InlineAbsoluteHypothetical(_) => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
let style_block_size = self.style().content_block_size();
|
let style = self.style().clone();
|
||||||
let style_min_block_size = self.style().min_block_size();
|
|
||||||
let style_max_block_size = self.style().max_block_size();
|
|
||||||
let noncontent_block_size = self.border_padding.block_start_end();
|
let noncontent_block_size = self.border_padding.block_start_end();
|
||||||
|
|
||||||
match self.specific {
|
match self.specific {
|
||||||
SpecificFragmentInfo::Image(ref mut image_fragment_info) => {
|
SpecificFragmentInfo::Image(ref mut image_fragment_info) => {
|
||||||
// TODO(ksh8281): compute border,margin,padding
|
let fragment_inline_size = image_fragment_info.image_inline_size();
|
||||||
let inline_size = image_fragment_info.computed_inline_size();
|
let fragment_block_size = image_fragment_info.image_block_size();
|
||||||
let block_size = ImageFragmentInfo::style_length(
|
self.border_box.size.block = image_fragment_info.replaced_image_fragment_info.
|
||||||
style_block_size,
|
calculate_replaced_block_size(style,
|
||||||
image_fragment_info.dom_block_size,
|
noncontent_block_size,
|
||||||
containing_block_block_size);
|
containing_block_block_size,
|
||||||
|
fragment_inline_size,
|
||||||
let block_size = match block_size {
|
fragment_block_size);
|
||||||
MaybeAuto::Auto => {
|
}
|
||||||
let scale = image_fragment_info.image_inline_size().to_f32().unwrap()
|
SpecificFragmentInfo::Canvas(ref mut canvas_fragment_info) => {
|
||||||
/ inline_size.to_f32().unwrap();
|
let fragment_inline_size = canvas_fragment_info.canvas_inline_size();
|
||||||
Au((image_fragment_info.image_block_size().to_f32().unwrap() / scale)
|
let fragment_block_size = canvas_fragment_info.canvas_block_size();
|
||||||
as i32)
|
self.border_box.size.block = canvas_fragment_info.replaced_image_fragment_info.
|
||||||
},
|
calculate_replaced_block_size(style,
|
||||||
MaybeAuto::Specified(h) => {
|
noncontent_block_size,
|
||||||
h
|
containing_block_block_size,
|
||||||
}
|
fragment_inline_size,
|
||||||
};
|
fragment_block_size);
|
||||||
|
|
||||||
let block_size = ImageFragmentInfo::clamp_size(block_size, style_min_block_size,
|
|
||||||
style_max_block_size,
|
|
||||||
Au(0));
|
|
||||||
|
|
||||||
image_fragment_info.computed_block_size = Some(block_size);
|
|
||||||
self.border_box.size.block = block_size + noncontent_block_size
|
|
||||||
}
|
}
|
||||||
SpecificFragmentInfo::ScannedText(ref info) => {
|
SpecificFragmentInfo::ScannedText(ref info) => {
|
||||||
// Scanned text fragments' content block-sizes are calculated by the text run
|
// Scanned text fragments' content block-sizes are calculated by the text run
|
||||||
|
@ -1463,7 +1583,7 @@ impl Fragment {
|
||||||
pub fn inline_metrics(&self, layout_context: &LayoutContext) -> InlineMetrics {
|
pub fn inline_metrics(&self, layout_context: &LayoutContext) -> InlineMetrics {
|
||||||
match self.specific {
|
match self.specific {
|
||||||
SpecificFragmentInfo::Image(ref image_fragment_info) => {
|
SpecificFragmentInfo::Image(ref image_fragment_info) => {
|
||||||
let computed_block_size = image_fragment_info.computed_block_size();
|
let computed_block_size = image_fragment_info.replaced_image_fragment_info.computed_block_size();
|
||||||
InlineMetrics {
|
InlineMetrics {
|
||||||
block_size_above_baseline: computed_block_size + self.border_padding.block_start_end(),
|
block_size_above_baseline: computed_block_size + self.border_padding.block_start_end(),
|
||||||
depth_below_baseline: Au(0),
|
depth_below_baseline: Au(0),
|
||||||
|
@ -1538,6 +1658,7 @@ impl Fragment {
|
||||||
SpecificFragmentInfo::InlineBlock(_) |
|
SpecificFragmentInfo::InlineBlock(_) |
|
||||||
SpecificFragmentInfo::InlineAbsoluteHypothetical(_) |
|
SpecificFragmentInfo::InlineAbsoluteHypothetical(_) |
|
||||||
SpecificFragmentInfo::TableWrapper => false,
|
SpecificFragmentInfo::TableWrapper => false,
|
||||||
|
SpecificFragmentInfo::Canvas(_) |
|
||||||
SpecificFragmentInfo::Generic |
|
SpecificFragmentInfo::Generic |
|
||||||
SpecificFragmentInfo::Iframe(_) |
|
SpecificFragmentInfo::Iframe(_) |
|
||||||
SpecificFragmentInfo::Image(_) |
|
SpecificFragmentInfo::Image(_) |
|
||||||
|
|
|
@ -13,12 +13,14 @@
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
|
||||||
extern crate cssparser;
|
extern crate cssparser;
|
||||||
|
extern crate canvas;
|
||||||
extern crate geom;
|
extern crate geom;
|
||||||
extern crate gfx;
|
extern crate gfx;
|
||||||
extern crate layout_traits;
|
extern crate layout_traits;
|
||||||
extern crate script;
|
extern crate script;
|
||||||
extern crate script_traits;
|
extern crate script_traits;
|
||||||
extern crate serialize;
|
extern crate serialize;
|
||||||
|
extern crate png;
|
||||||
extern crate style;
|
extern crate style;
|
||||||
#[phase(plugin)]
|
#[phase(plugin)]
|
||||||
extern crate "plugins" as servo_plugins;
|
extern crate "plugins" as servo_plugins;
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
//! o Instead of `html_element_in_html_document()`, use
|
//! o Instead of `html_element_in_html_document()`, use
|
||||||
//! `html_element_in_html_document_for_layout()`.
|
//! `html_element_in_html_document_for_layout()`.
|
||||||
|
|
||||||
|
use canvas::canvas_paint_task::CanvasMsg;
|
||||||
use context::SharedLayoutContext;
|
use context::SharedLayoutContext;
|
||||||
use css::node_style::StyledNode;
|
use css::node_style::StyledNode;
|
||||||
use incremental::RestyleDamage;
|
use incremental::RestyleDamage;
|
||||||
|
@ -39,12 +40,13 @@ use util::{PrivateLayoutData};
|
||||||
use cssparser::RGBA;
|
use cssparser::RGBA;
|
||||||
use gfx::display_list::OpaqueNode;
|
use gfx::display_list::OpaqueNode;
|
||||||
use script::dom::bindings::codegen::InheritTypes::{ElementCast, HTMLIFrameElementCast};
|
use script::dom::bindings::codegen::InheritTypes::{ElementCast, HTMLIFrameElementCast};
|
||||||
use script::dom::bindings::codegen::InheritTypes::{HTMLImageElementCast, HTMLInputElementCast};
|
use script::dom::bindings::codegen::InheritTypes::{HTMLCanvasElementCast, HTMLImageElementCast, HTMLInputElementCast};
|
||||||
use script::dom::bindings::codegen::InheritTypes::{HTMLTextAreaElementCast, NodeCast, TextCast};
|
use script::dom::bindings::codegen::InheritTypes::{HTMLTextAreaElementCast, NodeCast, TextCast};
|
||||||
use script::dom::bindings::js::JS;
|
use script::dom::bindings::js::JS;
|
||||||
use script::dom::element::{Element, ElementTypeId};
|
use script::dom::element::{Element, ElementTypeId};
|
||||||
use script::dom::element::{LayoutElementHelpers, RawLayoutElementHelpers};
|
use script::dom::element::{LayoutElementHelpers, RawLayoutElementHelpers};
|
||||||
use script::dom::htmlelement::HTMLElementTypeId;
|
use script::dom::htmlelement::HTMLElementTypeId;
|
||||||
|
use script::dom::htmlcanvaselement::{HTMLCanvasElement, LayoutHTMLCanvasElementHelpers};
|
||||||
use script::dom::htmliframeelement::HTMLIFrameElement;
|
use script::dom::htmliframeelement::HTMLIFrameElement;
|
||||||
use script::dom::htmlimageelement::LayoutHTMLImageElementHelpers;
|
use script::dom::htmlimageelement::LayoutHTMLImageElementHelpers;
|
||||||
use script::dom::htmlinputelement::LayoutHTMLInputElementHelpers;
|
use script::dom::htmlinputelement::LayoutHTMLInputElementHelpers;
|
||||||
|
@ -112,6 +114,27 @@ pub trait TLayoutNode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_renderer(&self) -> Option<Sender<CanvasMsg>> {
|
||||||
|
unsafe {
|
||||||
|
let canvas_element: Option<JS<HTMLCanvasElement>> = HTMLCanvasElementCast::to_js(self.get_jsmanaged());
|
||||||
|
canvas_element.and_then(|elem| elem.get_renderer())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_canvas_width(&self) -> u32 {
|
||||||
|
unsafe {
|
||||||
|
let canvas_element: Option<JS<HTMLCanvasElement>> = HTMLCanvasElementCast::to_js(self.get_jsmanaged());
|
||||||
|
canvas_element.unwrap().get_canvas_width()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_canvas_height(&self) -> u32 {
|
||||||
|
unsafe {
|
||||||
|
let canvas_element: Option<JS<HTMLCanvasElement>> = HTMLCanvasElementCast::to_js(self.get_jsmanaged());
|
||||||
|
canvas_element.unwrap().get_canvas_height()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// If this node is an iframe element, returns its pipeline and subpage IDs. If this node is
|
/// If this node is an iframe element, returns its pipeline and subpage IDs. If this node is
|
||||||
/// not an iframe element, fails.
|
/// not an iframe element, fails.
|
||||||
fn iframe_pipeline_and_subpage_ids(&self) -> (PipelineId, SubpageId) {
|
fn iframe_pipeline_and_subpage_ids(&self) -> (PipelineId, SubpageId) {
|
||||||
|
|
|
@ -44,6 +44,16 @@ impl CanvasRenderingContext2D {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait LayoutCanvasRenderingContext2DHelpers {
|
||||||
|
unsafe fn get_renderer(&self) -> Sender<CanvasMsg>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LayoutCanvasRenderingContext2DHelpers for JS<CanvasRenderingContext2D> {
|
||||||
|
unsafe fn get_renderer(&self) -> Sender<CanvasMsg> {
|
||||||
|
(*self.unsafe_get()).renderer.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> {
|
impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> {
|
||||||
fn Canvas(self) -> Temporary<HTMLCanvasElement> {
|
fn Canvas(self) -> Temporary<HTMLCanvasElement> {
|
||||||
Temporary::new(self.canvas)
|
Temporary::new(self.canvas)
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use canvas::canvas_paint_task::CanvasMsg;
|
||||||
use dom::attr::Attr;
|
use dom::attr::Attr;
|
||||||
use dom::attr::AttrHelpers;
|
use dom::attr::AttrHelpers;
|
||||||
use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding;
|
use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding;
|
||||||
|
@ -9,8 +10,8 @@ use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding::HTMLCanvasElemen
|
||||||
use dom::bindings::codegen::InheritTypes::HTMLCanvasElementDerived;
|
use dom::bindings::codegen::InheritTypes::HTMLCanvasElementDerived;
|
||||||
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast};
|
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast};
|
||||||
use dom::bindings::global::GlobalRef;
|
use dom::bindings::global::GlobalRef;
|
||||||
use dom::bindings::js::{MutNullableJS, JSRef, Temporary};
|
use dom::bindings::js::{MutNullableJS, JS, JSRef, Temporary};
|
||||||
use dom::canvasrenderingcontext2d::CanvasRenderingContext2D;
|
use dom::canvasrenderingcontext2d::{CanvasRenderingContext2D, LayoutCanvasRenderingContext2DHelpers};
|
||||||
use dom::document::Document;
|
use dom::document::Document;
|
||||||
use dom::element::{Element, AttributeHandlers};
|
use dom::element::{Element, AttributeHandlers};
|
||||||
use dom::eventtarget::{EventTarget, EventTargetTypeId};
|
use dom::eventtarget::{EventTarget, EventTargetTypeId};
|
||||||
|
@ -60,6 +61,27 @@ impl HTMLCanvasElement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait LayoutHTMLCanvasElementHelpers {
|
||||||
|
unsafe fn get_renderer(&self) -> Option<Sender<CanvasMsg>>;
|
||||||
|
unsafe fn get_canvas_width(&self) -> u32;
|
||||||
|
unsafe fn get_canvas_height(&self) -> u32;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LayoutHTMLCanvasElementHelpers for JS<HTMLCanvasElement> {
|
||||||
|
unsafe fn get_renderer(&self) -> Option<Sender<CanvasMsg>> {
|
||||||
|
let context = (*self.unsafe_get()).context.get_inner();
|
||||||
|
context.map(|cx| cx.get_renderer())
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn get_canvas_width(&self) -> u32 {
|
||||||
|
(*self.unsafe_get()).width.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn get_canvas_height(&self) -> u32 {
|
||||||
|
(*self.unsafe_get()).height.get()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> HTMLCanvasElementMethods for JSRef<'a, HTMLCanvasElement> {
|
impl<'a> HTMLCanvasElementMethods for JSRef<'a, HTMLCanvasElement> {
|
||||||
fn Width(self) -> u32 {
|
fn Width(self) -> u32 {
|
||||||
self.width.get()
|
self.width.get()
|
||||||
|
|
2
components/servo/Cargo.lock
generated
2
components/servo/Cargo.lock
generated
|
@ -26,7 +26,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "azure"
|
name = "azure"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/servo/rust-azure#e1a91efa633f155da89c6a1dadb0049d847b319d"
|
source = "git+https://github.com/servo/rust-azure#f4a02f3f621b0a994a20d42e438371a87c62f898"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"core_foundation 0.1.0 (git+https://github.com/servo/rust-core-foundation)",
|
"core_foundation 0.1.0 (git+https://github.com/servo/rust-core-foundation)",
|
||||||
"core_graphics 0.1.0 (git+https://github.com/servo/rust-core-graphics)",
|
"core_graphics 0.1.0 (git+https://github.com/servo/rust-core-graphics)",
|
||||||
|
|
2
ports/cef/Cargo.lock
generated
2
ports/cef/Cargo.lock
generated
|
@ -27,7 +27,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "azure"
|
name = "azure"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/servo/rust-azure#e1a91efa633f155da89c6a1dadb0049d847b319d"
|
source = "git+https://github.com/servo/rust-azure#f4a02f3f621b0a994a20d42e438371a87c62f898"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"core_foundation 0.1.0 (git+https://github.com/servo/rust-core-foundation)",
|
"core_foundation 0.1.0 (git+https://github.com/servo/rust-core-foundation)",
|
||||||
"core_graphics 0.1.0 (git+https://github.com/servo/rust-core-graphics)",
|
"core_graphics 0.1.0 (git+https://github.com/servo/rust-core-graphics)",
|
||||||
|
|
2
ports/gonk/Cargo.lock
generated
2
ports/gonk/Cargo.lock
generated
|
@ -15,7 +15,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "azure"
|
name = "azure"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/servo/rust-azure#e1a91efa633f155da89c6a1dadb0049d847b319d"
|
source = "git+https://github.com/servo/rust-azure#f4a02f3f621b0a994a20d42e438371a87c62f898"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"core_foundation 0.1.0 (git+https://github.com/servo/rust-core-foundation)",
|
"core_foundation 0.1.0 (git+https://github.com/servo/rust-core-foundation)",
|
||||||
"core_graphics 0.1.0 (git+https://github.com/servo/rust-core-graphics)",
|
"core_graphics 0.1.0 (git+https://github.com/servo/rust-core-graphics)",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue