servo: Merge #4137 - CanvasRenderTask connected to Layout (from ebalint:canvas); r=jdm

Content of the canvas is drawn, tests/html/test_canvas.html now works.

Source-Repo: https://github.com/servo/servo
Source-Revision: da400a7a453eacf6f3089cc07e5dc61f385a0909
This commit is contained in:
Edit Balint 2015-01-09 12:06:47 -07:00
Родитель 5622739b90
Коммит 8eb66707e6
11 изменённых файлов: 359 добавлений и 130 удалений

Просмотреть файл

@ -9,13 +9,15 @@ use geom::size::Size2D;
use servo_util::task::spawn_named;
use std::comm;
use std::sync::Arc;
#[deriving(Copy)]
#[deriving(Clone)]
pub enum CanvasMsg {
FillRect(Rect<f32>),
ClearRect(Rect<f32>),
StrokeRect(Rect<f32>),
Recreate(Size2D<i32>),
SendPixelContents(Sender<Arc<Vec<u8>>>),
Close,
}
@ -29,7 +31,7 @@ pub struct CanvasPaintTask {
impl CanvasPaintTask {
fn new(size: Size2D<i32>) -> CanvasPaintTask {
CanvasPaintTask {
drawtarget: CanvasPaintTask::create(size),
drawtarget: CanvasPaintTask::create_with_data(size),
fill_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),
@ -47,6 +49,7 @@ impl CanvasPaintTask {
CanvasMsg::StrokeRect(ref rect) => painter.stroke_rect(rect),
CanvasMsg::ClearRect(ref rect) => painter.clear_rect(rect),
CanvasMsg::Recreate(size) => painter.recreate(size),
CanvasMsg::SendPixelContents(chan) => painter.send_pixel_contents(chan),
CanvasMsg::Close => break,
}
}
@ -68,11 +71,20 @@ impl CanvasPaintTask {
self.drawtarget.stroke_rect(rect, &self.stroke_color, &self.stroke_opts, &drawopts);
}
fn create(size: Size2D<i32>) -> DrawTarget {
DrawTarget::new(BackendType::Skia, size, SurfaceFormat::B8G8R8A8)
fn create_with_data(size: Size2D<i32>) -> DrawTarget {
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>) {
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 fragment::{Fragment, IframeFragmentInfo};
use fragment::ImageFragmentInfo;
use fragment::CanvasFragmentInfo;
use fragment::InlineAbsoluteHypotheticalFragmentInfo;
use fragment::{InlineBlockFragmentInfo, SpecificFragmentInfo};
use fragment::TableColumnFragmentInfo;
@ -272,6 +273,9 @@ impl<'a> FlowConstructor<'a> {
Some(NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableRowElement))) |
Some(NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableSectionElement))) => SpecificFragmentInfo::TableRow,
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.
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.
match (display, float, positioning) {
@ -1288,6 +1292,7 @@ impl<'ln> NodeUtils for ThreadSafeLayoutNode<'ln> {
None |
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::HTMLCanvasElement))) => true,
Some(NodeTypeId::Element(_)) => false,
}
}

Просмотреть файл

