aboutsummaryrefslogtreecommitdiffstats
path: root/components/gfx
diff options
context:
space:
mode:
Diffstat (limited to 'components/gfx')
-rw-r--r--components/gfx/font.rs8
-rw-r--r--components/gfx/font_context.rs6
-rw-r--r--components/gfx/lib.rs18
-rw-r--r--components/gfx/paint_context.rs339
-rw-r--r--components/gfx/platform/freetype/font_list.rs4
-rw-r--r--components/gfx/platform/macos/font.rs5
-rw-r--r--components/gfx/platform/mod.rs8
-rw-r--r--components/gfx/text/glyph.rs177
-rw-r--r--components/gfx/text/shaping/harfbuzz.rs4
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
}