diff options
Diffstat (limited to 'components/gfx')
-rw-r--r-- | components/gfx/font.rs | 8 | ||||
-rw-r--r-- | components/gfx/font_context.rs | 6 | ||||
-rw-r--r-- | components/gfx/lib.rs | 18 | ||||
-rw-r--r-- | components/gfx/paint_context.rs | 339 | ||||
-rw-r--r-- | components/gfx/platform/freetype/font_list.rs | 4 | ||||
-rw-r--r-- | components/gfx/platform/macos/font.rs | 5 | ||||
-rw-r--r-- | components/gfx/platform/mod.rs | 8 | ||||
-rw-r--r-- | components/gfx/text/glyph.rs | 177 | ||||
-rw-r--r-- | components/gfx/text/shaping/harfbuzz.rs | 4 |
9 files changed, 316 insertions, 253 deletions
diff --git a/components/gfx/font.rs b/components/gfx/font.rs index fd17fa4e467..ba11c2a63cc 100644 --- a/components/gfx/font.rs +++ b/components/gfx/font.rs @@ -101,13 +101,13 @@ pub struct Font { bitflags! { flags ShapingFlags: u8 { - #[doc="Set if the text is entirely whitespace."] + #[doc = "Set if the text is entirely whitespace."] const IS_WHITESPACE_SHAPING_FLAG = 0x01, - #[doc="Set if we are to ignore ligatures."] + #[doc = "Set if we are to ignore ligatures."] const IGNORE_LIGATURES_SHAPING_FLAG = 0x02, - #[doc="Set if we are to disable kerning."] + #[doc = "Set if we are to disable kerning."] const DISABLE_KERNING_SHAPING_FLAG = 0x04, - #[doc="Text direction is right-to-left."] + #[doc = "Text direction is right-to-left."] const RTL_FLAG = 0x08, } } diff --git a/components/gfx/font_context.rs b/components/gfx/font_context.rs index 18ee5e9ff42..640b2b8250c 100644 --- a/components/gfx/font_context.rs +++ b/components/gfx/font_context.rs @@ -31,16 +31,16 @@ use std::sync::Arc; use azure::azure_hl::BackendType; use azure::scaled_font::ScaledFont; -#[cfg(any(target_os="linux", target_os = "android"))] +#[cfg(any(target_os = "linux", target_os = "android"))] use azure::scaled_font::FontInfo; -#[cfg(any(target_os="linux", target_os = "android"))] +#[cfg(any(target_os = "linux", target_os = "android"))] fn create_scaled_font(template: &Arc<FontTemplateData>, pt_size: Au) -> ScaledFont { ScaledFont::new(BackendType::Skia, FontInfo::FontData(&template.bytes), pt_size.to_f32_px()) } -#[cfg(target_os="macos")] +#[cfg(target_os = "macos")] fn create_scaled_font(template: &Arc<FontTemplateData>, pt_size: Au) -> ScaledFont { let cgfont = template.ctfont().as_ref().unwrap().copy_to_CGFont(); ScaledFont::new(BackendType::Skia, &cgfont, pt_size.to_f32_px()) diff --git a/components/gfx/lib.rs b/components/gfx/lib.rs index 6ffbe36fb5b..db73b9b200d 100644 --- a/components/gfx/lib.rs +++ b/components/gfx/lib.rs @@ -3,12 +3,12 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #![feature(arc_weak)] -#![cfg_attr(any(target_os="linux", target_os = "android"), feature(box_raw))] +#![cfg_attr(any(target_os = "linux", target_os = "android"), feature(box_raw))] #![feature(box_syntax)] #![feature(custom_attribute)] #![feature(custom_derive)] #![feature(hashmap_hasher)] -#![cfg_attr(any(target_os="linux", target_os = "android"), feature(heap_api))] +#![cfg_attr(any(target_os = "linux", target_os = "android"), feature(heap_api))] #![feature(mpsc_select)] #![feature(plugin)] #![feature(str_char)] @@ -55,23 +55,23 @@ extern crate canvas_traits; extern crate harfbuzz; // Linux and Android-specific library dependencies -#[cfg(any(target_os="linux", target_os = "android"))] +#[cfg(any(target_os = "linux", target_os = "android"))] extern crate fontconfig; -#[cfg(any(target_os="linux", target_os = "android"))] +#[cfg(any(target_os = "linux", target_os = "android"))] extern crate freetype; // Mac OS-specific library dependencies -#[cfg(target_os="macos")] extern crate core_foundation; -#[cfg(target_os="macos")] extern crate core_graphics; -#[cfg(target_os="macos")] extern crate core_text; +#[cfg(target_os = "macos")] extern crate core_foundation; +#[cfg(target_os = "macos")] extern crate core_graphics; +#[cfg(target_os = "macos")] extern crate core_text; pub use paint_context::PaintContext; // Private painting modules mod paint_context; -#[path="display_list/mod.rs"] +#[path = "display_list/mod.rs"] pub mod display_list; pub mod paint_task; @@ -85,7 +85,7 @@ pub mod font_template; mod filters; // Platform-specific implementations. -#[path="platform/mod.rs"] +#[path = "platform/mod.rs"] pub mod platform; // Text diff --git a/components/gfx/paint_context.rs b/components/gfx/paint_context.rs index a96d413cafc..2c38e0e6fea 100644 --- a/components/gfx/paint_context.rs +++ b/components/gfx/paint_context.rs @@ -72,6 +72,19 @@ enum DashSize { DashedBorder = 3 } +#[derive(Copy, Clone, Debug)] +struct Ellipse { + origin: Point2D<f32>, + width: f32, + height: f32, +} + +#[derive(Copy, Clone, Debug)] +struct Line { + start: Point2D<f32>, + end: Point2D<f32>, +} + impl<'a> PaintContext<'a> { pub fn draw_target(&self) -> &DrawTarget { &self.draw_target @@ -355,6 +368,104 @@ impl<'a> PaintContext<'a> { self.draw_target.push_clip(&path_builder.finish()); } + fn solve_quadratic(a: f32, b: f32, c: f32) -> (Option<f32>, Option<f32>) { + let discriminant = b * b - 4. * a * c; + if discriminant < 0. { + return (None, None); + } + let x1 = (-b + discriminant.sqrt())/(2. * a); + let x2 = (-b - discriminant.sqrt())/(2. * a); + if discriminant == 0. { + return (Some(x1), None); + } + return (Some(x1), Some(x2)); + } + + fn intersect_ellipse_line(e: Ellipse, l: Line) -> (Option<Point2D<f32>>, Option<Point2D<f32>>) { + debug_assert!(l.end.x - l.start.x > f32::EPSILON, "Error line segment end.x > start.x!!"); + // shift the origin to center of the ellipse. + let line = Line { start: l.start - e.origin, + end: l.end - e.origin }; + + let a = (line.end.y - line.start.y)/(line.end.x - line.start.x); + let b = line.start.y - (a * line.start.x); + // given the equation of a line, + // y = a * x + b, + // and the equation of an ellipse, + // x^2/w^2 + y^2/h^2 = 1, + // substitute y = a * x + b, giving + // x^2/w^2 + (a^2x^2 + 2abx + b^2)/h^2 = 1 + // then simplify to + // (h^2 + w^2a^2)x^2 + 2abw^2x + (b^2w^2 - w^2h^2) = 0 + // finally solve for w using the quadratic equation. + let w = e.width; + let h = e.height; + let quad_a = h * h + w * w * a * a; + let quad_b = 2. * a * b * w * w; + let quad_c = b * b * w * w - w * w * h * h; + let intersections = PaintContext::solve_quadratic(quad_a, quad_b, quad_c); + match intersections { + (Some(x0), Some(x1)) => { + let mut p0 = Point2D::new(x0, a * x0 + b) + e.origin; + let mut p1 = Point2D::new(x1, a * x1 + b) + e.origin; + if x0 > x1 { + mem::swap(&mut p0, &mut p1); + } + (Some(p0), Some(p1)) + }, + (Some(x0), None) => { + let p = Point2D::new(x0, a * x0 + b) + e.origin; + (Some(p), None) + }, + (None, Some(x1)) => { + let p = Point2D::new(x1, a * x1 + b) + e.origin; + (Some(p), None) + }, + (None, None) => (None, None), + } + } + + // Given an ellipse and line segment, the line segment may intersect the + // ellipse at 0, 1, or 2 points. We compute those intersection points. + // For each intersection point the angle of the point on the ellipse relative to + // the top|bottom of the ellipse is computed. + // Examples: + // - intersection at ellipse.center + (0, ellipse.height), the angle is 0 rad. + // - intersection at ellipse.center + (0, -ellipse.height), the angle is 0 rad. + // - intersection at ellipse.center + (+-ellipse.width, 0), the angle is pi/2. + fn ellipse_line_intersection_angles(e: Ellipse, l: Line) + -> (Option<(Point2D<f32>, f32)>, Option<(Point2D<f32>, f32)>) { + fn point_angle(e: Ellipse, intersect_point: Point2D<f32>) -> f32 { + ((intersect_point.y - e.origin.y).abs() / e.height).asin() + } + + let intersection = PaintContext::intersect_ellipse_line(e, l); + match intersection { + (Some(p0), Some(p1)) => (Some((p0, point_angle(e, p0))), Some((p1, point_angle(e, p1)))), + (Some(p0), None) => (Some((p0, point_angle(e, p0))), None), + (None, Some(p1)) => (None, Some((p1, point_angle(e, p1)))), + (None, None) => (None, None), + } + } + + fn ellipse_rightmost_line_intersection_angle(e: Ellipse, l: Line) -> Option<f32> { + match PaintContext::ellipse_line_intersection_angles(e, l) { + (Some((p0, angle0)), Some((p1, _))) if p0.x > p1.x => Some(angle0), + (_, Some((_, angle1))) => Some(angle1), + (Some((_, angle0)), None) => Some(angle0), + (None, None) => None, + } + } + + fn ellipse_leftmost_line_intersection_angle(e: Ellipse, l: Line) -> Option<f32> { + match PaintContext::ellipse_line_intersection_angles(e, l) { + (Some((p0, angle0)), Some((p1, _))) if p0.x < p1.x => Some(angle0), + (_, Some((_, angle1))) => Some(angle1), + (Some((_, angle0)), None) => Some(angle0), + (None, None) => None, + } + } + // The following comment is wonderful, and stolen from // gecko:gfx/thebes/gfxContext.cpp:RoundedRectangle for reference. // @@ -450,6 +561,11 @@ impl<'a> PaintContext<'a> { let box_BL = box_TL + Point2D::new(0.0, bounds.size.height); let box_BR = box_TL + Point2D::new(bounds.size.width, bounds.size.height); + let inner_TL = box_TL + Point2D::new(border.left, border.top); + let inner_TR = box_TR + Point2D::new(-border.right, border.top); + let inner_BR = box_BR + Point2D::new(-border.right, -border.bottom); + let inner_BL = box_BL + Point2D::new(border.left, -border.bottom); + let rad_R: AzFloat = 0.; let rad_BR = rad_R + f32::consts::FRAC_PI_4; let rad_B = rad_BR + f32::consts::FRAC_PI_4; @@ -457,7 +573,6 @@ impl<'a> PaintContext<'a> { let rad_L = rad_BL + f32::consts::FRAC_PI_4; let rad_TL = rad_L + f32::consts::FRAC_PI_4; let rad_T = rad_TL + f32::consts::FRAC_PI_4; - let rad_TR = rad_T + f32::consts::FRAC_PI_4; fn dx(x: AzFloat) -> Point2D<AzFloat> { Point2D::new(x, 0.) @@ -475,12 +590,41 @@ impl<'a> PaintContext<'a> { Point2D::new(0., if cond { dy } else { 0. }) } + fn compatible_borders_corner(border1_width: f32, border2_width: f32) -> bool { + (border1_width - border2_width).abs() <= f32::EPSILON + } + + let distance_to_elbow_TL = + if border.top == border.left { + (radius.top_left - border.top).max(0.) + } else { + 0. + }; + let distance_to_elbow_TR = + if border.top == border.right { + (radius.top_right - border.top).max(0.) + } else { + 0. + }; + let distance_to_elbow_BR = + if border.right == border.bottom { + (radius.bottom_right - border.bottom).max(0.) + } else { + 0. + }; + let distance_to_elbow_BL = + if border.left == border.bottom { + (radius.bottom_left - border.bottom).max(0.) + } else { + 0. + }; + match direction { Direction::Top => { let edge_TL = box_TL + dx(radius.top_left.max(border.left)); let edge_TR = box_TR + dx(-radius.top_right.max(border.right)); - let edge_BR = edge_TR + dy(border.top); - let edge_BL = edge_TL + dy(border.top); + let edge_BR = box_TR + dx(-border.right - distance_to_elbow_TR) + dy(border.top); + let edge_BL = box_TL + dx(border.left + distance_to_elbow_TL) + dy(border.top); let corner_TL = edge_TL + dx_if(radius.top_left == 0., -border.left); let corner_TR = edge_TR + dx_if(radius.top_right == 0., border.right); @@ -497,11 +641,18 @@ impl<'a> PaintContext<'a> { // the origin is the center of the arcs we're about to draw. let origin = edge_TR + Point2D::new((border.right - radius.top_right).max(0.), radius.top_right); - // the elbow is the inside of the border's curve. - let distance_to_elbow = (radius.top_right - border.top).max(0.); - - path_builder.arc(origin, radius.top_right, rad_T, rad_TR, false); - path_builder.arc(origin, distance_to_elbow, rad_TR, rad_T, true); + let angle = if compatible_borders_corner(border.top, border.right) { + f32::consts::FRAC_PI_4 + } else { + let line = Line { start: inner_TR, end: box_TR }; + let ellipse = Ellipse { origin: origin, width: radius.top_right, height: radius.top_right }; + PaintContext::ellipse_rightmost_line_intersection_angle(ellipse, line).unwrap() + }; + + path_builder.arc(origin, radius.top_right, rad_T, rad_R - angle, false); + if distance_to_elbow_TR != 0. { + path_builder.arc(origin, distance_to_elbow_TR, rad_R - angle, rad_T, true); + } } match mode { @@ -514,18 +665,26 @@ impl<'a> PaintContext<'a> { if radius.top_left != 0. { let origin = edge_TL + Point2D::new(-(border.left - radius.top_left).max(0.), - radius.top_left); - let distance_to_elbow = (radius.top_left - border.top).max(0.); + radius.top_left); + let angle = if compatible_borders_corner(border.top, border.left) { + f32::consts::FRAC_PI_4 + } else { + let line = Line { start: box_TL, end: inner_TL }; + let ellipse = Ellipse { origin: origin, width: radius.top_left, height: radius.top_left }; + PaintContext::ellipse_leftmost_line_intersection_angle(ellipse, line).unwrap() + }; - path_builder.arc(origin, distance_to_elbow, rad_T, rad_TL, true); - path_builder.arc(origin, radius.top_left, rad_TL, rad_T, false); + if distance_to_elbow_TL != 0. { + path_builder.arc(origin, distance_to_elbow_TL, rad_T, rad_L + angle, true); + } + path_builder.arc(origin, radius.top_left, rad_L + angle, rad_T, false); } } Direction::Left => { let edge_TL = box_TL + dy(radius.top_left.max(border.top)); let edge_BL = box_BL + dy(-radius.bottom_left.max(border.bottom)); - let edge_TR = edge_TL + dx(border.left); - let edge_BR = edge_BL + dx(border.left); + let edge_TR = box_TL + dx(border.left) + dy(border.top + distance_to_elbow_TL); + let edge_BR = box_BL + dx(border.left) + dy(-border.bottom - distance_to_elbow_BL); let corner_TL = edge_TL + dy_if(radius.top_left == 0., -border.top); let corner_BL = edge_BL + dy_if(radius.bottom_left == 0., border.bottom); @@ -540,11 +699,20 @@ impl<'a> PaintContext<'a> { if radius.top_left != 0. { let origin = edge_TL + Point2D::new(radius.top_left, - -(border.top - radius.top_left).max(0.)); - let distance_to_elbow = (radius.top_left - border.left).max(0.); + -(border.top - radius.top_left).max(0.)); - path_builder.arc(origin, radius.top_left, rad_L, rad_TL, false); - path_builder.arc(origin, distance_to_elbow, rad_TL, rad_L, true); + let angle = if compatible_borders_corner(border.top, border.left) { + f32::consts::FRAC_PI_4 + } else { + let line = Line { start: box_TL, end: inner_TL }; + let ellipse = Ellipse { origin: origin, width: radius.top_left, height: radius.top_left }; + PaintContext::ellipse_leftmost_line_intersection_angle(ellipse, line).unwrap() + }; + + path_builder.arc(origin, radius.top_left, rad_L, rad_L + angle, false); + if distance_to_elbow_TL != 0. { + path_builder.arc(origin, distance_to_elbow_TL, rad_L + angle, rad_L, true); + } } match mode { @@ -558,18 +726,28 @@ impl<'a> PaintContext<'a> { if radius.bottom_left != 0. { let origin = edge_BL + Point2D::new(radius.bottom_left, - (border.bottom - radius.bottom_left).max(0.)); - let distance_to_elbow = (radius.bottom_left - border.left).max(0.); - - path_builder.arc(origin, distance_to_elbow, rad_L, rad_BL, true); - path_builder.arc(origin, radius.bottom_left, rad_BL, rad_L, false); + (border.bottom - radius.bottom_left).max(0.)); + let angle = if compatible_borders_corner(border.bottom, border.left) { + f32::consts::FRAC_PI_4 + } else { + let line = Line { start: box_BL, end: inner_BL }; + let ellipse = Ellipse { origin: origin, + width: radius.bottom_left, + height: radius.bottom_left }; + PaintContext::ellipse_leftmost_line_intersection_angle(ellipse, line).unwrap() + }; + + if distance_to_elbow_BL != 0. { + path_builder.arc(origin, distance_to_elbow_BL, rad_L, rad_L - angle, true); + } + path_builder.arc(origin, radius.bottom_left, rad_L - angle, rad_L, false); } } Direction::Right => { let edge_TR = box_TR + dy(radius.top_right.max(border.top)); let edge_BR = box_BR + dy(-radius.bottom_right.max(border.bottom)); - let edge_TL = edge_TR + dx(-border.right); - let edge_BL = edge_BR + dx(-border.right); + let edge_TL = box_TR + dx(-border.right) + dy(border.top + distance_to_elbow_TR); + let edge_BL = box_BR + dx(-border.right) + dy(-border.bottom - distance_to_elbow_BR); let corner_TR = edge_TR + dy_if(radius.top_right == 0., -border.top); let corner_BR = edge_BR + dy_if(radius.bottom_right == 0., border.bottom); @@ -585,10 +763,18 @@ impl<'a> PaintContext<'a> { if radius.top_right != 0. { let origin = edge_TR + Point2D::new(-radius.top_right, -(border.top - radius.top_right).max(0.)); - let distance_to_elbow = (radius.top_right - border.right).max(0.); + let angle = if compatible_borders_corner(border.top, border.right) { + f32::consts::FRAC_PI_4 + } else { + let line = Line { start: inner_TR, end: box_TR }; + let ellipse = Ellipse { origin: origin, width: radius.top_right, height: radius.top_right }; + PaintContext::ellipse_rightmost_line_intersection_angle(ellipse, line).unwrap() + }; - path_builder.arc(origin, distance_to_elbow, rad_R, rad_TR, true); - path_builder.arc(origin, radius.top_right, rad_TR, rad_R, false); + if distance_to_elbow_TR != 0. { + path_builder.arc(origin, distance_to_elbow_TR, rad_R, rad_R - angle, true); + } + path_builder.arc(origin, radius.top_right, rad_R - angle, rad_R, false); } match mode { @@ -602,18 +788,28 @@ impl<'a> PaintContext<'a> { if radius.bottom_right != 0. { let origin = edge_BR + Point2D::new(-radius.bottom_right, - (border.bottom - radius.bottom_right).max(0.)); - let distance_to_elbow = (radius.bottom_right - border.right).max(0.); - - path_builder.arc(origin, radius.bottom_right, rad_R, rad_BR, false); - path_builder.arc(origin, distance_to_elbow, rad_BR, rad_R, true); + (border.bottom - radius.bottom_right).max(0.)); + let angle = if compatible_borders_corner(border.bottom, border.right) { + f32::consts::FRAC_PI_4 + } else { + let line = Line { start: inner_BR, end: box_BR }; + let ellipse = Ellipse { origin: origin, + width: radius.bottom_right, + height: radius.bottom_right }; + PaintContext::ellipse_rightmost_line_intersection_angle(ellipse, line).unwrap() + }; + + path_builder.arc(origin, radius.bottom_right, rad_R, rad_R + angle, false); + if distance_to_elbow_BR != 0. { + path_builder.arc(origin, distance_to_elbow_BR, rad_R + angle, rad_R, true); + } } } Direction::Bottom => { let edge_BL = box_BL + dx(radius.bottom_left.max(border.left)); let edge_BR = box_BR + dx(-radius.bottom_right.max(border.right)); - let edge_TL = edge_BL + dy(-border.bottom); - let edge_TR = edge_BR + dy(-border.bottom); + let edge_TL = box_BL + dy(-border.bottom) + dx(border.left + distance_to_elbow_BL); + let edge_TR = box_BR + dy(-border.bottom) + dx(-border.right - distance_to_elbow_BR); let corner_BR = edge_BR + dx_if(radius.bottom_right == 0., border.right); let corner_BL = edge_BL + dx_if(radius.bottom_left == 0., -border.left); @@ -629,10 +825,20 @@ impl<'a> PaintContext<'a> { if radius.bottom_right != 0. { let origin = edge_BR + Point2D::new((border.right - radius.bottom_right).max(0.), -radius.bottom_right); - let distance_to_elbow = (radius.bottom_right - border.bottom).max(0.); - - path_builder.arc(origin, distance_to_elbow, rad_B, rad_BR, true); - path_builder.arc(origin, radius.bottom_right, rad_BR, rad_B, false); + let angle = if compatible_borders_corner(border.bottom, border.right) { + f32::consts::FRAC_PI_4 + } else { + let line = Line { start: inner_BR, end: box_BR }; + let ellipse = Ellipse { origin: origin, + width: radius.bottom_right, + height: radius.bottom_right }; + PaintContext::ellipse_rightmost_line_intersection_angle(ellipse, line).unwrap() + }; + + if distance_to_elbow_BR != 0. { + path_builder.arc(origin, distance_to_elbow_BR, rad_B, rad_R + angle, true); + } + path_builder.arc(origin, radius.bottom_right, rad_R + angle, rad_B, false); } match mode { @@ -645,11 +851,21 @@ impl<'a> PaintContext<'a> { if radius.bottom_left != 0. { let origin = edge_BL - Point2D::new((border.left - radius.bottom_left).max(0.), - radius.bottom_left); - let distance_to_elbow = (radius.bottom_left - border.bottom).max(0.); - - path_builder.arc(origin, radius.bottom_left, rad_B, rad_BL, false); - path_builder.arc(origin, distance_to_elbow, rad_BL, rad_B, true); + radius.bottom_left); + let angle = if compatible_borders_corner(border.bottom, border.left) { + f32::consts::FRAC_PI_4 + } else { + let line = Line { start: box_BL, end: inner_BL }; + let ellipse = Ellipse { origin: origin, + width: radius.bottom_left, + height: radius.bottom_left }; + PaintContext::ellipse_leftmost_line_intersection_angle(ellipse, line).unwrap() + }; + + path_builder.arc(origin, radius.bottom_left, rad_B, rad_L - angle, false); + if distance_to_elbow_BL != 0. { + path_builder.arc(origin, distance_to_elbow_BL, rad_L - angle, rad_B, true); + } } } } @@ -960,14 +1176,13 @@ impl<'a> PaintContext<'a> { // FIXME(https://github.com/rust-lang/rust/issues/23338) let font = self.font_context.get_paint_font_from_template( &text.text_run.font_template, text.text_run.actual_pt_size); - font - .borrow() - .draw_text(&temporary_draw_target.draw_target, - &*text.text_run, - &text.range, - baseline_origin, - text.text_color, - opts::get().enable_text_antialiasing); + font.borrow() + .draw_text(&temporary_draw_target.draw_target, + &*text.text_run, + &text.range, + baseline_origin, + text.text_color, + opts::get().enable_text_antialiasing); } // Blur, if necessary. @@ -1029,8 +1244,9 @@ impl<'a> PaintContext<'a> { // Calculate the transform matrix. let old_transform = self.draw_target.get_transform(); - let inflated_size = Rect::new(Point2D::new(0.0, 0.0), Size2D::new(size.width as AzFloat, - size.height as AzFloat)); + let inflated_size = Rect::new(Point2D::new(0.0, 0.0), + Size2D::new(size.width as AzFloat, + size.height as AzFloat)); let temporary_draw_target_bounds = old_transform.transform_rect(&inflated_size); matrix = Matrix2D::identity().translate( -temporary_draw_target_bounds.origin.x as AzFloat, @@ -1060,7 +1276,8 @@ impl<'a> PaintContext<'a> { self.draw_target.set_transform(&Matrix2D::identity()); let rect = Rect::new(Point2D::new(0.0, 0.0), self.draw_target.get_size().to_azure_size()); - let rect_temporary = Rect::new(Point2D::new(0.0, 0.0), temporary_draw_target.get_size().to_azure_size()); + let rect_temporary = Rect::new(Point2D::new(0.0, 0.0), + temporary_draw_target.get_size().to_azure_size()); // Create the Azure filter pipeline. let mut accum_blur = Au(0); @@ -1081,7 +1298,10 @@ impl<'a> PaintContext<'a> { self.pop_clip_if_applicable(); debug!("######### use expanded Rect."); - self.draw_target.draw_filter(&filter_node, &rect_temporary, &rect_temporary.origin, draw_options); + self.draw_target.draw_filter(&filter_node, + &rect_temporary, + &rect_temporary.origin, + draw_options); self.push_clip_if_applicable(); } else { debug!("######### use regular Rect."); @@ -1132,9 +1352,10 @@ impl<'a> PaintContext<'a> { } // Draw the shadow, and blur if we need to. - temporary_draw_target.draw_target.fill(&path, - Pattern::Color(ColorPattern::new(color)).to_pattern_ref(), - &DrawOptions::new(1.0, CompositionOp::Over, AntialiasMode::None)); + temporary_draw_target.draw_target.fill( + &path, + Pattern::Color(ColorPattern::new(color)).to_pattern_ref(), + &DrawOptions::new(1.0, CompositionOp::Over, AntialiasMode::None)); self.blur_if_necessary(temporary_draw_target, blur_radius); // Undo the draw target's clip if we need to, and push back the stacking context clip. diff --git a/components/gfx/platform/freetype/font_list.rs b/components/gfx/platform/freetype/font_list.rs index f3557d7dd2f..9e0a5177312 100644 --- a/components/gfx/platform/freetype/font_list.rs +++ b/components/gfx/platform/freetype/font_list.rs @@ -139,7 +139,7 @@ pub fn get_system_default_family(generic_name: &str) -> Option<String> { } } -#[cfg(target_os="linux")] +#[cfg(target_os = "linux")] pub fn get_last_resort_font_families() -> Vec<String> { vec!( "Fira Sans".to_owned(), @@ -148,7 +148,7 @@ pub fn get_last_resort_font_families() -> Vec<String> { ) } -#[cfg(target_os="android")] +#[cfg(target_os = "android")] pub fn get_last_resort_font_families() -> Vec<String> { vec!("Roboto".to_owned()) } diff --git a/components/gfx/platform/macos/font.rs b/components/gfx/platform/macos/font.rs index b96f217e0c9..eb33e326230 100644 --- a/components/gfx/platform/macos/font.rs +++ b/components/gfx/platform/macos/font.rs @@ -33,11 +33,6 @@ pub struct FontTable { data: CFData, } -// Noncopyable. -impl Drop for FontTable { - fn drop(&mut self) {} -} - impl FontTable { pub fn wrap(data: CFData) -> FontTable { FontTable { data: data } diff --git a/components/gfx/platform/mod.rs b/components/gfx/platform/mod.rs index f3bc3f6ec08..085da7cc932 100644 --- a/components/gfx/platform/mod.rs +++ b/components/gfx/platform/mod.rs @@ -2,13 +2,13 @@ * 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/. */ -#[cfg(any(target_os="linux", target_os = "android"))] +#[cfg(any(target_os = "linux", target_os = "android"))] pub use platform::freetype::{font, font_context, font_list, font_template}; -#[cfg(target_os="macos")] +#[cfg(target_os = "macos")] pub use platform::macos::{font, font_context, font_list, font_template}; -#[cfg(any(target_os="linux", target_os = "android"))] +#[cfg(any(target_os = "linux", target_os = "android"))] pub mod freetype { pub mod font; pub mod font_context; @@ -16,7 +16,7 @@ pub mod freetype { pub mod font_template; } -#[cfg(target_os="macos")] +#[cfg(target_os = "macos")] pub mod macos { pub mod font; pub mod font_context; diff --git a/components/gfx/text/glyph.rs b/components/gfx/text/glyph.rs index 29918e5d2d9..d27128014b5 100644 --- a/components/gfx/text/glyph.rs +++ b/components/gfx/text/glyph.rs @@ -58,17 +58,7 @@ impl GlyphEntry { starts_ligature, glyph_count); - let mut val = FLAG_NOT_MISSING; - - if !starts_cluster { - val |= FLAG_NOT_CLUSTER_START; - } - if !starts_ligature { - val |= FLAG_NOT_LIGATURE_GROUP_START; - } - val |= (glyph_count as u32) << GLYPH_COUNT_SHIFT; - - GlyphEntry::new(val) + GlyphEntry::new(glyph_count as u32) } /// Create a GlyphEntry for the case where glyphs couldn't be found for the specified @@ -76,55 +66,22 @@ impl GlyphEntry { fn missing(glyph_count: usize) -> GlyphEntry { assert!(glyph_count <= u16::MAX as usize); - GlyphEntry::new((glyph_count as u32) << GLYPH_COUNT_SHIFT) + GlyphEntry::new(glyph_count as u32) } } /// The id of a particular glyph within a font pub type GlyphId = u32; -// TODO: unify with bit flags? -#[derive(PartialEq, Copy, Clone)] -pub enum BreakType { - None, - Normal, - Hyphen, -} - -static BREAK_TYPE_NONE: u8 = 0x0; -static BREAK_TYPE_NORMAL: u8 = 0x1; -static BREAK_TYPE_HYPHEN: u8 = 0x2; - -fn break_flag_to_enum(flag: u8) -> BreakType { - if (flag & BREAK_TYPE_NORMAL) != 0 { - BreakType::Normal - } else if (flag & BREAK_TYPE_HYPHEN) != 0 { - BreakType::Hyphen - } else { - BreakType::None - } -} - -fn break_enum_to_flag(e: BreakType) -> u8 { - match e { - BreakType::None => BREAK_TYPE_NONE, - BreakType::Normal => BREAK_TYPE_NORMAL, - BreakType::Hyphen => BREAK_TYPE_HYPHEN, - } -} - // TODO: make this more type-safe. -static FLAG_CHAR_IS_SPACE: u32 = 0x10000000; -// These two bits store some BREAK_TYPE_* flags -static FLAG_CAN_BREAK_MASK: u32 = 0x60000000; -static FLAG_CAN_BREAK_SHIFT: u32 = 29; -static FLAG_IS_SIMPLE_GLYPH: u32 = 0x80000000; +const FLAG_CHAR_IS_SPACE: u32 = 0x40000000; +const FLAG_IS_SIMPLE_GLYPH: u32 = 0x80000000; // glyph advance; in Au's. -static GLYPH_ADVANCE_MASK: u32 = 0x0FFF0000; -static GLYPH_ADVANCE_SHIFT: u32 = 16; -static GLYPH_ID_MASK: u32 = 0x0000FFFF; +const GLYPH_ADVANCE_MASK: u32 = 0x3FFF0000; +const GLYPH_ADVANCE_SHIFT: u32 = 16; +const GLYPH_ID_MASK: u32 = 0x0000FFFF; // Non-simple glyphs (more than one glyph per char; missing glyph, // newline, tab, large advance, or nonzero x/y offsets) may have one @@ -132,21 +89,8 @@ static GLYPH_ID_MASK: u32 = 0x0000FFFF; // side array so that there is a 1:1 mapping of GlyphEntry to // unicode char. -// The number of detailed glyphs for this char. If the char couldn't -// be mapped to a glyph (!FLAG_NOT_MISSING), then this actually holds -// the UTF8 code point instead. -static GLYPH_COUNT_MASK: u32 = 0x00FFFF00; -static GLYPH_COUNT_SHIFT: u32 = 8; -// N.B. following Gecko, these are all inverted so that a lot of -// missing chars can be memset with zeros in one fell swoop. -static FLAG_NOT_MISSING: u32 = 0x00000001; -static FLAG_NOT_CLUSTER_START: u32 = 0x00000002; -static FLAG_NOT_LIGATURE_GROUP_START: u32 = 0x00000004; - -static FLAG_CHAR_IS_TAB: u32 = 0x00000008; -static FLAG_CHAR_IS_NEWLINE: u32 = 0x00000010; -//static FLAG_CHAR_IS_LOW_SURROGATE: u32 = 0x00000020; -//static CHAR_IDENTITY_FLAGS_MASK: u32 = 0x00000038; +// The number of detailed glyphs for this char. +const GLYPH_COUNT_MASK: u32 = 0x0000FFFF; fn is_simple_glyph_id(id: GlyphId) -> bool { ((id as u32) & GLYPH_ID_MASK) == id @@ -164,7 +108,6 @@ type DetailedGlyphCount = u16; // Getters and setters for GlyphEntry. Setter methods are functional, // because GlyphEntry is immutable and only a u32 in size. impl GlyphEntry { - // getter methods #[inline(always)] fn advance(&self) -> Au { Au(((self.value & GLYPH_ADVANCE_MASK) >> GLYPH_ADVANCE_SHIFT) as i32) @@ -174,62 +117,20 @@ impl GlyphEntry { self.value & GLYPH_ID_MASK } - fn is_ligature_start(&self) -> bool { - self.has_flag(!FLAG_NOT_LIGATURE_GROUP_START) - } - - fn is_cluster_start(&self) -> bool { - self.has_flag(!FLAG_NOT_CLUSTER_START) - } - - // True if original char was normal (U+0020) space. Other chars may - // map to space glyph, but this does not account for them. + /// True if original char was normal (U+0020) space. Other chars may + /// map to space glyph, but this does not account for them. fn char_is_space(&self) -> bool { self.has_flag(FLAG_CHAR_IS_SPACE) } - fn char_is_tab(&self) -> bool { - !self.is_simple() && self.has_flag(FLAG_CHAR_IS_TAB) - } - - fn char_is_newline(&self) -> bool { - !self.is_simple() && self.has_flag(FLAG_CHAR_IS_NEWLINE) - } - - fn can_break_before(&self) -> BreakType { - let flag = ((self.value & FLAG_CAN_BREAK_MASK) >> FLAG_CAN_BREAK_SHIFT) as u8; - break_flag_to_enum(flag) - } - - // setter methods #[inline(always)] fn set_char_is_space(&self) -> GlyphEntry { GlyphEntry::new(self.value | FLAG_CHAR_IS_SPACE) } - #[inline(always)] - fn set_char_is_tab(&self) -> GlyphEntry { - assert!(!self.is_simple()); - GlyphEntry::new(self.value | FLAG_CHAR_IS_TAB) - } - - #[inline(always)] - fn set_char_is_newline(&self) -> GlyphEntry { - assert!(!self.is_simple()); - GlyphEntry::new(self.value | FLAG_CHAR_IS_NEWLINE) - } - - #[inline(always)] - fn set_can_break_before(&self, e: BreakType) -> GlyphEntry { - let flag = (break_enum_to_flag(e) as u32) << FLAG_CAN_BREAK_SHIFT; - GlyphEntry::new(self.value | flag) - } - - // helper methods - fn glyph_count(&self) -> u16 { assert!(!self.is_simple()); - ((self.value & GLYPH_COUNT_MASK) >> GLYPH_COUNT_SHIFT) as u16 + (self.value & GLYPH_COUNT_MASK) as u16 } #[inline(always)] @@ -576,9 +477,6 @@ impl<'a> GlyphStore { } }; - // FIXME(pcwalton): Is this necessary? I think it's a no-op. - entry = entry.adapt_character_flags_of_entry(self.entry_buffer[i.to_usize()]); - if character == Some(' ') { entry = entry.set_char_is_space() } @@ -647,62 +545,11 @@ impl<'a> GlyphStore { .fold(Au(0), |advance, (_, glyph)| advance + glyph.advance()) } - // getter methods pub fn char_is_space(&self, i: CharIndex) -> bool { assert!(i < self.char_len()); self.entry_buffer[i.to_usize()].char_is_space() } - pub fn char_is_tab(&self, i: CharIndex) -> bool { - assert!(i < self.char_len()); - self.entry_buffer[i.to_usize()].char_is_tab() - } - - pub fn char_is_newline(&self, i: CharIndex) -> bool { - assert!(i < self.char_len()); - self.entry_buffer[i.to_usize()].char_is_newline() - } - - pub fn is_ligature_start(&self, i: CharIndex) -> bool { - assert!(i < self.char_len()); - self.entry_buffer[i.to_usize()].is_ligature_start() - } - - pub fn is_cluster_start(&self, i: CharIndex) -> bool { - assert!(i < self.char_len()); - self.entry_buffer[i.to_usize()].is_cluster_start() - } - - pub fn can_break_before(&self, i: CharIndex) -> BreakType { - assert!(i < self.char_len()); - self.entry_buffer[i.to_usize()].can_break_before() - } - - // setter methods - pub fn set_char_is_space(&mut self, i: CharIndex) { - assert!(i < self.char_len()); - let entry = self.entry_buffer[i.to_usize()]; - self.entry_buffer[i.to_usize()] = entry.set_char_is_space(); - } - - pub fn set_char_is_tab(&mut self, i: CharIndex) { - assert!(i < self.char_len()); - let entry = self.entry_buffer[i.to_usize()]; - self.entry_buffer[i.to_usize()] = entry.set_char_is_tab(); - } - - pub fn set_char_is_newline(&mut self, i: CharIndex) { - assert!(i < self.char_len()); - let entry = self.entry_buffer[i.to_usize()]; - self.entry_buffer[i.to_usize()] = entry.set_char_is_newline(); - } - - pub fn set_can_break_before(&mut self, i: CharIndex, t: BreakType) { - assert!(i < self.char_len()); - let entry = self.entry_buffer[i.to_usize()]; - self.entry_buffer[i.to_usize()] = entry.set_can_break_before(t); - } - pub fn space_count_in_range(&self, range: &Range<CharIndex>) -> u32 { let mut spaces = 0; for index in range.each_index() { diff --git a/components/gfx/text/shaping/harfbuzz.rs b/components/gfx/text/shaping/harfbuzz.rs index 462d5bf485c..426068a4106 100644 --- a/components/gfx/text/shaping/harfbuzz.rs +++ b/components/gfx/text/shaping/harfbuzz.rs @@ -576,13 +576,13 @@ extern fn glyph_h_advance_func(_: *mut hb_font_t, fn glyph_space_advance(font: *mut Font) -> f64 { let space_unicode = ' '; let space_glyph: hb_codepoint_t; - match unsafe {(*font).glyph_index(space_unicode)} { + match unsafe { (*font).glyph_index(space_unicode) } { Some(g) => { space_glyph = g as hb_codepoint_t; } None => panic!("No space info") } - let space_advance = unsafe {(*font).glyph_h_advance(space_glyph as GlyphId)}; + let space_advance = unsafe { (*font).glyph_h_advance(space_glyph as GlyphId) }; space_advance } |