mirror of
https://github.com/servo/servo.git
synced 2025-08-08 15:05:35 +01:00
Invert control flow, fix resizing, and improve checkerboarding
significantly by giving tiles some time to paint before we render unrendered content.
This commit is contained in:
parent
e483a189a3
commit
10f7b49cf7
27 changed files with 1195 additions and 678 deletions
|
@ -19,6 +19,7 @@ use render_context::RenderContext;
|
|||
use text::glyph::CharIndex;
|
||||
use text::TextRun;
|
||||
|
||||
use azure::azure::AzFloat;
|
||||
use collections::Deque;
|
||||
use collections::dlist::{mod, DList};
|
||||
use geom::{Point2D, Rect, SideOffsets2D, Size2D, Matrix2D};
|
||||
|
@ -26,18 +27,11 @@ use libc::uintptr_t;
|
|||
use servo_net::image::base::Image;
|
||||
use servo_util::dlist as servo_dlist;
|
||||
use servo_util::geometry::Au;
|
||||
use servo_util::opts;
|
||||
use servo_util::range::Range;
|
||||
use std::fmt;
|
||||
use std::slice::Items;
|
||||
use style::computed_values::border_style;
|
||||
use sync::Arc;
|
||||
use std::num::Zero;
|
||||
use std::ptr;
|
||||
|
||||
use azure::AzFloat;
|
||||
use azure::scaled_font::ScaledFont;
|
||||
use azure::azure_hl::ColorPattern;
|
||||
|
||||
pub mod optimizer;
|
||||
|
||||
|
@ -58,88 +52,6 @@ impl OpaqueNode {
|
|||
}
|
||||
}
|
||||
|
||||
trait ScaledFontExtensionMethods {
|
||||
fn draw_text_into_context(&self,
|
||||
rctx: &RenderContext,
|
||||
run: &Box<TextRun>,
|
||||
range: &Range<CharIndex>,
|
||||
baseline_origin: Point2D<Au>,
|
||||
color: Color,
|
||||
antialias: bool);
|
||||
}
|
||||
|
||||
impl ScaledFontExtensionMethods for ScaledFont {
|
||||
fn draw_text_into_context(&self,
|
||||
rctx: &RenderContext,
|
||||
run: &Box<TextRun>,
|
||||
range: &Range<CharIndex>,
|
||||
baseline_origin: Point2D<Au>,
|
||||
color: Color,
|
||||
antialias: bool) {
|
||||
use libc::types::common::c99::uint32_t;
|
||||
use azure::{struct__AzDrawOptions,
|
||||
struct__AzGlyph,
|
||||
struct__AzGlyphBuffer,
|
||||
struct__AzPoint};
|
||||
use azure::azure::{AzDrawTargetFillGlyphs};
|
||||
|
||||
let target = rctx.get_draw_target();
|
||||
let pattern = ColorPattern::new(color);
|
||||
let azure_pattern = pattern.azure_color_pattern;
|
||||
assert!(azure_pattern.is_not_null());
|
||||
|
||||
let fields = if antialias {
|
||||
0x0200
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
let mut options = struct__AzDrawOptions {
|
||||
mAlpha: 1f64 as AzFloat,
|
||||
fields: fields,
|
||||
};
|
||||
|
||||
let mut origin = baseline_origin.clone();
|
||||
let mut azglyphs = vec!();
|
||||
azglyphs.reserve(range.length().to_uint());
|
||||
|
||||
for (glyphs, _offset, slice_range) in run.iter_slices_for_range(range) {
|
||||
for (_i, glyph) in glyphs.iter_glyphs_for_char_range(&slice_range) {
|
||||
let glyph_advance = glyph.advance();
|
||||
let glyph_offset = glyph.offset().unwrap_or(Zero::zero());
|
||||
|
||||
let azglyph = struct__AzGlyph {
|
||||
mIndex: glyph.id() as uint32_t,
|
||||
mPosition: struct__AzPoint {
|
||||
x: (origin.x + glyph_offset.x).to_subpx() as AzFloat,
|
||||
y: (origin.y + glyph_offset.y).to_subpx() as AzFloat
|
||||
}
|
||||
};
|
||||
origin = Point2D(origin.x + glyph_advance, origin.y);
|
||||
azglyphs.push(azglyph)
|
||||
};
|
||||
}
|
||||
|
||||
let azglyph_buf_len = azglyphs.len();
|
||||
if azglyph_buf_len == 0 { return; } // Otherwise the Quartz backend will assert.
|
||||
|
||||
let mut glyphbuf = struct__AzGlyphBuffer {
|
||||
mGlyphs: azglyphs.as_mut_ptr(),
|
||||
mNumGlyphs: azglyph_buf_len as uint32_t
|
||||
};
|
||||
|
||||
unsafe {
|
||||
// TODO(Issue #64): this call needs to move into azure_hl.rs
|
||||
AzDrawTargetFillGlyphs(target.azure_draw_target,
|
||||
self.get_ref(),
|
||||
&mut glyphbuf,
|
||||
azure_pattern,
|
||||
&mut options,
|
||||
ptr::null_mut());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// "Steps" as defined by CSS 2.1 § E.2.
|
||||
#[deriving(Clone, PartialEq, Show)]
|
||||
pub enum StackingLevel {
|
||||
|
@ -543,55 +455,7 @@ impl DisplayItem {
|
|||
|
||||
TextDisplayItemClass(ref text) => {
|
||||
debug!("Drawing text at {}.", text.base.bounds);
|
||||
|
||||
// Optimization: Don’t set a transform matrix for upright text,
|
||||
// and pass a strart point to `draw_text_into_context`.
|
||||
// For sideways text, it’s easier to do the rotation such that its center
|
||||
// (the baseline’s start point) is at (0, 0) coordinates.
|
||||
let baseline_origin = match text.orientation {
|
||||
Upright => text.baseline_origin,
|
||||
SidewaysLeft => {
|
||||
let x = text.baseline_origin.x.to_nearest_px() as AzFloat;
|
||||
let y = text.baseline_origin.y.to_nearest_px() as AzFloat;
|
||||
render_context.draw_target.set_transform(¤t_transform.mul(
|
||||
&Matrix2D::new(
|
||||
0., -1.,
|
||||
1., 0.,
|
||||
x, y
|
||||
)
|
||||
));
|
||||
Zero::zero()
|
||||
},
|
||||
SidewaysRight => {
|
||||
let x = text.baseline_origin.x.to_nearest_px() as AzFloat;
|
||||
let y = text.baseline_origin.y.to_nearest_px() as AzFloat;
|
||||
render_context.draw_target.set_transform(¤t_transform.mul(
|
||||
&Matrix2D::new(
|
||||
0., 1.,
|
||||
-1., 0.,
|
||||
x, y
|
||||
)
|
||||
));
|
||||
Zero::zero()
|
||||
}
|
||||
};
|
||||
|
||||
render_context.font_ctx.get_render_font_from_template(
|
||||
&text.text_run.font_template,
|
||||
text.text_run.actual_pt_size
|
||||
).borrow().draw_text_into_context(
|
||||
render_context,
|
||||
&*text.text_run,
|
||||
&text.range,
|
||||
baseline_origin,
|
||||
text.text_color,
|
||||
opts::get().enable_text_antialiasing
|
||||
);
|
||||
|
||||
// Undo the transform, only when we did one.
|
||||
if text.orientation != Upright {
|
||||
render_context.draw_target.set_transform(current_transform)
|
||||
}
|
||||
render_context.draw_text(&**text, current_transform);
|
||||
}
|
||||
|
||||
ImageDisplayItemClass(ref image_item) => {
|
||||
|
|
|
@ -30,6 +30,7 @@ extern crate "util" as servo_util;
|
|||
extern crate "msg" as servo_msg;
|
||||
extern crate style;
|
||||
extern crate sync;
|
||||
extern crate time;
|
||||
extern crate url;
|
||||
|
||||
// Eventually we would like the shaper to be pluggable, as many operating systems have their own
|
||||
|
|
|
@ -2,23 +2,32 @@
|
|||
* 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 display_list::{SidewaysLeft, SidewaysRight, TextDisplayItem, Upright};
|
||||
use font_context::FontContext;
|
||||
use style::computed_values::border_style;
|
||||
|
||||
use azure::azure_hl::{B8G8R8A8, A8, Color, ColorPattern, ColorPatternRef, DrawOptions};
|
||||
use azure::azure_hl::{DrawSurfaceOptions, DrawTarget, Linear, SourceOp, StrokeOptions};
|
||||
use azure::AZ_CAP_BUTT;
|
||||
use azure::AzFloat;
|
||||
use azure::azure_hl::{DrawSurfaceOptions,DrawTarget, Linear, SourceOp, StrokeOptions};
|
||||
use azure::scaled_font::ScaledFont;
|
||||
use azure::{AZ_CAP_BUTT, AzDrawTargetFillGlyphs, AzFloat, struct__AzDrawOptions, struct__AzGlyph};
|
||||
use azure::{struct__AzGlyphBuffer, struct__AzPoint};
|
||||
use geom::matrix2d::Matrix2D;
|
||||
use geom::point::Point2D;
|
||||
use geom::rect::Rect;
|
||||
use geom::size::Size2D;
|
||||
use geom::side_offsets::SideOffsets2D;
|
||||
use libc::types::common::c99::uint16_t;
|
||||
use libc::types::common::c99::{uint16_t, uint32_t};
|
||||
use libc::size_t;
|
||||
use png::{RGB8, RGBA8, K8, KA8};
|
||||
use servo_net::image::base::Image;
|
||||
use servo_util::geometry::Au;
|
||||
use servo_util::opts;
|
||||
use servo_util::range::Range;
|
||||
use std::num::Zero;
|
||||
use std::ptr;
|
||||
use sync::Arc;
|
||||
use text::glyph::CharIndex;
|
||||
use text::TextRun;
|
||||
|
||||
pub struct RenderContext<'a> {
|
||||
pub draw_target: &'a DrawTarget,
|
||||
|
@ -390,6 +399,50 @@ impl<'a> RenderContext<'a> {
|
|||
self.draw_border_path(original_bounds, direction, border, scaled_color);
|
||||
}
|
||||
|
||||
pub fn draw_text(&mut self,
|
||||
text: &TextDisplayItem,
|
||||
current_transform: &Matrix2D<AzFloat>) {
|
||||
// Optimization: Don’t set a transform matrix for upright text, and pass a start point to
|
||||
// `draw_text_into_context`.
|
||||
//
|
||||
// For sideways text, it’s easier to do the rotation such that its center (the baseline’s
|
||||
// start point) is at (0, 0) coordinates.
|
||||
let baseline_origin = match text.orientation {
|
||||
Upright => text.baseline_origin,
|
||||
SidewaysLeft => {
|
||||
let x = text.baseline_origin.x.to_subpx() as AzFloat;
|
||||
let y = text.baseline_origin.y.to_subpx() as AzFloat;
|
||||
self.draw_target.set_transform(¤t_transform.mul(&Matrix2D::new(0., -1.,
|
||||
1., 0.,
|
||||
x, y)));
|
||||
Zero::zero()
|
||||
}
|
||||
SidewaysRight => {
|
||||
let x = text.baseline_origin.x.to_subpx() as AzFloat;
|
||||
let y = text.baseline_origin.y.to_subpx() as AzFloat;
|
||||
self.draw_target.set_transform(¤t_transform.mul(&Matrix2D::new(0., 1.,
|
||||
-1., 0.,
|
||||
x, y)));
|
||||
Zero::zero()
|
||||
}
|
||||
};
|
||||
|
||||
self.font_ctx
|
||||
.get_render_font_from_template(&text.text_run.font_template,
|
||||
text.text_run.actual_pt_size)
|
||||
.borrow()
|
||||
.draw_text_into_context(self,
|
||||
&*text.text_run,
|
||||
&text.range,
|
||||
baseline_origin,
|
||||
text.text_color,
|
||||
opts::get().enable_text_antialiasing);
|
||||
|
||||
// Undo the transform, only when we did one.
|
||||
if text.orientation != Upright {
|
||||
self.draw_target.set_transform(current_transform)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait ToAzureRect {
|
||||
|
@ -417,3 +470,78 @@ impl ToSideOffsetsPx for SideOffsets2D<Au> {
|
|||
self.left.to_nearest_px() as AzFloat)
|
||||
}
|
||||
}
|
||||
|
||||
trait ScaledFontExtensionMethods {
|
||||
fn draw_text_into_context(&self,
|
||||
rctx: &RenderContext,
|
||||
run: &Box<TextRun>,
|
||||
range: &Range<CharIndex>,
|
||||
baseline_origin: Point2D<Au>,
|
||||
color: Color,
|
||||
antialias: bool);
|
||||
}
|
||||
|
||||
impl ScaledFontExtensionMethods for ScaledFont {
|
||||
fn draw_text_into_context(&self,
|
||||
rctx: &RenderContext,
|
||||
run: &Box<TextRun>,
|
||||
range: &Range<CharIndex>,
|
||||
baseline_origin: Point2D<Au>,
|
||||
color: Color,
|
||||
antialias: bool) {
|
||||
let target = rctx.get_draw_target();
|
||||
let pattern = ColorPattern::new(color);
|
||||
let azure_pattern = pattern.azure_color_pattern;
|
||||
assert!(azure_pattern.is_not_null());
|
||||
|
||||
let fields = if antialias {
|
||||
0x0200
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
let mut options = struct__AzDrawOptions {
|
||||
mAlpha: 1f64 as AzFloat,
|
||||
fields: fields,
|
||||
};
|
||||
|
||||
let mut origin = baseline_origin.clone();
|
||||
let mut azglyphs = vec!();
|
||||
azglyphs.reserve(range.length().to_uint());
|
||||
|
||||
for (glyphs, _offset, slice_range) in run.iter_slices_for_range(range) {
|
||||
for (_i, glyph) in glyphs.iter_glyphs_for_char_range(&slice_range) {
|
||||
let glyph_advance = glyph.advance();
|
||||
let glyph_offset = glyph.offset().unwrap_or(Zero::zero());
|
||||
let azglyph = struct__AzGlyph {
|
||||
mIndex: glyph.id() as uint32_t,
|
||||
mPosition: struct__AzPoint {
|
||||
x: (origin.x + glyph_offset.x).to_subpx() as AzFloat,
|
||||
y: (origin.y + glyph_offset.y).to_subpx() as AzFloat
|
||||
}
|
||||
};
|
||||
origin = Point2D(origin.x + glyph_advance, origin.y);
|
||||
azglyphs.push(azglyph)
|
||||
};
|
||||
}
|
||||
|
||||
let azglyph_buf_len = azglyphs.len();
|
||||
if azglyph_buf_len == 0 { return; } // Otherwise the Quartz backend will assert.
|
||||
|
||||
let mut glyphbuf = struct__AzGlyphBuffer {
|
||||
mGlyphs: azglyphs.as_mut_ptr(),
|
||||
mNumGlyphs: azglyph_buf_len as uint32_t
|
||||
};
|
||||
|
||||
unsafe {
|
||||
// TODO(Issue #64): this call needs to move into azure_hl.rs
|
||||
AzDrawTargetFillGlyphs(target.azure_draw_target,
|
||||
self.get_ref(),
|
||||
&mut glyphbuf,
|
||||
azure_pattern,
|
||||
&mut options,
|
||||
ptr::null_mut());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
use buffer_map::BufferMap;
|
||||
use display_list::optimizer::DisplayListOptimizer;
|
||||
use display_list::DisplayList;
|
||||
use font_cache_task::FontCacheTask;
|
||||
use font_context::FontContext;
|
||||
use render_context::RenderContext;
|
||||
|
||||
|
@ -37,7 +38,6 @@ use std::comm::{Receiver, Sender, channel};
|
|||
use std::mem;
|
||||
use std::task::TaskBuilder;
|
||||
use sync::Arc;
|
||||
use font_cache_task::FontCacheTask;
|
||||
|
||||
/// Information about a layer that layout sends to the painting task.
|
||||
#[deriving(Clone)]
|
||||
|
@ -153,7 +153,10 @@ impl<C> RenderTask<C> where C: RenderListener + Send {
|
|||
shutdown_chan: Sender<()>) {
|
||||
let ConstellationChan(c) = constellation_chan.clone();
|
||||
spawn_named_with_send_on_failure("RenderTask", task_state::Render, proc() {
|
||||
{ // Ensures RenderTask and graphics context are destroyed before shutdown msg
|
||||
{
|
||||
// Ensures that the render task and graphics context are destroyed before the
|
||||
// shutdown message.
|
||||
let mut compositor = compositor;
|
||||
let native_graphics_context = compositor.get_graphics_metadata().map(
|
||||
|md| NativePaintingGraphicsContext::from_metadata(&md));
|
||||
let worker_threads = WorkerThreadProxy::spawn(compositor.get_graphics_metadata(),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue