mirror of
https://github.com/servo/servo.git
synced 2025-08-06 22:15:33 +01:00
layout: Implement filter
per CSS-FILTERS § 5.
`blur` and `drop-shadow` are not yet supported, because the `text-shadow` PR makes some fundamental changes to blur rendering that are needed first.
This commit is contained in:
parent
6b3c05cdd2
commit
15d60d7ea4
20 changed files with 499 additions and 62 deletions
|
@ -5,16 +5,17 @@
|
|||
//! Painting of display lists using Moz2D/Azure.
|
||||
|
||||
use azure::azure::AzIntSize;
|
||||
use azure::azure_hl::{SurfaceFormat, Color, ColorPattern, DrawOptions};
|
||||
use azure::azure_hl::{DrawSurfaceOptions, DrawTarget, ExtendMode, FilterType};
|
||||
use azure::azure_hl::{Color, ColorPattern};
|
||||
use azure::azure_hl::{DrawOptions, DrawSurfaceOptions, DrawTarget, ExtendMode, FilterType};
|
||||
use azure::azure_hl::{GaussianBlurInput, GradientStop, Filter, LinearGradientPattern};
|
||||
use azure::azure_hl::{PatternRef, Path, PathBuilder, CompositionOp};
|
||||
use azure::azure_hl::{GaussianBlurAttribute, StrokeOptions};
|
||||
use azure::azure_hl::{GaussianBlurAttribute, StrokeOptions, SurfaceFormat};
|
||||
use azure::scaled_font::ScaledFont;
|
||||
use azure::{AZ_CAP_BUTT, AzFloat, struct__AzDrawOptions, struct__AzGlyph};
|
||||
use azure::{struct__AzGlyphBuffer, struct__AzPoint, AzDrawTargetFillGlyphs};
|
||||
use display_list::TextOrientation::{SidewaysLeft, SidewaysRight, Upright};
|
||||
use display_list::{BOX_SHADOW_INFLATION_FACTOR, BorderRadii, ClippingRegion, TextDisplayItem};
|
||||
use filters;
|
||||
use font_context::FontContext;
|
||||
use geom::matrix2d::Matrix2D;
|
||||
use geom::point::Point2D;
|
||||
|
@ -33,7 +34,7 @@ use std::f32;
|
|||
use std::mem;
|
||||
use std::num::{Float, FloatMath};
|
||||
use std::ptr;
|
||||
use style::computed_values::border_style;
|
||||
use style::computed_values::{border_style, filter};
|
||||
use std::sync::Arc;
|
||||
use text::TextRun;
|
||||
use text::glyph::CharIndex;
|
||||
|
@ -75,7 +76,7 @@ impl<'a> PaintContext<'a> {
|
|||
pub fn draw_solid_color(&self, bounds: &Rect<Au>, color: Color) {
|
||||
self.draw_target.make_current();
|
||||
self.draw_target.fill_rect(&bounds.to_azure_rect(),
|
||||
PatternRef::ColorPatternRef(&ColorPattern::new(color)),
|
||||
PatternRef::Color(&ColorPattern::new(color)),
|
||||
None);
|
||||
}
|
||||
|
||||
|
@ -158,10 +159,9 @@ impl<'a> PaintContext<'a> {
|
|||
Size2D(self.screen_rect.size.width as AzFloat,
|
||||
self.screen_rect.size.height as AzFloat));
|
||||
let mut draw_options = DrawOptions::new(1.0, 0);
|
||||
draw_options.set_composition_op(CompositionOp::SourceOp);
|
||||
draw_options.set_composition_op(CompositionOp::Source);
|
||||
self.draw_target.make_current();
|
||||
self.draw_target.fill_rect(&rect, PatternRef::ColorPatternRef(&pattern),
|
||||
Some(&draw_options));
|
||||
self.draw_target.fill_rect(&rect, PatternRef::Color(&pattern), Some(&draw_options));
|
||||
}
|
||||
|
||||
fn draw_border_segment(&self,
|
||||
|
@ -859,19 +859,20 @@ impl<'a> PaintContext<'a> {
|
|||
stops: &[GradientStop]) {
|
||||
self.draw_target.make_current();
|
||||
|
||||
let stops = self.draw_target.create_gradient_stops(stops, ExtendMode::ExtendClamp);
|
||||
let stops = self.draw_target.create_gradient_stops(stops, ExtendMode::Clamp);
|
||||
let pattern = LinearGradientPattern::new(&start_point.to_azure_point(),
|
||||
&end_point.to_azure_point(),
|
||||
stops,
|
||||
&Matrix2D::identity());
|
||||
|
||||
self.draw_target.fill_rect(&bounds.to_azure_rect(),
|
||||
PatternRef::LinearGradientPatternRef(&pattern),
|
||||
PatternRef::LinearGradient(&pattern),
|
||||
None);
|
||||
}
|
||||
|
||||
pub fn get_or_create_temporary_draw_target(&mut self, opacity: AzFloat) -> DrawTarget {
|
||||
if opacity == 1.0 {
|
||||
pub fn get_or_create_temporary_draw_target(&mut self, filters: &filter::T) -> DrawTarget {
|
||||
// Determine if we need a temporary draw target.
|
||||
if !filters::temporary_draw_target_needed_for_style_filters(filters) {
|
||||
// Reuse the draw target, but remove the transient clip. If we don't do the latter,
|
||||
// we'll be in a state whereby the paint subcontext thinks it has no transient clip
|
||||
// (see `StackingContext::optimize_and_draw_into_context`) but it actually does,
|
||||
|
@ -883,10 +884,7 @@ impl<'a> PaintContext<'a> {
|
|||
|
||||
// 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 size = Size2D(size.width, size.height);
|
||||
|
||||
let temporary_draw_target =
|
||||
self.draw_target.create_similar_draw_target(&size, self.draw_target.get_format());
|
||||
|
@ -898,24 +896,29 @@ impl<'a> PaintContext<'a> {
|
|||
/// 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) {
|
||||
filters: &filter::T) {
|
||||
if (*temporary_draw_target) == self.draw_target {
|
||||
// We're directly painting to the surface; nothing to do.
|
||||
return
|
||||
}
|
||||
|
||||
// Set up transforms.
|
||||
let old_transform = self.draw_target.get_transform();
|
||||
self.draw_target.set_transform(&Matrix2D::identity());
|
||||
temporary_draw_target.set_transform(&Matrix2D::identity());
|
||||
|
||||
// Create the Azure filter pipeline.
|
||||
let (filter_node, opacity) = filters::create_filters(&self.draw_target,
|
||||
temporary_draw_target,
|
||||
filters);
|
||||
|
||||
// Perform the blit operation.
|
||||
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(Filter::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.draw_filter(&filter_node,
|
||||
&rect,
|
||||
&rect.origin,
|
||||
draw_options);
|
||||
self.draw_target.set_transform(&old_transform);
|
||||
}
|
||||
|
||||
|
@ -974,9 +977,9 @@ impl<'a> PaintContext<'a> {
|
|||
if blur_radius > Au(0) {
|
||||
// Go ahead and create the blur now. Despite the name, Azure's notion of `StdDeviation`
|
||||
// describes the blur radius, not the sigma for the Gaussian blur.
|
||||
let blur_filter = self.draw_target.create_filter(FilterType::GaussianBlurFilterType);
|
||||
blur_filter.set_attribute(GaussianBlurAttribute::StdDeviationGaussianBlurAttribute(
|
||||
blur_radius.to_subpx() as AzFloat));
|
||||
let blur_filter = self.draw_target.create_filter(FilterType::GaussianBlur);
|
||||
blur_filter.set_attribute(GaussianBlurAttribute::StdDeviation(blur_radius.to_subpx() as
|
||||
AzFloat));
|
||||
blur_filter.set_input(GaussianBlurInput, &temporary_draw_target.snapshot());
|
||||
|
||||
// Blit the blur onto the tile. We undo the transforms here because we want to directly
|
||||
|
@ -985,7 +988,7 @@ impl<'a> PaintContext<'a> {
|
|||
self.draw_target.set_transform(&Matrix2D::identity());
|
||||
let temporary_draw_target_size = temporary_draw_target.get_size();
|
||||
self.draw_target
|
||||
.draw_filter(blur_filter,
|
||||
.draw_filter(&blur_filter,
|
||||
&Rect(Point2D(0.0, 0.0),
|
||||
Size2D(temporary_draw_target_size.width as AzFloat,
|
||||
temporary_draw_target_size.height as AzFloat)),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue