diff options
Diffstat (limited to 'components/gfx/render_context.rs')
-rw-r--r-- | components/gfx/render_context.rs | 68 |
1 files changed, 64 insertions, 4 deletions
diff --git a/components/gfx/render_context.rs b/components/gfx/render_context.rs index 973d1925a3f..6dbe84be15a 100644 --- a/components/gfx/render_context.rs +++ b/components/gfx/render_context.rs @@ -4,6 +4,7 @@ //! Painting of display lists using Moz2D/Azure. +use azure::azure::AzIntSize; use azure::azure_hl::{B8G8R8A8, A8, Color, ColorPattern, ColorPatternRef, DrawOptions}; use azure::azure_hl::{DrawSurfaceOptions, DrawTarget, ExtendClamp, GradientStop, Linear}; use azure::azure_hl::{LinearGradientPattern, LinearGradientPatternRef, SourceOp, StrokeOptions}; @@ -33,7 +34,7 @@ use text::TextRun; use text::glyph::CharIndex; pub struct RenderContext<'a> { - pub draw_target: &'a DrawTarget, + pub draw_target: DrawTarget, pub font_ctx: &'a mut Box<FontContext>, /// The rectangle that this context encompasses in page coordinates. pub page_rect: Rect<f32>, @@ -54,8 +55,8 @@ enum DashSize { } impl<'a> RenderContext<'a> { - pub fn get_draw_target(&self) -> &'a DrawTarget { - self.draw_target + pub fn get_draw_target(&self) -> &DrawTarget { + &self.draw_target } pub fn draw_solid_color(&self, bounds: &Rect<Au>, color: Color) { @@ -153,7 +154,13 @@ impl<'a> RenderContext<'a> { self.draw_target.fill_rect(&rect, ColorPatternRef(&pattern), Some(&draw_options)); } - fn draw_border_segment(&self, direction: Direction, bounds: &Rect<Au>, border: SideOffsets2D<f32>, radius: &BorderRadii<AzFloat>, color: SideOffsets2D<Color>, style: SideOffsets2D<border_style::T>) { + fn draw_border_segment(&self, + direction: Direction, + bounds: &Rect<Au>, + border: SideOffsets2D<f32>, + radius: &BorderRadii<AzFloat>, + color: SideOffsets2D<Color>, + style: SideOffsets2D<border_style::T>) { let (style_select, color_select) = match direction { Top => (style.top, color.top), Left => (style.left, color.left), @@ -641,6 +648,49 @@ impl<'a> RenderContext<'a> { LinearGradientPatternRef(&pattern), None); } + + pub fn get_or_create_temporary_draw_target(&mut self, opacity: AzFloat) -> DrawTarget { + if opacity == 1.0 { + return self.draw_target.clone() + } + + // FIXME(pcwalton): This surface might be bigger than necessary and waste memory. + let size = self.draw_target.get_size(); + let size = Size2D { + width: size.width, + height: size.height, + }; + + let temporary_draw_target = + self.draw_target.create_similar_draw_target(&size, self.draw_target.get_format()); + temporary_draw_target.set_transform(&self.draw_target.get_transform()); + temporary_draw_target + } + + /// If we created a temporary draw target, then draw it to the main draw target. This is called + /// after doing all the painting, and the temporary draw target must not be used afterward. + pub fn draw_temporary_draw_target_if_necessary(&mut self, + temporary_draw_target: &DrawTarget, + opacity: AzFloat) { + if (*temporary_draw_target) == self.draw_target { + // We're directly rendering to the surface; nothing to do. + return + } + + let old_transform = self.draw_target.get_transform(); + self.draw_target.set_transform(&Matrix2D::identity()); + temporary_draw_target.set_transform(&Matrix2D::identity()); + let rect = Rect(Point2D(0.0, 0.0), self.draw_target.get_size().to_azure_size()); + let source_surface = temporary_draw_target.snapshot(); + let draw_surface_options = DrawSurfaceOptions::new(Linear, true); + let draw_options = DrawOptions::new(opacity, 0); + self.draw_target.draw_surface(source_surface, + rect, + rect, + draw_surface_options, + draw_options); + self.draw_target.set_transform(&old_transform); + } } pub trait ToAzurePoint { @@ -665,6 +715,16 @@ impl ToAzureRect for Rect<Au> { } } +pub trait ToAzureSize { + fn to_azure_size(&self) -> Size2D<AzFloat>; +} + +impl ToAzureSize for AzIntSize { + fn to_azure_size(&self) -> Size2D<AzFloat> { + Size2D(self.width as AzFloat, self.height as AzFloat) + } +} + trait ToSideOffsetsPx { fn to_float_px(&self) -> SideOffsets2D<AzFloat>; } |