@ -11,6 +11,7 @@
#![deny(unsafe_blocks)]
use block::BlockFlow;
use canvas::canvas_paint_task::CanvasMsg::SendPixelContents;
use context::LayoutContext;
use flow::{mod, Flow, IS_ABSOLUTELY_POSITIONED, NEEDS_LAYER};
use fragment::{CoordinateSystem, Fragment, IframeFragmentInfo, ImageFragmentInfo};
@ -32,12 +33,14 @@ use gfx::display_list::TextOrientation;
use gfx::display_list::{SolidColorDisplayItem};
use gfx::display_list::{StackingContext, TextDisplayItem};
use gfx::paint_task::PaintLayer;
use png;
use png::PixelsByColorType;
use servo_msg::compositor_msg::ScrollPolicy;
use servo_msg::constellation_msg::Msg as ConstellationMsg;
use servo_msg::constellation_msg::ConstellationChan;
use servo_net::image::holder::ImageHolder;
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::opts;
use std::default::Default;
@ -862,6 +865,37 @@ impl FragmentDisplayListBuilding for Fragment {
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)]
use canvas::canvas_paint_task::CanvasMsg;
use css::node_style::StyledNode;
use construct::FlowConstructor;
use context::LayoutContext;
@ -128,6 +129,7 @@ pub enum SpecificFragmentInfo {
Generic,
Iframe(Box<IframeFragmentInfo>),
Image(Box<ImageFragmentInfo>),
Canvas(Box<CanvasFragmentInfo>),
/// A hypothetical box (see CSS 2.1 § 10.3.7) for an absolutely-positioned block that was
/// declared with `display: inline;`.
@ -156,6 +158,7 @@ impl SpecificFragmentInfo {
| SpecificFragmentInfo::TableRow
| SpecificFragmentInfo::TableWrapper
| SpecificFragmentInfo::UnscannedText(_)
| SpecificFragmentInfo::Canvas(_)
| SpecificFragmentInfo::Generic => return RestyleDamage::empty(),
SpecificFragmentInfo::InlineAbsoluteHypothetical(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 {
match *self {
SpecificFragmentInfo::Canvas(_) => "SpecificFragmentInfo::Canvas",
SpecificFragmentInfo::Generic => "SpecificFragmentInfo::Generic",
SpecificFragmentInfo::Iframe(_) => "SpecificFragmentInfo::Iframe",
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.
#[deriving(Clone)]
pub struct ImageFragmentInfo {
/// The image held within this fragment.
pub replaced_image_fragment_info: ReplacedImageFragmentInfo,
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 {
@ -247,15 +274,60 @@ impl ImageFragmentInfo {
}).and_then(|pixels| Some(Au::from_px(pixels)))
}
let is_vertical = node.style().writing_mode.is_vertical();
let dom_width = convert_length(node, &atom!("width"));
let dom_height = convert_length(node, &atom!("height"));
ImageFragmentInfo {
replaced_image_fragment_info: ReplacedImageFragmentInfo::new(node,
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 untrusted_node: UntrustedNodeAddress = opaque_node.to_untrusted_node_address();
ImageFragmentInfo {
image: ImageHolder::new(image_url, local_image_cache),
ReplacedImageFragmentInfo {
for_node: untrusted_node,
computed_inline_size: None,
computed_block_size: None,
@ -275,18 +347,6 @@ impl ImageFragmentInfo {
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.
//
// `dom_length`: inline-size or block-size as specified in the `img` tag.
@ -319,16 +379,101 @@ impl ImageFragmentInfo {
})
}
/// 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;
pub fn calculate_replaced_inline_size(&mut self,
style: ComputedValues,
noncontent_inline_size: Au,
container_inline_size: Au,
fragment_inline_size: Au,
fragment_block_size: Au) -> Au {
let style_inline_size = style.content_inline_size();
let style_block_size = style.content_block_size();
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)
-> QuantitiesIncludedInIntrinsicInlineSizes {
match self.specific {
SpecificFragmentInfo::Canvas(_) |
SpecificFragmentInfo::Generic |
SpecificFragmentInfo::Iframe(_) |
SpecificFragmentInfo::Image(_) |
@ -1000,6 +1146,13 @@ impl Fragment {
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) => {
let range = &text_fragment_info.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::TableRow | SpecificFragmentInfo::TableWrapper | SpecificFragmentInfo::InlineBlock(_) |
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) => {
image_fragment_info.computed_inline_size()
image_fragment_info.replaced_image_fragment_info.computed_inline_size()
}
SpecificFragmentInfo::ScannedText(ref text_fragment_info) => {
let (range, run) = (&text_fragment_info.range, &text_fragment_info.run);
@ -1066,7 +1222,10 @@ impl Fragment {
SpecificFragmentInfo::TableRow | SpecificFragmentInfo::TableWrapper | SpecificFragmentInfo::InlineBlock(_) |
SpecificFragmentInfo::InlineAbsoluteHypothetical(_) => Au(0),
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(_) => {
// 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)
-> Option<(SplitInfo, Option<SplitInfo>, Arc<Box<TextRun>> /* TODO(bjz): remove */)> {
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::TableColumn(_) => panic!("Table column fragments do not need to split"),
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
/// 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 {
SpecificFragmentInfo::Generic | SpecificFragmentInfo::Iframe(_) | SpecificFragmentInfo::Table | SpecificFragmentInfo::TableCell |
SpecificFragmentInfo::TableRow | SpecificFragmentInfo::TableWrapper => return,
@ -1308,16 +1467,11 @@ impl Fragment {
SpecificFragmentInfo::UnscannedText(_) => {
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(_) => {}
};
let style_inline_size = self.style().content_inline_size();
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 style = self.style().clone();
let noncontent_inline_size = self.border_padding.inline_start_end();
match self.specific {
@ -1341,49 +1495,24 @@ impl Fragment {
self.border_box.size.inline = info.content_size.inline + noncontent_inline_size
}
SpecificFragmentInfo::Image(ref mut image_fragment_info) => {
// TODO(ksh8281): compute border,margin
let inline_size = ImageFragmentInfo::style_length(
style_inline_size,
image_fragment_info.dom_inline_size,
container_inline_size);
let inline_size = match inline_size {
MaybeAuto::Auto => {
let intrinsic_width = image_fragment_info.image_inline_size();
let intrinsic_height = image_fragment_info.image_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 = ImageFragmentInfo::style_length(
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);
let fragment_inline_size = image_fragment_info.image_inline_size();
let fragment_block_size = image_fragment_info.image_block_size();
self.border_box.size.inline = image_fragment_info.replaced_image_fragment_info.
calculate_replaced_inline_size(style,
noncontent_inline_size,
container_inline_size,
fragment_inline_size,
fragment_block_size);
}
SpecificFragmentInfo::Canvas(ref mut canvas_fragment_info) => {
let fragment_inline_size = canvas_fragment_info.canvas_inline_size();
let fragment_block_size = canvas_fragment_info.canvas_block_size();
self.border_box.size.inline = canvas_fragment_info.replaced_image_fragment_info.
calculate_replaced_inline_size(style,
noncontent_inline_size,
container_inline_size,
fragment_inline_size,
fragment_block_size);
}
_ => panic!("this case should have been handled above"),
}
@ -1401,42 +1530,33 @@ impl Fragment {
SpecificFragmentInfo::UnscannedText(_) => {
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(_) => {}
}
let style_block_size = self.style().content_block_size();
let style_min_block_size = self.style().min_block_size();
let style_max_block_size = self.style().max_block_size();
let style = self.style().clone();
let noncontent_block_size = self.border_padding.block_start_end();
match self.specific {
SpecificFragmentInfo::Image(ref mut image_fragment_info) => {
// TODO(ksh8281): compute border,margin,padding
let inline_size = image_fragment_info.computed_inline_size();
let block_size = ImageFragmentInfo::style_length(
style_block_size,
image_fragment_info.dom_block_size,
containing_block_block_size);
let block_size = match block_size {
MaybeAuto::Auto => {
let scale = image_fragment_info.image_inline_size().to_f32().unwrap()
/ inline_size.to_f32().unwrap();
Au((image_fragment_info.image_block_size().to_f32().unwrap() / scale)
as i32)
},
MaybeAuto::Specified(h) => {
h
}
};
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
let fragment_inline_size = image_fragment_info.image_inline_size();
let fragment_block_size = image_fragment_info.image_block_size();
self.border_box.size.block = image_fragment_info.replaced_image_fragment_info.
calculate_replaced_block_size(style,
noncontent_block_size,
containing_block_block_size,
fragment_inline_size,
fragment_block_size);
}
SpecificFragmentInfo::Canvas(ref mut canvas_fragment_info) => {
let fragment_inline_size = canvas_fragment_info.canvas_inline_size();
let fragment_block_size = canvas_fragment_info.canvas_block_size();
self.border_box.size.block = canvas_fragment_info.replaced_image_fragment_info.
calculate_replaced_block_size(style,
noncontent_block_size,
containing_block_block_size,
fragment_inline_size,
fragment_block_size);
}
SpecificFragmentInfo::ScannedText(ref info) => {
// 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 {
match self.specific {
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 {
block_size_above_baseline: computed_block_size + self.border_padding.block_start_end(),
depth_below_baseline: Au(0),
@ -1538,6 +1658,7 @@ impl Fragment {
SpecificFragmentInfo::InlineBlock(_) |
SpecificFragmentInfo::InlineAbsoluteHypothetical(_) |
SpecificFragmentInfo::TableWrapper => false,
SpecificFragmentInfo::Canvas(_) |
SpecificFragmentInfo::Generic |
SpecificFragmentInfo::Iframe(_) |
SpecificFragmentInfo::Image(_) |

Просмотреть файл

@ -13,12 +13,14 @@
extern crate log;
extern crate cssparser;
extern crate canvas;
extern crate geom;
extern crate gfx;
extern crate layout_traits;
extern crate script;
extern crate script_traits;
extern crate serialize;
extern crate png;
extern crate style;
#[phase(plugin)]
extern crate "plugins" as servo_plugins;

Просмотреть файл

@ -30,6 +30,7 @@
//! o Instead of `html_element_in_html_document()`, use
//! `html_element_in_html_document_for_layout()`.
use canvas::canvas_paint_task::CanvasMsg;
use context::SharedLayoutContext;
use css::node_style::StyledNode;
use incremental::RestyleDamage;
@ -39,12 +40,13 @@ use util::{PrivateLayoutData};
use cssparser::RGBA;
use gfx::display_list::OpaqueNode;
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::js::JS;
use script::dom::element::{Element, ElementTypeId};
use script::dom::element::{LayoutElementHelpers, RawLayoutElementHelpers};
use script::dom::htmlelement::HTMLElementTypeId;
use script::dom::htmlcanvaselement::{HTMLCanvasElement, LayoutHTMLCanvasElementHelpers};
use script::dom::htmliframeelement::HTMLIFrameElement;
use script::dom::htmlimageelement::LayoutHTMLImageElementHelpers;
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
/// not an iframe element, fails.
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> {
fn Canvas(self) -> Temporary<HTMLCanvasElement> {
Temporary::new(self.canvas)

Просмотреть файл

@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use canvas::canvas_paint_task::CanvasMsg;
use dom::attr::Attr;
use dom::attr::AttrHelpers;
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::{ElementCast, HTMLElementCast};
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{MutNullableJS, JSRef, Temporary};
use dom::canvasrenderingcontext2d::CanvasRenderingContext2D;
use dom::bindings::js::{MutNullableJS, JS, JSRef, Temporary};
use dom::canvasrenderingcontext2d::{CanvasRenderingContext2D, LayoutCanvasRenderingContext2DHelpers};
use dom::document::Document;
use dom::element::{Element, AttributeHandlers};
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> {
fn Width(self) -> u32 {
self.width.get()

2
servo/components/servo/Cargo.lock сгенерированный
Просмотреть файл

@ -26,7 +26,7 @@ dependencies = [
[[package]]
name = "azure"
version = "0.1.0"
source = "git+https://github.com/servo/rust-azure#e1a91efa633f155da89c6a1dadb0049d847b319d"
source = "git+https://github.com/servo/rust-azure#f4a02f3f621b0a994a20d42e438371a87c62f898"
dependencies = [
"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)",

2
servo/ports/cef/Cargo.lock сгенерированный
Просмотреть файл

@ -27,7 +27,7 @@ dependencies = [
[[package]]
name = "azure"
version = "0.1.0"
source = "git+https://github.com/servo/rust-azure#e1a91efa633f155da89c6a1dadb0049d847b319d"
source = "git+https://github.com/servo/rust-azure#f4a02f3f621b0a994a20d42e438371a87c62f898"
dependencies = [
"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)",

2
servo/ports/gonk/Cargo.lock сгенерированный
Просмотреть файл

@ -15,7 +15,7 @@ dependencies = [
[[package]]
name = "azure"
version = "0.1.0"
source = "git+https://github.com/servo/rust-azure#e1a91efa633f155da89c6a1dadb0049d847b319d"
source = "git+https://github.com/servo/rust-azure#f4a02f3f621b0a994a20d42e438371a87c62f898"
dependencies = [
"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)",