Add some implicit conversions between scalars and vectors where appropriate

This commit is contained in:
Patrick Walton 2020-04-01 17:20:32 -07:00
parent 40bd13aa5a
commit 794dd55038
26 changed files with 268 additions and 225 deletions

View File

@ -341,7 +341,7 @@ pub unsafe extern "C" fn PFCanvasSetLineDashOffset(canvas: PFCanvasRef, new_offs
pub unsafe extern "C" fn PFCanvasSetFontByPostScriptName(canvas: PFCanvasRef, pub unsafe extern "C" fn PFCanvasSetFontByPostScriptName(canvas: PFCanvasRef,
postscript_name: *const c_char, postscript_name: *const c_char,
postscript_name_len: usize) { postscript_name_len: usize) {
(*canvas).set_font_by_postscript_name(to_rust_string(&postscript_name, postscript_name_len)) (*canvas).set_font(to_rust_string(&postscript_name, postscript_name_len))
} }
#[no_mangle] #[no_mangle]

View File

@ -23,7 +23,7 @@ use pathfinder_content::stroke::{OutlineStrokeToFill, StrokeStyle};
use pathfinder_geometry::line_segment::LineSegment2F; use pathfinder_geometry::line_segment::LineSegment2F;
use pathfinder_geometry::rect::RectF; use pathfinder_geometry::rect::RectF;
use pathfinder_geometry::transform2d::Transform2F; use pathfinder_geometry::transform2d::Transform2F;
use pathfinder_geometry::vector::{Vector2F, vec2f}; use pathfinder_geometry::vector::{IntoVector2F, Vector2F, vec2f};
use pathfinder_renderer::paint::{Paint, PaintId}; use pathfinder_renderer::paint::{Paint, PaintId};
use pathfinder_renderer::scene::{ClipPath, ClipPathId, DrawPath, RenderTarget, Scene}; use pathfinder_renderer::scene::{ClipPath, ClipPathId, DrawPath, RenderTarget, Scene};
use std::borrow::Cow; use std::borrow::Cow;
@ -550,7 +550,7 @@ impl Path2D {
start_angle: f32, start_angle: f32,
end_angle: f32, end_angle: f32,
direction: ArcDirection) { direction: ArcDirection) {
let transform = Transform2F::from_scale(Vector2F::splat(radius)).translate(center); let transform = Transform2F::from_scale(radius).translate(center);
self.current_contour.push_arc(&transform, start_angle, end_angle, direction); self.current_contour.push_arc(&transform, start_angle, end_angle, direction);
} }
@ -562,12 +562,10 @@ impl Path2D {
let (vu0, vu1) = (v0.normalize(), v1.normalize()); let (vu0, vu1) = (v0.normalize(), v1.normalize());
let hypot = radius / f32::sqrt(0.5 * (1.0 - vu0.dot(vu1))); let hypot = radius / f32::sqrt(0.5 * (1.0 - vu0.dot(vu1)));
let bisector = vu0 + vu1; let bisector = vu0 + vu1;
let center = ctrl + bisector.scale(hypot / bisector.length()); let center = ctrl + bisector * (hypot / bisector.length());
let transform = Transform2F::from_scale(Vector2F::splat(radius)).translate(center); let transform = Transform2F::from_scale(radius).translate(center);
let chord = LineSegment2F::new(vu0.yx() * vec2f(-1.0, 1.0), vu1.yx() * vec2f( 1.0, -1.0));
let chord = LineSegment2F::new(vu0.yx().scale_xy(vec2f(-1.0, 1.0)),
vu1.yx().scale_xy(vec2f( 1.0, -1.0)));
// FIXME(pcwalton): Is clockwise direction correct? // FIXME(pcwalton): Is clockwise direction correct?
self.current_contour.push_arc_from_unit_chord(&transform, chord, ArcDirection::CW); self.current_contour.push_arc_from_unit_chord(&transform, chord, ArcDirection::CW);
@ -582,12 +580,13 @@ impl Path2D {
self.current_contour.close(); self.current_contour.close();
} }
pub fn ellipse(&mut self, pub fn ellipse<A>(&mut self,
center: Vector2F, center: Vector2F,
axes: Vector2F, axes: A,
rotation: f32, rotation: f32,
start_angle: f32, start_angle: f32,
end_angle: f32) { end_angle: f32)
where A: IntoVector2F {
self.flush_current_contour(); self.flush_current_contour();
let transform = Transform2F::from_scale(axes).rotate(rotation).translate(center); let transform = Transform2F::from_scale(axes).rotate(rotation).translate(center);

View File

@ -33,7 +33,7 @@ impl<'a> ContourDilator<'a> {
pub fn dilate(&mut self) { pub fn dilate(&mut self) {
// Determine orientation. // Determine orientation.
let scale = self.amount.scale_xy(match self.orientation { let scale = self.amount * (match self.orientation {
Orientation::Ccw => vec2f( 1.0, -1.0), Orientation::Ccw => vec2f( 1.0, -1.0),
Orientation::Cw => vec2f(-1.0, 1.0), Orientation::Cw => vec2f(-1.0, 1.0),
}); });
@ -86,7 +86,7 @@ impl<'a> ContourDilator<'a> {
let scaled_bisector = if bisector_length == 0.0 { let scaled_bisector = if bisector_length == 0.0 {
Vector2F::zero() Vector2F::zero()
} else { } else {
bisector.scale_xy(scale).scale(1.0 / bisector_length) bisector * scale * (1.0 / bisector_length)
}; };
let new_position = position - scaled_bisector; let new_position = position - scaled_bisector;

View File

@ -420,7 +420,7 @@ impl Contour {
direction: ArcDirection) { direction: ArcDirection) {
let mut direction_transform = Transform2F::default(); let mut direction_transform = Transform2F::default();
if direction == ArcDirection::CCW { if direction == ArcDirection::CCW {
chord = chord.scale_xy(vec2f(1.0, -1.0)); chord *= vec2f(1.0, -1.0);
direction_transform = Transform2F::from_scale(vec2f(1.0, -1.0)); direction_transform = Transform2F::from_scale(vec2f(1.0, -1.0));
} }

View File

@ -103,7 +103,7 @@ impl Segment {
let p0 = Vector2F::splat(SQRT_2 * 0.5); let p0 = Vector2F::splat(SQRT_2 * 0.5);
let p1 = vec2f(-SQRT_2 / 6.0 + 4.0 / 3.0, 7.0 * SQRT_2 / 6.0 - 4.0 / 3.0); let p1 = vec2f(-SQRT_2 / 6.0 + 4.0 / 3.0, 7.0 * SQRT_2 / 6.0 - 4.0 / 3.0);
let flip = vec2f(1.0, -1.0); let flip = vec2f(1.0, -1.0);
let (p2, p3) = (p1.scale_xy(flip), p0.scale_xy(flip)); let (p2, p3) = (p1 * flip, p0 * flip);
Segment::cubic(LineSegment2F::new(p3, p0), LineSegment2F::new(p2, p1)) Segment::cubic(LineSegment2F::new(p3, p0), LineSegment2F::new(p2, p1))
} }
@ -150,7 +150,7 @@ impl Segment {
let mut new_segment = *self; let mut new_segment = *self;
let p1_2 = self.ctrl.from() + self.ctrl.from(); let p1_2 = self.ctrl.from() + self.ctrl.from();
new_segment.ctrl = LineSegment2F::new(self.baseline.from() + p1_2, new_segment.ctrl = LineSegment2F::new(self.baseline.from() + p1_2,
p1_2 + self.baseline.to()).scale(1.0 / 3.0); p1_2 + self.baseline.to()) * (1.0 / 3.0);
new_segment.kind = SegmentKind::Cubic; new_segment.kind = SegmentKind::Cubic;
new_segment new_segment
} }

View File

@ -16,7 +16,7 @@ use pathfinder_geometry::line_segment::LineSegment2F;
use pathfinder_geometry::rect::RectF; use pathfinder_geometry::rect::RectF;
use pathfinder_geometry::transform2d::Transform2F; use pathfinder_geometry::transform2d::Transform2F;
use pathfinder_geometry::util::EPSILON; use pathfinder_geometry::util::EPSILON;
use pathfinder_geometry::vector::Vector2F; use pathfinder_geometry::vector::{Vector2F, vec2f};
use std::f32; use std::f32;
const TOLERANCE: f32 = 0.01; const TOLERANCE: f32 = 0.01;
@ -139,10 +139,10 @@ impl<'a> OutlineStrokeToFill<'a> {
LineCap::Butt => unreachable!(), LineCap::Butt => unreachable!(),
LineCap::Square => { LineCap::Square => {
let offset = gradient.scale(width * 0.5); let offset = gradient * (width * 0.5);
let p2 = p1 + offset; let p2 = p1 + offset;
let p3 = p2 + gradient.yx().scale_xy(Vector2F::new(-width, width)); let p3 = p2 + gradient.yx() * vec2f(-width, width);
let p4 = p3 - offset; let p4 = p3 - offset;
contour.push_endpoint(p2); contour.push_endpoint(p2);
@ -151,9 +151,9 @@ impl<'a> OutlineStrokeToFill<'a> {
} }
LineCap::Round => { LineCap::Round => {
let scale = Vector2F::splat(width * 0.5); let scale = width * 0.5;
let offset = gradient.yx().scale_xy(Vector2F::new(-1.0, 1.0)); let offset = gradient.yx() * vec2f(-1.0, 1.0);
let translation = p1 + offset.scale(width * 0.5); let translation = p1 + offset * (width * 0.5);
let transform = Transform2F::from_scale(scale).translate(translation); let transform = Transform2F::from_scale(scale).translate(translation);
let chord = LineSegment2F::new(-offset, offset); let chord = LineSegment2F::new(-offset, offset);
contour.push_arc_from_unit_chord(&transform, chord, ArcDirection::CW); contour.push_arc_from_unit_chord(&transform, chord, ArcDirection::CW);
@ -395,7 +395,7 @@ impl Contour {
} }
} }
LineJoin::Round => { LineJoin::Round => {
let scale = Vector2F::splat(distance.abs()); let scale = distance.abs();
let transform = Transform2F::from_scale(scale).translate(join_point); let transform = Transform2F::from_scale(scale).translate(join_point);
let chord_from = (prev_tangent.to() - join_point).normalize(); let chord_from = (prev_tangent.to() - join_point).normalize();
let chord_to = (next_tangent.to() - join_point).normalize(); let chord_to = (next_tangent.to() - join_point).normalize();

View File

@ -53,10 +53,10 @@ impl Camera {
} }
fn new_2d(view_box: RectF, viewport_size: Vector2I) -> Camera { fn new_2d(view_box: RectF, viewport_size: Vector2I) -> Camera {
let scale = i32::min(viewport_size.x(), viewport_size.y()) as f32 let scale = i32::min(viewport_size.x(), viewport_size.y()) as f32 *
* scale_factor_for_view_box(view_box); scale_factor_for_view_box(view_box);
let origin = viewport_size.to_f32().scale(0.5) - view_box.size().scale(scale * 0.5); let origin = viewport_size.to_f32() * 0.5 - view_box.size() * (scale * 0.5);
Camera::TwoD(Transform2F::from_uniform_scale(scale).translate(origin)) Camera::TwoD(Transform2F::from_scale(scale).translate(origin))
} }
fn new_3d(mode: Mode, view_box: RectF, viewport_size: Vector2I) -> Camera { fn new_3d(mode: Mode, view_box: RectF, viewport_size: Vector2I) -> Camera {

View File

@ -255,8 +255,7 @@ impl<W> DemoApp<W> where W: Window {
transform: self.render_transform.clone().unwrap(), transform: self.render_transform.clone().unwrap(),
dilation: if self.ui_model.stem_darkening_effect_enabled { dilation: if self.ui_model.stem_darkening_effect_enabled {
let font_size = APPROX_FONT_SIZE * self.window_size.backing_scale_factor; let font_size = APPROX_FONT_SIZE * self.window_size.backing_scale_factor;
let (x, y) = (STEM_DARKENING_FACTORS[0], STEM_DARKENING_FACTORS[1]); vec2f(STEM_DARKENING_FACTORS[0], STEM_DARKENING_FACTORS[1]) * font_size
vec2f(x, y).scale(font_size)
} else { } else {
Vector2F::zero() Vector2F::zero()
}, },
@ -290,15 +289,8 @@ impl<W> DemoApp<W> where W: Window {
} }
Event::MouseMoved(new_position) if self.mouselook_enabled => { Event::MouseMoved(new_position) if self.mouselook_enabled => {
let mouse_position = self.process_mouse_position(new_position); let mouse_position = self.process_mouse_position(new_position);
if let Camera::ThreeD { if let Camera::ThreeD { ref mut modelview_transform, .. } = self.camera {
ref mut modelview_transform, let rotation = mouse_position.relative.to_f32() * MOUSELOOK_ROTATION_SPEED;
..
} = self.camera
{
let rotation = mouse_position
.relative
.to_f32()
.scale(MOUSELOOK_ROTATION_SPEED);
modelview_transform.yaw += rotation.x(); modelview_transform.yaw += rotation.x();
modelview_transform.pitch += rotation.y(); modelview_transform.pitch += rotation.y();
self.dirty = true; self.dirty = true;
@ -312,19 +304,15 @@ impl<W> DemoApp<W> where W: Window {
Event::Zoom(d_dist, position) => { Event::Zoom(d_dist, position) => {
if let Camera::TwoD(ref mut transform) = self.camera { if let Camera::TwoD(ref mut transform) = self.camera {
let backing_scale_factor = self.window_size.backing_scale_factor; let backing_scale_factor = self.window_size.backing_scale_factor;
let position = position.to_f32().scale(backing_scale_factor); let position = position.to_f32() * backing_scale_factor;
let scale_delta = 1.0 + d_dist * CAMERA_SCALE_SPEED_2D; let scale_delta = 1.0 + d_dist * CAMERA_SCALE_SPEED_2D;
*transform = transform.translate(-position) *transform = transform.translate(-position)
.uniform_scale(scale_delta) .scale(scale_delta)
.translate(position); .translate(position);
} }
} }
Event::Look { pitch, yaw } => { Event::Look { pitch, yaw } => {
if let Camera::ThreeD { if let Camera::ThreeD { ref mut modelview_transform, .. } = self.camera {
ref mut modelview_transform,
..
} = self.camera
{
modelview_transform.pitch += pitch; modelview_transform.pitch += pitch;
modelview_transform.yaw += yaw; modelview_transform.yaw += yaw;
} }
@ -470,7 +458,7 @@ impl<W> DemoApp<W> where W: Window {
} }
fn process_mouse_position(&mut self, new_position: Vector2I) -> MousePosition { fn process_mouse_position(&mut self, new_position: Vector2I) -> MousePosition {
let absolute = new_position.scale(self.window_size.backing_scale_factor as i32); let absolute = new_position * self.window_size.backing_scale_factor as i32;
let relative = absolute - self.last_mouse_position; let relative = absolute - self.last_mouse_position;
self.last_mouse_position = absolute; self.last_mouse_position = absolute;
MousePosition { absolute, relative } MousePosition { absolute, relative }
@ -487,10 +475,8 @@ impl<W> DemoApp<W> where W: Window {
self.renderer.debug_ui_presenter.ui_presenter.event_queue.push(*ui_event); self.renderer.debug_ui_presenter.ui_presenter.event_queue.push(*ui_event);
} }
self.renderer.debug_ui_presenter.ui_presenter.mouse_position = self self.renderer.debug_ui_presenter.ui_presenter.mouse_position =
.last_mouse_position self.last_mouse_position.to_f32() * self.window_size.backing_scale_factor;
.to_f32()
.scale(self.window_size.backing_scale_factor);
let mut ui_action = UIAction::None; let mut ui_action = UIAction::None;
if self.options.ui == UIVisibility::All { if self.options.ui == UIVisibility::All {
@ -605,7 +591,7 @@ impl<W> DemoApp<W> where W: Window {
} }
UIAction::ZoomIn => { UIAction::ZoomIn => {
if let Camera::TwoD(ref mut transform) = self.camera { if let Camera::TwoD(ref mut transform) = self.camera {
let scale = Vector2F::splat(1.0 + CAMERA_ZOOM_AMOUNT_2D); let scale = 1.0 + CAMERA_ZOOM_AMOUNT_2D;
let center = center_of_window(&self.window_size); let center = center_of_window(&self.window_size);
*transform = transform.translate(-center).scale(scale).translate(center); *transform = transform.translate(-center).scale(scale).translate(center);
self.dirty = true; self.dirty = true;
@ -613,7 +599,7 @@ impl<W> DemoApp<W> where W: Window {
} }
UIAction::ZoomOut => { UIAction::ZoomOut => {
if let Camera::TwoD(ref mut transform) = self.camera { if let Camera::TwoD(ref mut transform) = self.camera {
let scale = Vector2F::splat(1.0 - CAMERA_ZOOM_AMOUNT_2D); let scale = 1.0 - CAMERA_ZOOM_AMOUNT_2D;
let center = center_of_window(&self.window_size); let center = center_of_window(&self.window_size);
*transform = transform.translate(-center).scale(scale).translate(center); *transform = transform.translate(-center).scale(scale).translate(center);
self.dirty = true; self.dirty = true;
@ -779,7 +765,7 @@ fn build_svg_tree(tree: &Tree, viewport_size: Vector2I, effects: Option<Effects>
_ => vec2i(1, 1), _ => vec2i(1, 1),
}; };
let name = "Text".to_owned(); let name = "Text".to_owned();
let render_target = RenderTarget::new(viewport_size.scale_xy(scale), name); let render_target = RenderTarget::new(viewport_size * scale, name);
Some(scene.push_render_target(render_target)) Some(scene.push_render_target(render_target))
} }
}; };
@ -794,7 +780,7 @@ fn build_svg_tree(tree: &Tree, viewport_size: Vector2I, effects: Option<Effects>
} }
fn center_of_window(window_size: &WindowSize) -> Vector2F { fn center_of_window(window_size: &WindowSize) -> Vector2F {
window_size.device_size().to_f32().scale(0.5) window_size.device_size().to_f32() * 0.5
} }
fn get_svg_building_message(built_svg: &BuiltSVG) -> String { fn get_svg_building_message(built_svg: &BuiltSVG) -> String {

View File

@ -10,9 +10,9 @@
//! A minimal cross-platform windowing layer. //! A minimal cross-platform windowing layer.
use pathfinder_geometry::vector::Vector2I;
use pathfinder_geometry::rect::RectI; use pathfinder_geometry::rect::RectI;
use pathfinder_geometry::transform3d::{Perspective, Transform4F}; use pathfinder_geometry::transform3d::{Perspective, Transform4F};
use pathfinder_geometry::vector::Vector2I;
use pathfinder_resources::ResourceLoader; use pathfinder_resources::ResourceLoader;
use rayon::ThreadPoolBuilder; use rayon::ThreadPoolBuilder;
use std::path::PathBuf; use std::path::PathBuf;
@ -90,10 +90,7 @@ pub struct WindowSize {
impl WindowSize { impl WindowSize {
#[inline] #[inline]
pub fn device_size(&self) -> Vector2I { pub fn device_size(&self) -> Vector2I {
self.logical_size (self.logical_size.to_f32() * self.backing_scale_factor).to_i32()
.to_f32()
.scale(self.backing_scale_factor)
.to_i32()
} }
} }

View File

@ -218,7 +218,7 @@ pub unsafe extern "C" fn magicleap_pathfinder_render(pf: *mut c_void, options: *
let scale = i32::min(viewport_size.x(), viewport_size.y()) as f32 / let scale = i32::min(viewport_size.x(), viewport_size.y()) as f32 /
f32::max(svg.scene.bounds().size().x(), svg.scene.bounds().size().y()); f32::max(svg.scene.bounds().size().x(), svg.scene.bounds().size().y());
let transform = Transform2F::from_translation(svg.scene.bounds().size().scale(-0.5)) let transform = Transform2F::from_translation(svg.scene.bounds().size().scale(-0.5))
.post_mul(&Transform2F::from_scale(Vector2F::splat(scale))) .post_mul(&Transform2F::from_scale(scale))
.post_mul(&Transform2F::from_translation(viewport_size.to_f32().scale(0.5))); .post_mul(&Transform2F::from_translation(viewport_size.to_f32().scale(0.5)));
let render_options = RenderOptions { let render_options = RenderOptions {

View File

@ -18,7 +18,7 @@ use glutin::window::WindowBuilder;
use pathfinder_canvas::{CanvasFontContext, CanvasRenderingContext2D, Path2D}; use pathfinder_canvas::{CanvasFontContext, CanvasRenderingContext2D, Path2D};
use pathfinder_color::ColorF; use pathfinder_color::ColorF;
use pathfinder_geometry::rect::RectF; use pathfinder_geometry::rect::RectF;
use pathfinder_geometry::vector::{Vector2F, Vector2I, vec2f, vec2i}; use pathfinder_geometry::vector::{vec2f, vec2i};
use pathfinder_gl::{GLDevice, GLVersion}; use pathfinder_gl::{GLDevice, GLVersion};
use pathfinder_resources::fs::FilesystemResourceLoader; use pathfinder_resources::fs::FilesystemResourceLoader;
use pathfinder_renderer::concurrent::rayon::RayonExecutor; use pathfinder_renderer::concurrent::rayon::RayonExecutor;

View File

@ -119,9 +119,9 @@ impl MoireRenderer {
let foreground_color = self.colors.sample(color_time + 0.5); let foreground_color = self.colors.sample(color_time + 0.5);
// Calculate outer and inner circle centers (circle and Leminscate of Gerono respectively). // Calculate outer and inner circle centers (circle and Leminscate of Gerono respectively).
let window_center = self.window_size.to_f32().scale(0.5); let window_center = self.window_size.to_f32() * 0.5;
let outer_center = window_center + vec2f(sin_time, cos_time).scale(OUTER_RADIUS); let outer_center = window_center + vec2f(sin_time, cos_time) * OUTER_RADIUS;
let inner_center = window_center + vec2f(1.0, sin_time).scale(cos_time * INNER_RADIUS); let inner_center = window_center + vec2f(1.0, sin_time) * (cos_time * INNER_RADIUS);
// Clear to background color. // Clear to background color.
self.renderer.set_options(RendererOptions { background_color: Some(background_color) }); self.renderer.set_options(RendererOptions { background_color: Some(background_color) });
@ -144,12 +144,12 @@ impl MoireRenderer {
self.frame += 1; self.frame += 1;
} }
fn draw_circles(&self, canvas: &mut CanvasRenderingContext2D, center: Vector2F) { fn draw_circles(&self, canvas: &mut CanvasRenderingContext2D, mut center: Vector2F) {
let center = center.scale(self.device_pixel_ratio); center *= self.device_pixel_ratio;
for index in 0..CIRCLE_COUNT { for index in 0..CIRCLE_COUNT {
let radius = (index + 1) as f32 * CIRCLE_SPACING * self.device_pixel_ratio; let radius = (index + 1) as f32 * CIRCLE_SPACING * self.device_pixel_ratio;
let mut path = Path2D::new(); let mut path = Path2D::new();
path.ellipse(center, Vector2F::splat(radius), 0.0, 0.0, PI * 2.0); path.ellipse(center, radius, 0.0, 0.0, PI * 2.0);
canvas.stroke_path(path); canvas.stroke_path(path);
} }
} }

View File

@ -66,8 +66,7 @@ fn render_demo(canvas: &mut CanvasRenderingContext2D,
time); time);
draw_paragraph(canvas, RectF::new(vec2f(window_size.x() - 450.0, 50.0), vec2f(150.0, 100.0))); draw_paragraph(canvas, RectF::new(vec2f(window_size.x() - 450.0, 50.0), vec2f(150.0, 100.0)));
draw_graph(canvas, draw_graph(canvas,
RectF::new(window_size.scale_xy(vec2f(0.0, 0.5)), RectF::new(window_size * vec2f(0.0, 0.5), window_size * vec2f(1.0, 0.5)),
window_size.scale_xy(vec2f(1.0, 0.5))),
time); time);
draw_color_wheel(canvas, draw_color_wheel(canvas,
RectF::new(window_size - vec2f(300.0, 300.0), vec2f(250.0, 250.0)), RectF::new(window_size - vec2f(300.0, 300.0), vec2f(250.0, 250.0)),
@ -130,7 +129,7 @@ fn draw_eyes(canvas: &mut CanvasRenderingContext2D,
rect: RectF, rect: RectF,
mouse_position: Vector2F, mouse_position: Vector2F,
time: f32) { time: f32) {
let eyes_radii = rect.size().scale_xy(vec2f(0.23, 0.5)); let eyes_radii = rect.size() * vec2f(0.23, 0.5);
let eyes_left_position = rect.origin() + eyes_radii; let eyes_left_position = rect.origin() + eyes_radii;
let eyes_right_position = rect.origin() + vec2f(rect.width() - eyes_radii.x(), eyes_radii.y()); let eyes_right_position = rect.origin() + vec2f(rect.width() - eyes_radii.x(), eyes_radii.y());
let eyes_center = f32::min(eyes_radii.x(), eyes_radii.y()) * 0.5; let eyes_center = f32::min(eyes_radii.x(), eyes_radii.y()) * 0.5;
@ -138,7 +137,7 @@ fn draw_eyes(canvas: &mut CanvasRenderingContext2D,
let mut gradient = Gradient::linear( let mut gradient = Gradient::linear(
LineSegment2F::new(vec2f(0.0, rect.height() * 0.5), LineSegment2F::new(vec2f(0.0, rect.height() * 0.5),
rect.size().scale_xy(vec2f(0.1, 1.0))) + rect.origin()); rect.size() * vec2f(0.1, 1.0)) + rect.origin());
gradient.add_color_stop(rgbau(0, 0, 0, 32), 0.0); gradient.add_color_stop(rgbau(0, 0, 0, 32), 0.0);
gradient.add_color_stop(rgbau(0, 0, 0, 16), 1.0); gradient.add_color_stop(rgbau(0, 0, 0, 16), 1.0);
let mut path = Path2D::new(); let mut path = Path2D::new();
@ -147,9 +146,9 @@ fn draw_eyes(canvas: &mut CanvasRenderingContext2D,
canvas.set_fill_style(gradient); canvas.set_fill_style(gradient);
canvas.fill_path(path, FillRule::Winding); canvas.fill_path(path, FillRule::Winding);
let mut gradient = Gradient::linear( let mut gradient =
LineSegment2F::new(vec2f(0.0, rect.height() * 0.25), Gradient::linear(LineSegment2F::new(vec2f(0.0, rect.height() * 0.25),
rect.size().scale_xy(vec2f(0.1, 1.0))) + rect.origin()); rect.size() * vec2f(0.1, 1.0)) + rect.origin());
gradient.add_color_stop(rgbu(220, 220, 220), 0.0); gradient.add_color_stop(rgbu(220, 220, 220), 0.0);
gradient.add_color_stop(rgbu(128, 128, 128), 1.0); gradient.add_color_stop(rgbu(128, 128, 128), 1.0);
let mut path = Path2D::new(); let mut path = Path2D::new();
@ -158,12 +157,12 @@ fn draw_eyes(canvas: &mut CanvasRenderingContext2D,
canvas.set_fill_style(gradient); canvas.set_fill_style(gradient);
canvas.fill_path(path, FillRule::Winding); canvas.fill_path(path, FillRule::Winding);
let mut delta = (mouse_position - eyes_right_position) / eyes_radii.scale(10.0); let mut delta = (mouse_position - eyes_right_position) / (eyes_radii * 10.0);
let distance = delta.length(); let distance = delta.length();
if distance > 1.0 { if distance > 1.0 {
delta = delta.scale(1.0 / distance); delta *= 1.0 / distance;
} }
delta = delta.scale_xy(eyes_radii).scale_xy(vec2f(0.4, 0.5)); delta *= eyes_radii * vec2f(0.4, 0.5);
let mut path = Path2D::new(); let mut path = Path2D::new();
path.ellipse(eyes_left_position + delta + vec2f(0.0, eyes_radii.y() * 0.25 * (1.0 - blink)), path.ellipse(eyes_left_position + delta + vec2f(0.0, eyes_radii.y() * 0.25 * (1.0 - blink)),
vec2f(eyes_center, eyes_center * blink), vec2f(eyes_center, eyes_center * blink),
@ -178,7 +177,7 @@ fn draw_eyes(canvas: &mut CanvasRenderingContext2D,
canvas.set_fill_style(rgbu(32, 32, 32)); canvas.set_fill_style(rgbu(32, 32, 32));
canvas.fill_path(path, FillRule::Winding); canvas.fill_path(path, FillRule::Winding);
let gloss_position = eyes_left_position - eyes_radii.scale_xy(vec2f(0.25, 0.5)); let gloss_position = eyes_left_position - eyes_radii * vec2f(0.25, 0.5);
let gloss_radii = F32x2::new(0.1, 0.75) * F32x2::splat(eyes_radii.x()); let gloss_radii = F32x2::new(0.1, 0.75) * F32x2::splat(eyes_radii.x());
let mut gloss = Gradient::radial(gloss_position, gloss_radii); let mut gloss = Gradient::radial(gloss_position, gloss_radii);
gloss.add_color_stop(rgbau(255, 255, 255, 128), 0.0); gloss.add_color_stop(rgbau(255, 255, 255, 128), 0.0);
@ -188,7 +187,7 @@ fn draw_eyes(canvas: &mut CanvasRenderingContext2D,
path.ellipse(eyes_left_position, eyes_radii, 0.0, 0.0, PI_2); path.ellipse(eyes_left_position, eyes_radii, 0.0, 0.0, PI_2);
canvas.fill_path(path, FillRule::Winding); canvas.fill_path(path, FillRule::Winding);
let gloss_position = eyes_right_position - eyes_radii.scale_xy(vec2f(0.25, 0.5)); let gloss_position = eyes_right_position - eyes_radii * vec2f(0.25, 0.5);
let mut gloss = Gradient::radial(gloss_position, gloss_radii); let mut gloss = Gradient::radial(gloss_position, gloss_radii);
gloss.add_color_stop(rgbau(255, 255, 255, 128), 0.0); gloss.add_color_stop(rgbau(255, 255, 255, 128), 0.0);
gloss.add_color_stop(rgbau(255, 255, 255, 0), 1.0); gloss.add_color_stop(rgbau(255, 255, 255, 0), 1.0);
@ -263,7 +262,7 @@ fn draw_graph(canvas: &mut CanvasRenderingContext2D, rect: RectF, time: f32) {
let sample_points: ArrayVec<[Vector2F; 6]> = samples.iter() let sample_points: ArrayVec<[Vector2F; 6]> = samples.iter()
.enumerate() .enumerate()
.map(|(index, &sample)| { .map(|(index, &sample)| {
rect.origin() + vec2f(index as f32, sample).scale_xy(sample_scale) rect.origin() + vec2f(index as f32, sample) * sample_scale
}).collect(); }).collect();
// Draw graph background. // Draw graph background.
@ -336,7 +335,7 @@ fn draw_color_wheel(canvas: &mut CanvasRenderingContext2D, rect: RectF, time: f3
let line = LineSegment2F::new(vec2f(f32::cos(start_angle), f32::sin(start_angle)), let line = LineSegment2F::new(vec2f(f32::cos(start_angle), f32::sin(start_angle)),
vec2f(f32::cos(end_angle), f32::sin(end_angle))); vec2f(f32::cos(end_angle), f32::sin(end_angle)));
let scale = util::lerp(inner_radius, outer_radius, 0.5); let scale = util::lerp(inner_radius, outer_radius, 0.5);
let mut gradient = Gradient::linear(line.scale(scale) + center); let mut gradient = Gradient::linear(line * scale + center);
let start_color = ColorF::from_hsl(start_angle, 1.0, 0.55).to_u8(); let start_color = ColorF::from_hsl(start_angle, 1.0, 0.55).to_u8();
let end_color = ColorF::from_hsl(end_angle, 1.0, 0.55).to_u8(); let end_color = ColorF::from_hsl(end_angle, 1.0, 0.55).to_u8();
gradient.add_color_stop(start_color, 0.0); gradient.add_color_stop(start_color, 0.0);
@ -353,8 +352,8 @@ fn draw_color_wheel(canvas: &mut CanvasRenderingContext2D, rect: RectF, time: f3
canvas.set_stroke_style(rgbau(0, 0, 0, 64)); canvas.set_stroke_style(rgbau(0, 0, 0, 64));
canvas.set_line_width(1.0); canvas.set_line_width(1.0);
let mut path = Path2D::new(); let mut path = Path2D::new();
path.ellipse(center, Vector2F::splat(inner_radius - 0.5), 0.0, 0.0, PI_2); path.ellipse(center, inner_radius - 0.5, 0.0, 0.0, PI_2);
path.ellipse(center, Vector2F::splat(outer_radius + 0.5), 0.0, 0.0, PI_2); path.ellipse(center, outer_radius + 0.5, 0.0, 0.0, PI_2);
canvas.stroke_path(path); canvas.stroke_path(path);
// Prepare to draw the selector. // Prepare to draw the selector.
@ -374,9 +373,8 @@ fn draw_color_wheel(canvas: &mut CanvasRenderingContext2D, rect: RectF, time: f3
// Draw center triangle. // Draw center triangle.
let triangle_radius = inner_radius - 6.0; let triangle_radius = inner_radius - 6.0;
let triangle_vertex_a = vec2f(triangle_radius, 0.0); let triangle_vertex_a = vec2f(triangle_radius, 0.0);
let triangle_vertex_b = vec2f(FRAC_PI_2_3.cos(), FRAC_PI_2_3.sin()).scale(triangle_radius); let triangle_vertex_b = vec2f(FRAC_PI_2_3.cos(), FRAC_PI_2_3.sin()) * triangle_radius;
let triangle_vertex_c = vec2f((-FRAC_PI_2_3).cos(), let triangle_vertex_c = vec2f((-FRAC_PI_2_3).cos(), (-FRAC_PI_2_3).sin()) * triangle_radius;
(-FRAC_PI_2_3).sin()).scale(triangle_radius);
let mut gradient_0 = Gradient::linear_from_points(triangle_vertex_a, triangle_vertex_b); let mut gradient_0 = Gradient::linear_from_points(triangle_vertex_a, triangle_vertex_b);
gradient_0.add_color_stop(ColorF::from_hsl(hue, 1.0, 0.5).to_u8(), 0.0); gradient_0.add_color_stop(ColorF::from_hsl(hue, 1.0, 0.5).to_u8(), 0.0);
gradient_0.add_color_stop(ColorU::white(), 1.0); gradient_0.add_color_stop(ColorU::white(), 1.0);
@ -398,9 +396,8 @@ fn draw_color_wheel(canvas: &mut CanvasRenderingContext2D, rect: RectF, time: f3
canvas.stroke_path(path); canvas.stroke_path(path);
// Stroke the selection circle on the triangle. // Stroke the selection circle on the triangle.
let selection_circle_center = let selection_circle_center = vec2f(FRAC_PI_2_3.cos(), FRAC_PI_2_3.sin()) * triangle_radius *
vec2f(FRAC_PI_2_3.cos(), FRAC_PI_2_3.sin()).scale(triangle_radius) vec2f(0.3, 0.4);
.scale_xy(vec2f(0.3, 0.4));
canvas.set_stroke_style(rgbau(255, 255, 255, 192)); canvas.set_stroke_style(rgbau(255, 255, 255, 192));
canvas.set_line_width(2.0); canvas.set_line_width(2.0);
let mut path = Path2D::new(); let mut path = Path2D::new();
@ -442,9 +439,9 @@ fn draw_lines(canvas: &mut CanvasRenderingContext2D, rect: RectF, time: f32) {
LineJoin::Miter, LineJoin::Round, LineJoin::Bevel LineJoin::Miter, LineJoin::Round, LineJoin::Bevel
].iter().enumerate() { ].iter().enumerate() {
let origin = rect.origin() + let origin = rect.origin() +
vec2f(spacing, -spacing).scale(0.5) + vec2f(0.5, -0.5) * spacing +
vec2f((cap_index * 3 + join_index) as f32 / 9.0 * rect.width(), 0.0) + vec2f((cap_index * 3 + join_index) as f32 / 9.0 * rect.width(), 0.0) +
vec2f(PADDING, PADDING); PADDING;
canvas.set_line_cap(cap); canvas.set_line_cap(cap);
canvas.set_line_join(join); canvas.set_line_join(join);
@ -584,7 +581,7 @@ fn draw_search_box(canvas: &mut CanvasRenderingContext2D, text: &str, rect: Rect
canvas.set_fill_style(rgbau(255, 255, 255, 64)); canvas.set_fill_style(rgbau(255, 255, 255, 64));
canvas.set_text_align(TextAlign::Left); canvas.set_text_align(TextAlign::Left);
canvas.set_text_baseline(TextBaseline::Middle); canvas.set_text_baseline(TextBaseline::Middle);
canvas.fill_text(text, rect.origin() + Vector2F::splat(rect.height()) * vec2f(1.05, 0.5)); canvas.fill_text(text, rect.origin() + vec2f(1.05, 0.5) * rect.height());
} }
fn draw_dropdown(canvas: &mut CanvasRenderingContext2D, text: &str, rect: RectF) { fn draw_dropdown(canvas: &mut CanvasRenderingContext2D, text: &str, rect: RectF) {
@ -606,7 +603,7 @@ fn draw_dropdown(canvas: &mut CanvasRenderingContext2D, text: &str, rect: RectF)
canvas.set_fill_style(rgbau(255, 255, 255, 160)); canvas.set_fill_style(rgbau(255, 255, 255, 160));
canvas.set_text_align(TextAlign::Left); canvas.set_text_align(TextAlign::Left);
canvas.set_text_baseline(TextBaseline::Middle); canvas.set_text_baseline(TextBaseline::Middle);
canvas.fill_text(text, rect.origin() + Vector2F::splat(rect.height()) * vec2f(0.3, 0.5)); canvas.fill_text(text, rect.origin() + vec2f(0.3, 0.5) * rect.height());
} }
fn draw_label(canvas: &mut CanvasRenderingContext2D, text: &str, rect: RectF) { fn draw_label(canvas: &mut CanvasRenderingContext2D, text: &str, rect: RectF) {
@ -644,7 +641,7 @@ fn draw_text_edit_box(canvas: &mut CanvasRenderingContext2D, text: &str, rect: R
canvas.set_fill_style(rgbau(255, 255, 255, 64)); canvas.set_fill_style(rgbau(255, 255, 255, 64));
canvas.set_text_align(TextAlign::Left); canvas.set_text_align(TextAlign::Left);
canvas.set_text_baseline(TextBaseline::Middle); canvas.set_text_baseline(TextBaseline::Middle);
canvas.fill_text(text, rect.origin() + Vector2F::splat(rect.height()) * vec2f(0.3, 0.5)); canvas.fill_text(text, rect.origin() + vec2f(0.3, 0.5) * rect.height());
} }
fn draw_numeric_edit_box(canvas: &mut CanvasRenderingContext2D, fn draw_numeric_edit_box(canvas: &mut CanvasRenderingContext2D,
@ -660,7 +657,7 @@ fn draw_numeric_edit_box(canvas: &mut CanvasRenderingContext2D,
canvas.set_fill_style(rgbau(255, 255, 255, 64)); canvas.set_fill_style(rgbau(255, 255, 255, 64));
canvas.set_text_align(TextAlign::Right); canvas.set_text_align(TextAlign::Right);
canvas.set_text_baseline(TextBaseline::Middle); canvas.set_text_baseline(TextBaseline::Middle);
canvas.fill_text(unit, rect.upper_right() + vec2f(-0.3, 0.5) * Vector2F::splat(rect.height())); canvas.fill_text(unit, rect.upper_right() + vec2f(-0.3, 0.5) * rect.height());
canvas.set_font_size(17.0); canvas.set_font_size(17.0);
canvas.set_fill_style(rgbau(255, 255, 255, 128)); canvas.set_fill_style(rgbau(255, 255, 255, 128));
@ -681,7 +678,7 @@ fn draw_check_box(canvas: &mut CanvasRenderingContext2D, text: &str, rect: RectF
canvas.fill_text(text, rect.origin() + vec2f(28.0, rect.height() * 0.5)); canvas.fill_text(text, rect.origin() + vec2f(28.0, rect.height() * 0.5));
let check_box_rect = RectF::new(vec2f(rect.origin_x(), rect.center().y().floor() - 9.0), let check_box_rect = RectF::new(vec2f(rect.origin_x(), rect.center().y().floor() - 9.0),
vec2f(20.0, 20.0)).contract(Vector2F::splat(1.0)); vec2f(20.0, 20.0)).contract(1.0);
fill_path_with_box_gradient(canvas, fill_path_with_box_gradient(canvas,
create_rounded_rect_path(check_box_rect, CORNER_RADIUS), create_rounded_rect_path(check_box_rect, CORNER_RADIUS),
FillRule::Winding, FillRule::Winding,
@ -754,9 +751,8 @@ fn draw_slider(canvas: &mut CanvasRenderingContext2D, value: f32, rect: RectF) {
background_gradient.add_color_stop(rgbau(0, 0, 0, 0), 1.0); background_gradient.add_color_stop(rgbau(0, 0, 0, 0), 1.0);
canvas.set_fill_style(background_gradient); canvas.set_fill_style(background_gradient);
let mut path = Path2D::new(); let mut path = Path2D::new();
path.rect(RectF::new(knob_position, path.rect(RectF::new(knob_position, Vector2F::zero()).dilate(knob_radius + 5.0));
Vector2F::zero()).dilate(Vector2F::splat(knob_radius + 5.0))); path.ellipse(knob_position, knob_radius, 0.0, 0.0, PI_2);
path.ellipse(knob_position, Vector2F::splat(knob_radius), 0.0, 0.0, PI_2);
canvas.fill_path(path, FillRule::EvenOdd); canvas.fill_path(path, FillRule::EvenOdd);
// Fill knob. // Fill knob.
@ -766,7 +762,7 @@ fn draw_slider(canvas: &mut CanvasRenderingContext2D, value: f32, rect: RectF) {
background_gradient.add_color_stop(rgbau(255, 255, 255, 16), 0.0); background_gradient.add_color_stop(rgbau(255, 255, 255, 16), 0.0);
background_gradient.add_color_stop(rgbau(0, 0, 0, 16), 1.0); background_gradient.add_color_stop(rgbau(0, 0, 0, 16), 1.0);
let mut path = Path2D::new(); let mut path = Path2D::new();
path.ellipse(knob_position, Vector2F::splat(knob_radius - 1.0), 0.0, 0.0, PI_2); path.ellipse(knob_position, knob_radius - 1.0, 0.0, 0.0, PI_2);
canvas.set_fill_style(rgbu(40, 43, 48)); canvas.set_fill_style(rgbu(40, 43, 48));
canvas.fill_path(path.clone(), FillRule::Winding); canvas.fill_path(path.clone(), FillRule::Winding);
canvas.set_fill_style(background_gradient); canvas.set_fill_style(background_gradient);
@ -774,7 +770,7 @@ fn draw_slider(canvas: &mut CanvasRenderingContext2D, value: f32, rect: RectF) {
// Outline knob. // Outline knob.
let mut path = Path2D::new(); let mut path = Path2D::new();
path.ellipse(knob_position, Vector2F::splat(knob_radius - 0.5), 0.0, 0.0, PI_2); path.ellipse(knob_position, knob_radius - 0.5, 0.0, 0.0, PI_2);
canvas.set_stroke_style(rgbau(0, 0, 0, 92)); canvas.set_stroke_style(rgbau(0, 0, 0, 92));
canvas.stroke_path(path); canvas.stroke_path(path);
@ -831,8 +827,7 @@ fn draw_thumbnails(canvas: &mut CanvasRenderingContext2D,
for image_index in 0..image_count { for image_index in 0..image_count {
let image_origin = rect.origin() + vec2f(10.0, 10.0) + let image_origin = rect.origin() + vec2f(10.0, 10.0) +
vec2i(image_index as i32 % 2, image_index as i32 / 2).to_f32() vec2i(image_index as i32 % 2, image_index as i32 / 2).to_f32() * (THUMB_HEIGHT + 10.0);
.scale(THUMB_HEIGHT + 10.0);
let image_rect = RectF::new(image_origin, Vector2F::splat(THUMB_HEIGHT)); let image_rect = RectF::new(image_origin, Vector2F::splat(THUMB_HEIGHT));
let image_y = image_index as f32 * image_y_scale; let image_y = image_index as f32 * image_y_scale;
@ -845,8 +840,8 @@ fn draw_thumbnails(canvas: &mut CanvasRenderingContext2D,
let pattern_transform = Transform2F::from_translation( let pattern_transform = Transform2F::from_translation(
image_rect.origin() - vec2i( image_rect.origin() - vec2i(
(image_index % IMAGES_ACROSS) as i32, (image_index % IMAGES_ACROSS) as i32,
(image_index / IMAGES_ACROSS) as i32).to_f32().scale(THUMB_HEIGHT)) * (image_index / IMAGES_ACROSS) as i32).to_f32() * THUMB_HEIGHT) *
Transform2F::from_scale(vec2f(0.5, 0.5)); Transform2F::from_scale(0.5);
let pattern = Pattern::new(PatternSource::Image((*image).clone()), let pattern = Pattern::new(PatternSource::Image((*image).clone()),
pattern_transform, pattern_transform,
PatternFlags::empty()); PatternFlags::empty());
@ -863,7 +858,7 @@ fn draw_thumbnails(canvas: &mut CanvasRenderingContext2D,
canvas, canvas,
shadow_path, shadow_path,
FillRule::EvenOdd, FillRule::EvenOdd,
image_rect.dilate(Vector2F::splat(1.0)) + vec2f(0.0, 1.0), image_rect.dilate(1.0) + vec2f(0.0, 1.0),
5.0, 5.0,
3.0, 3.0,
rgbau(0, 0, 0, 128), rgbau(0, 0, 0, 128),
@ -871,7 +866,7 @@ fn draw_thumbnails(canvas: &mut CanvasRenderingContext2D,
*/ */
canvas.set_stroke_style(rgbau(255, 255, 255, 192)); canvas.set_stroke_style(rgbau(255, 255, 255, 192));
canvas.stroke_path(create_rounded_rect_path(image_rect.dilate(Vector2F::splat(0.5)), 3.5)); canvas.stroke_path(create_rounded_rect_path(image_rect.dilate(0.5), 3.5));
} }
canvas.restore(); canvas.restore();
@ -934,8 +929,8 @@ fn draw_spinner(canvas: &mut CanvasRenderingContext2D, center: Vector2F, radius:
path.close_path(); path.close_path();
set_linear_gradient_fill_style( set_linear_gradient_fill_style(
canvas, canvas,
center + vec2f(outer_radius.cos(), outer_radius.sin()).scale(average_radius), center + vec2f(outer_radius.cos(), outer_radius.sin()) * average_radius,
center + vec2f(inner_radius.cos(), inner_radius.sin()).scale(average_radius), center + vec2f(inner_radius.cos(), inner_radius.sin()) * average_radius,
rgbau(0, 0, 0, 0), rgbau(0, 0, 0, 0),
rgbau(0, 0, 0, 128)); rgbau(0, 0, 0, 128));
canvas.fill_path(path, FillRule::Winding); canvas.fill_path(path, FillRule::Winding);
@ -954,8 +949,7 @@ fn fill_path_with_box_gradient(canvas: &mut CanvasRenderingContext2D,
// TODO(pcwalton): Fill the corners with radial gradients. // TODO(pcwalton): Fill the corners with radial gradients.
let window_rect = RectF::new(Vector2F::zero(), vec2i(WINDOW_WIDTH, WINDOW_HEIGHT).to_f32()); let window_rect = RectF::new(Vector2F::zero(), vec2i(WINDOW_WIDTH, WINDOW_HEIGHT).to_f32());
let inner_rect = rect.contract(Vector2F::splat(blur_radius)); let (inner_rect, outer_rect) = (rect.contract(blur_radius), rect.dilate(blur_radius));
let outer_rect = rect.dilate(Vector2F::splat(blur_radius));
canvas.save(); canvas.save();

View File

@ -106,16 +106,15 @@ fn main() {
); );
// Clear to swf stage background color. // Clear to swf stage background color.
let mut scene = Scene::new(); let mut scene = Scene::new();
scene.set_view_box(RectF::new( scene.set_view_box(RectF::new(Vector2F::zero(),
Vector2F::zero(), vec2f(stage.width() as f32,
vec2f(stage.width() as f32, stage.height() as f32).scale(device_pixel_ratio) stage.height() as f32) * device_pixel_ratio));
));
draw_paths_into_scene(&library, &mut scene); draw_paths_into_scene(&library, &mut scene);
// Render the canvas to screen. // Render the canvas to screen.
let scene = SceneProxy::from_scene(scene, RayonExecutor); let scene = SceneProxy::from_scene(scene, RayonExecutor);
let mut build_options = BuildOptions::default(); let mut build_options = BuildOptions::default();
let scale_transform = Transform2F::from_scale(Vector2F::splat(device_pixel_ratio)); let scale_transform = Transform2F::from_scale(device_pixel_ratio);
build_options.transform = RenderTransform::Transform2D(scale_transform); build_options.transform = RenderTransform::Transform2D(scale_transform);
scene.build_and_render(&mut renderer, build_options); scene.build_and_render(&mut renderer, build_options);

View File

@ -100,8 +100,8 @@ fn export_pdf<W: Write>(scene: &Scene, writer: &mut W) -> io::Result<()> {
let current = segment.baseline.from(); let current = segment.baseline.from();
let c = segment.ctrl.from(); let c = segment.ctrl.from();
let p = segment.baseline.to(); let p = segment.baseline.to();
let c1 = Vector2F::splat(2./3.) * c + Vector2F::splat(1./3.) * current; let c1 = c * (2.0 / 3.0) + current * (1.0 / 3.0);
let c2 = Vector2F::splat(2./3.) * c + Vector2F::splat(1./3.) * p; let c2 = c * (2.0 / 3.0) + p * (1.0 / 3.0);
pdf.cubic_to(c1, c2, p); pdf.cubic_to(c1, c2, p);
} }
SegmentKind::Cubic => { SegmentKind::Cubic => {
@ -166,8 +166,8 @@ fn export_ps<W: Write>(scene: &Scene, writer: &mut W) -> io::Result<()> {
let current = segment.baseline.from(); let current = segment.baseline.from();
let c = segment.ctrl.from(); let c = segment.ctrl.from();
let p = segment.baseline.to(); let p = segment.baseline.to();
let c1 = Vector2F::splat(2. / 3.) * c + Vector2F::splat(1. / 3.) * current; let c1 = c * (2.0 / 3.0) + current * (1.0 / 3.0);
let c2 = Vector2F::splat(2. / 3.) * c + Vector2F::splat(1. / 3.) * p; let c2 = c * (2.0 / 3.0) + p * (1.0 / 3.0);
writeln!(writer, "{} {} {} curveto", P(c1), P(c2), P(p))?; writeln!(writer, "{} {} {} curveto", P(c1), P(c2), P(p))?;
} }
SegmentKind::Cubic => { SegmentKind::Cubic => {

View File

@ -11,10 +11,10 @@
//! Line segment types, optimized with SIMD. //! Line segment types, optimized with SIMD.
use crate::transform2d::Matrix2x2F; use crate::transform2d::Matrix2x2F;
use crate::vector::Vector2F; use crate::vector::{Vector2F, vec2f};
use crate::util; use crate::util;
use pathfinder_simd::default::F32x4; use pathfinder_simd::default::F32x4;
use std::ops::{Add, Sub}; use std::ops::{Add, Mul, MulAssign, Sub};
#[derive(Clone, Copy, Debug, PartialEq, Default)] #[derive(Clone, Copy, Debug, PartialEq, Default)]
pub struct LineSegment2F(pub F32x4); pub struct LineSegment2F(pub F32x4);
@ -87,21 +87,6 @@ impl LineSegment2F {
self.0[3] = y self.0[3] = y
} }
#[inline]
pub fn translate(self, offset: Vector2F) -> LineSegment2F {
LineSegment2F(self.0 + offset.0.to_f32x4().xyxy())
}
#[inline]
pub fn scale(self, factor: f32) -> LineSegment2F {
LineSegment2F(self.0 * F32x4::splat(factor))
}
#[inline]
pub fn scale_xy(self, factors: Vector2F) -> LineSegment2F {
LineSegment2F(self.0 * factors.0.to_f32x4().xyxy())
}
#[inline] #[inline]
pub fn split(self, t: f32) -> (LineSegment2F, LineSegment2F) { pub fn split(self, t: f32) -> (LineSegment2F, LineSegment2F) {
debug_assert!(t >= 0.0 && t <= 1.0); debug_assert!(t >= 0.0 && t <= 1.0);
@ -239,7 +224,7 @@ impl LineSegment2F {
#[inline] #[inline]
pub fn sample(self, t: f32) -> Vector2F { pub fn sample(self, t: f32) -> Vector2F {
self.from() + self.vector().scale(t) self.from() + self.vector() * t
} }
#[inline] #[inline]
@ -252,7 +237,7 @@ impl LineSegment2F {
if self.is_zero_length() { if self.is_zero_length() {
self self
} else { } else {
self + self.vector().yx().normalize().scale_xy(Vector2F::new(-distance, distance)) self + self.vector().yx().normalize() * vec2f(-distance, distance)
} }
} }
@ -278,6 +263,29 @@ impl Sub<Vector2F> for LineSegment2F {
} }
} }
impl Mul<Vector2F> for LineSegment2F {
type Output = LineSegment2F;
#[inline]
fn mul(self, factors: Vector2F) -> LineSegment2F {
LineSegment2F(self.0 * factors.0.to_f32x4().xyxy())
}
}
impl Mul<f32> for LineSegment2F {
type Output = LineSegment2F;
#[inline]
fn mul(self, factor: f32) -> LineSegment2F {
LineSegment2F(self.0 * F32x4::splat(factor))
}
}
impl MulAssign<Vector2F> for LineSegment2F {
#[inline]
fn mul_assign(&mut self, factors: Vector2F) {
*self = *self * factors
}
}
#[derive(Clone, Copy, Debug, Default)] #[derive(Clone, Copy, Debug, Default)]
#[repr(C)] #[repr(C)]
pub struct LineSegmentU4 { pub struct LineSegmentU4 {

View File

@ -10,9 +10,9 @@
//! 2D axis-aligned rectangles, optimized with SIMD. //! 2D axis-aligned rectangles, optimized with SIMD.
use crate::vector::{Vector2F, Vector2I}; use crate::vector::{IntoVector2F, Vector2F, Vector2I};
use pathfinder_simd::default::{F32x4, I32x4}; use pathfinder_simd::default::{F32x4, I32x4};
use std::ops::Add; use std::ops::{Add, Mul};
#[derive(Clone, Copy, Debug, PartialEq, Default)] #[derive(Clone, Copy, Debug, PartialEq, Default)]
pub struct RectF(pub F32x4); pub struct RectF(pub F32x4);
@ -158,17 +158,7 @@ impl RectF {
#[inline] #[inline]
pub fn center(self) -> Vector2F { pub fn center(self) -> Vector2F {
self.origin() + self.size().scale(0.5) self.origin() + self.size() * 0.5
}
#[inline]
pub fn scale(self, factor: f32) -> RectF {
RectF(self.0 * F32x4::splat(factor))
}
#[inline]
pub fn scale_xy(self, factors: Vector2F) -> RectF {
RectF(self.0 * factors.0.concat_xy_xy(factors.0))
} }
/// Rounds all points to the nearest integer. /// Rounds all points to the nearest integer.
@ -183,12 +173,14 @@ impl RectF {
} }
#[inline] #[inline]
pub fn dilate(self, amount: Vector2F) -> RectF { pub fn dilate<A>(self, amount: A) -> RectF where A: IntoVector2F {
let amount = amount.into_vector_2f();
RectF::from_points(self.origin() - amount, self.lower_right() + amount) RectF::from_points(self.origin() - amount, self.lower_right() + amount)
} }
#[inline] #[inline]
pub fn contract(self, amount: Vector2F) -> RectF { pub fn contract<A>(self, amount: A) -> RectF where A: IntoVector2F {
let amount = amount.into_vector_2f();
RectF::from_points(self.origin() + amount, self.lower_right() - amount) RectF::from_points(self.origin() + amount, self.lower_right() - amount)
} }
@ -206,6 +198,22 @@ impl Add<Vector2F> for RectF {
} }
} }
impl Mul<Vector2F> for RectF {
type Output = RectF;
#[inline]
fn mul(self, factors: Vector2F) -> RectF {
RectF(self.0 * factors.0.concat_xy_xy(factors.0))
}
}
impl Mul<f32> for RectF {
type Output = RectF;
#[inline]
fn mul(self, factor: f32) -> RectF {
RectF(self.0 * F32x4::splat(factor))
}
}
/// NB: The origin is inclusive, while the lower right point is exclusive. /// NB: The origin is inclusive, while the lower right point is exclusive.
#[derive(Clone, Copy, Debug, PartialEq, Default)] #[derive(Clone, Copy, Debug, PartialEq, Default)]
pub struct RectI(pub I32x4); pub struct RectI(pub I32x4);
@ -319,7 +327,7 @@ impl RectI {
#[inline] #[inline]
pub fn contains_point(&self, point: Vector2I) -> bool { pub fn contains_point(&self, point: Vector2I) -> bool {
// self.origin <= point && point <= self.lower_right - 1 // self.origin <= point && point <= self.lower_right - 1
let lower_right = self.lower_right() - Vector2I::splat(1); let lower_right = self.lower_right() - 1;
self.origin() self.origin()
.0 .0
.concat_xy_xy(point.0) .concat_xy_xy(point.0)

View File

@ -14,7 +14,7 @@ use crate::line_segment::LineSegment2F;
use crate::rect::RectF; use crate::rect::RectF;
use crate::transform3d::Transform4F; use crate::transform3d::Transform4F;
use crate::unit_vector::UnitVector; use crate::unit_vector::UnitVector;
use crate::vector::{Vector2F, vec2f}; use crate::vector::{IntoVector2F, Vector2F, vec2f};
use pathfinder_simd::default::F32x4; use pathfinder_simd::default::F32x4;
use std::ops::{Mul, MulAssign, Sub}; use std::ops::{Mul, MulAssign, Sub};
@ -25,13 +25,14 @@ pub struct Matrix2x2F(pub F32x4);
impl Default for Matrix2x2F { impl Default for Matrix2x2F {
#[inline] #[inline]
fn default() -> Matrix2x2F { fn default() -> Matrix2x2F {
Self::from_scale(vec2f(1.0, 1.0)) Self::from_scale(1.0)
} }
} }
impl Matrix2x2F { impl Matrix2x2F {
#[inline] #[inline]
pub fn from_scale(scale: Vector2F) -> Matrix2x2F { pub fn from_scale<S>(scale: S) -> Matrix2x2F where S: IntoVector2F {
let scale = scale.into_vector_2f();
Matrix2x2F(F32x4::new(scale.x(), 0.0, 0.0, scale.y())) Matrix2x2F(F32x4::new(scale.x(), 0.0, 0.0, scale.y()))
} }
@ -137,18 +138,14 @@ impl Default for Transform2F {
impl Transform2F { impl Transform2F {
#[inline] #[inline]
pub fn from_scale(scale: Vector2F) -> Transform2F { pub fn from_scale<S>(scale: S) -> Transform2F where S: IntoVector2F {
let scale = scale.into_vector_2f();
Transform2F { Transform2F {
matrix: Matrix2x2F::from_scale(scale), matrix: Matrix2x2F::from_scale(scale),
vector: Vector2F::zero(), vector: Vector2F::zero(),
} }
} }
#[inline]
pub fn from_uniform_scale(scale: f32) -> Transform2F {
Transform2F::from_scale(Vector2F::splat(scale))
}
#[inline] #[inline]
pub fn from_rotation(theta: f32) -> Transform2F { pub fn from_rotation(theta: f32) -> Transform2F {
Transform2F { Transform2F {
@ -171,11 +168,9 @@ impl Transform2F {
} }
#[inline] #[inline]
pub fn from_scale_rotation_translation( pub fn from_scale_rotation_translation<S>(scale: S, theta: f32, translation: Vector2F)
scale: Vector2F, -> Transform2F where S: IntoVector2F {
theta: f32, let scale = scale.into_vector_2f();
translation: Vector2F,
) -> Transform2F {
let rotation = Transform2F::from_rotation(theta); let rotation = Transform2F::from_rotation(theta);
let translation = Transform2F::from_translation(translation); let translation = Transform2F::from_translation(translation);
Transform2F::from_scale(scale) * rotation * translation Transform2F::from_scale(scale) * rotation * translation
@ -245,15 +240,11 @@ impl Transform2F {
} }
#[inline] #[inline]
pub fn scale(&self, scale: Vector2F) -> Transform2F { pub fn scale<S>(&self, scale: S) -> Transform2F where S: IntoVector2F {
let scale = scale.into_vector_2f();
Transform2F::from_scale(scale) * *self Transform2F::from_scale(scale) * *self
} }
#[inline]
pub fn uniform_scale(&self, scale: f32) -> Transform2F {
self.scale(Vector2F::splat(scale))
}
/// Returns the translation part of this matrix. /// Returns the translation part of this matrix.
/// ///
/// This decomposition assumes that scale, rotation, and translation are applied in that order. /// This decomposition assumes that scale, rotation, and translation are applied in that order.

View File

@ -12,7 +12,7 @@
use crate::rect::RectF; use crate::rect::RectF;
use crate::transform2d::Matrix2x2F; use crate::transform2d::Matrix2x2F;
use crate::vector::{Vector2F, Vector2I, Vector3F, Vector4F, vec2f}; use crate::vector::{Vector2F, Vector2I, Vector3F, Vector4F};
use pathfinder_simd::default::F32x4; use pathfinder_simd::default::F32x4;
use std::ops::{Add, Mul, MulAssign, Neg}; use std::ops::{Add, Mul, MulAssign, Neg};
@ -407,7 +407,7 @@ impl Mul<Vector2F> for Perspective {
#[inline] #[inline]
fn mul(self, vector: Vector2F) -> Vector2F { fn mul(self, vector: Vector2F) -> Vector2F {
let point = (self.transform * vector.to_4d()).to_2d() * Vector2F::new(1.0, -1.0); let point = (self.transform * vector.to_4d()).to_2d() * Vector2F::new(1.0, -1.0);
(point + vec2f(1.0, 1.0)) * self.window_size.to_f32().scale(0.5) (point + 1.0) * self.window_size.to_f32() * 0.5
} }
} }

View File

@ -12,7 +12,7 @@
use pathfinder_simd::default::{F32x2, F32x4, I32x2}; use pathfinder_simd::default::{F32x2, F32x4, I32x2};
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use std::ops::{Add, AddAssign, Div, Mul, Neg, Sub}; use std::ops::{Add, AddAssign, Div, Mul, MulAssign, Neg, Sub};
/// 2D points with 32-bit floating point coordinates. /// 2D points with 32-bit floating point coordinates.
#[derive(Clone, Copy, Debug, Default)] #[derive(Clone, Copy, Debug, Default)]
@ -90,16 +90,6 @@ impl Vector2F {
xy.x() + xy.y() xy.x() + xy.y()
} }
#[inline]
pub fn scale(self, x: f32) -> Vector2F {
Vector2F(self.0 * F32x2::splat(x))
}
#[inline]
pub fn scale_xy(self, factors: Vector2F) -> Vector2F {
Vector2F(self.0 * factors.0)
}
#[inline] #[inline]
pub fn floor(self) -> Vector2F { pub fn floor(self) -> Vector2F {
Vector2F(self.0.floor()) Vector2F(self.0.floor())
@ -132,7 +122,7 @@ impl Vector2F {
/// Treats this point as a vector and normalizes it. /// Treats this point as a vector and normalizes it.
#[inline] #[inline]
pub fn normalize(self) -> Vector2F { pub fn normalize(self) -> Vector2F {
self.scale(1.0 / self.length()) self * (1.0 / self.length())
} }
/// Swaps y and x. /// Swaps y and x.
@ -157,7 +147,7 @@ impl Vector2F {
#[inline] #[inline]
pub fn lerp(self, other: Vector2F, t: f32) -> Vector2F { pub fn lerp(self, other: Vector2F, t: f32) -> Vector2F {
self + (other - self).scale(t) self + (other - self) * t
} }
#[inline] #[inline]
@ -187,6 +177,14 @@ impl Add<Vector2F> for Vector2F {
} }
} }
impl Add<f32> for Vector2F {
type Output = Vector2F;
#[inline]
fn add(self, other: f32) -> Vector2F {
self + Vector2F::splat(other)
}
}
impl AddAssign<Vector2F> for Vector2F { impl AddAssign<Vector2F> for Vector2F {
#[inline] #[inline]
fn add_assign(&mut self, other: Vector2F) { fn add_assign(&mut self, other: Vector2F) {
@ -210,6 +208,28 @@ impl Mul<Vector2F> for Vector2F {
} }
} }
impl Mul<f32> for Vector2F {
type Output = Vector2F;
#[inline]
fn mul(self, other: f32) -> Vector2F {
self * Vector2F::splat(other)
}
}
impl MulAssign<Vector2F> for Vector2F {
#[inline]
fn mul_assign(&mut self, other: Vector2F) {
*self = *self * other
}
}
impl MulAssign<f32> for Vector2F {
#[inline]
fn mul_assign(&mut self, other: f32) {
*self = *self * other
}
}
impl Div<Vector2F> for Vector2F { impl Div<Vector2F> for Vector2F {
type Output = Vector2F; type Output = Vector2F;
#[inline] #[inline]
@ -226,6 +246,30 @@ impl Neg for Vector2F {
} }
} }
/// Either a scalar or a `Vector2F`.
///
/// Scalars will be automatically splatted (i.e. `x` becomes `vec2f(x, x)`).
///
/// Be judicious with the use of this trait. Only use it if it will aid readability without the
/// potential to introduce bugs.
pub trait IntoVector2F {
fn into_vector_2f(self) -> Vector2F;
}
impl IntoVector2F for Vector2F {
#[inline]
fn into_vector_2f(self) -> Vector2F {
self
}
}
impl IntoVector2F for f32 {
#[inline]
fn into_vector_2f(self) -> Vector2F {
Vector2F::splat(self)
}
}
/// 2D points with 32-bit signed integer coordinates. /// 2D points with 32-bit signed integer coordinates.
#[derive(Clone, Copy, Debug, Default)] #[derive(Clone, Copy, Debug, Default)]
pub struct Vector2I(pub I32x2); pub struct Vector2I(pub I32x2);
@ -276,16 +320,6 @@ impl Vector2I {
Vector2I(self.0.max(other.0)) Vector2I(self.0.max(other.0))
} }
#[inline]
pub fn scale(self, factor: i32) -> Vector2I {
Vector2I(self.0 * I32x2::splat(factor))
}
#[inline]
pub fn scale_xy(self, factors: Vector2I) -> Vector2I {
Vector2I(self.0 * factors.0)
}
#[inline] #[inline]
pub fn to_f32(self) -> Vector2F { pub fn to_f32(self) -> Vector2F {
Vector2F(self.0.to_f32x2()) Vector2F(self.0.to_f32x2())
@ -306,6 +340,14 @@ impl Add<Vector2I> for Vector2I {
} }
} }
impl Add<i32> for Vector2I {
type Output = Vector2I;
#[inline]
fn add(self, other: i32) -> Vector2I {
self + Vector2I::splat(other)
}
}
impl AddAssign<Vector2I> for Vector2I { impl AddAssign<Vector2I> for Vector2I {
#[inline] #[inline]
fn add_assign(&mut self, other: Vector2I) { fn add_assign(&mut self, other: Vector2I) {
@ -329,6 +371,30 @@ impl Sub<Vector2I> for Vector2I {
} }
} }
impl Sub<i32> for Vector2I {
type Output = Vector2I;
#[inline]
fn sub(self, other: i32) -> Vector2I {
self - Vector2I::splat(other)
}
}
impl Mul<Vector2I> for Vector2I {
type Output = Vector2I;
#[inline]
fn mul(self, other: Vector2I) -> Vector2I {
Vector2I(self.0 * other.0)
}
}
impl Mul<i32> for Vector2I {
type Output = Vector2I;
#[inline]
fn mul(self, other: i32) -> Vector2I {
self * Vector2I::splat(other)
}
}
impl PartialEq for Vector2I { impl PartialEq for Vector2I {
#[inline] #[inline]
fn eq(&self, other: &Vector2I) -> bool { fn eq(&self, other: &Vector2I) -> bool {

View File

@ -189,10 +189,9 @@ impl TreeNode {
requested_size) { requested_size) {
return Some(origin); return Some(origin);
} }
if let Some(origin) = kids[3].allocate( if let Some(origin) = kids[3].allocate(this_origin + kid_size as i32,
this_origin + Vector2I::splat(kid_size as i32), kid_size,
kid_size, requested_size) {
requested_size) {
return Some(origin); return Some(origin);
} }
@ -217,7 +216,7 @@ impl TreeNode {
} }
let child_size = this_size / 2; let child_size = this_size / 2;
let this_center = this_origin + Vector2I::splat(child_size as i32); let this_center = this_origin + child_size as i32;
let child_index; let child_index;
let mut child_origin = this_origin; let mut child_origin = this_origin;

View File

@ -278,9 +278,7 @@ impl<'a> SceneBuilder<'a> {
continue; continue;
} }
let uv_rect = let uv_rect = RectI::new(tile_coords, vec2i(1, 1)).to_f32() * uv_scale;
RectI::new(tile_coords, Vector2I::splat(1)).to_f32()
.scale_xy(uv_scale);
tiles.push(Tile::new_solid_from_texture_rect(tile_coords, uv_rect)); tiles.push(Tile::new_solid_from_texture_rect(tile_coords, uv_rect));
} }
} }
@ -894,12 +892,12 @@ fn calculate_mask_uv(tile_index: u16, tile_offset: Vector2I) -> Vector2F {
let mask_u = tile_index as i32 % MASK_TILES_ACROSS as i32; let mask_u = tile_index as i32 % MASK_TILES_ACROSS as i32;
let mask_v = tile_index as i32 / MASK_TILES_ACROSS as i32; let mask_v = tile_index as i32 / MASK_TILES_ACROSS as i32;
let scale = vec2f(1.0 / MASK_TILES_ACROSS as f32, 1.0 / MASK_TILES_DOWN as f32); let scale = vec2f(1.0 / MASK_TILES_ACROSS as f32, 1.0 / MASK_TILES_DOWN as f32);
(vec2i(mask_u, mask_v) + tile_offset).to_f32().scale_xy(scale) (vec2i(mask_u, mask_v) + tile_offset).to_f32() * scale
} }
fn calculate_opacity_uv(draw_tiling_path_info: &DrawTilingPathInfo) -> Vector2F { fn calculate_opacity_uv(draw_tiling_path_info: &DrawTilingPathInfo) -> Vector2F {
let DrawTilingPathInfo { opacity_tile_transform, opacity, .. } = *draw_tiling_path_info; let DrawTilingPathInfo { opacity_tile_transform, opacity, .. } = *draw_tiling_path_info;
let texel_coord = (vec2i((opacity % 16) as i32, (opacity / 16) as i32).to_f32() + let texel_coord = (vec2i((opacity % 16) as i32, (opacity / 16) as i32).to_f32() +
vec2f(0.5, 0.5)).scale(1.0 / 16.0); vec2f(0.5, 0.5)) * (1.0 / 16.0);
opacity_tile_transform * texel_coord opacity_tile_transform * texel_coord
} }

View File

@ -297,8 +297,7 @@ impl Palette {
Paint::Gradient(Gradient { radii: Some(_), .. }) => { Paint::Gradient(Gradient { radii: Some(_), .. }) => {
let texture_origin_uv = let texture_origin_uv =
rect_to_inset_uv(metadata.location.rect, texture_scale).origin(); rect_to_inset_uv(metadata.location.rect, texture_scale).origin();
let gradient_tile_scale = let gradient_tile_scale = texture_scale * (GRADIENT_TILE_LENGTH - 1) as f32;
texture_scale.scale((GRADIENT_TILE_LENGTH - 1) as f32);
Transform2F { Transform2F {
matrix: Matrix2x2F::from_scale(gradient_tile_scale), matrix: Matrix2x2F::from_scale(gradient_tile_scale),
vector: texture_origin_uv, vector: texture_origin_uv,
@ -320,7 +319,7 @@ impl Palette {
let texture_origin_uv = rect_to_uv(metadata.location.rect, let texture_origin_uv = rect_to_uv(metadata.location.rect,
texture_scale).lower_left(); texture_scale).lower_left();
Transform2F::from_translation(texture_origin_uv) * Transform2F::from_translation(texture_origin_uv) *
Transform2F::from_scale(texture_scale.scale_xy(vec2f(1.0, -1.0))) * Transform2F::from_scale(texture_scale * vec2f(1.0, -1.0)) *
transform.inverse() transform.inverse()
} }
} }
@ -372,7 +371,7 @@ impl PaintMetadata {
// TODO(pcwalton): Apply clamp/repeat to tile rect. // TODO(pcwalton): Apply clamp/repeat to tile rect.
pub(crate) fn calculate_tex_coords(&self, tile_position: Vector2I) -> Vector2F { pub(crate) fn calculate_tex_coords(&self, tile_position: Vector2I) -> Vector2F {
let tile_size = vec2i(TILE_WIDTH as i32, TILE_HEIGHT as i32); let tile_size = vec2i(TILE_WIDTH as i32, TILE_HEIGHT as i32);
let position = tile_position.scale_xy(tile_size).to_f32(); let position = (tile_position * tile_size).to_f32();
let tex_coords = self.texture_transform * position; let tex_coords = self.texture_transform * position;
tex_coords tex_coords
} }
@ -394,11 +393,11 @@ impl PaintMetadata {
} }
fn rect_to_uv(rect: RectI, texture_scale: Vector2F) -> RectF { fn rect_to_uv(rect: RectI, texture_scale: Vector2F) -> RectF {
rect.to_f32().scale_xy(texture_scale) rect.to_f32() * texture_scale
} }
fn rect_to_inset_uv(rect: RectI, texture_scale: Vector2F) -> RectF { fn rect_to_inset_uv(rect: RectI, texture_scale: Vector2F) -> RectF {
rect_to_uv(rect, texture_scale).contract(texture_scale.scale(0.5)) rect_to_uv(rect, texture_scale).contract(texture_scale * 0.5)
} }
// Opacity allocation // Opacity allocation
@ -424,7 +423,7 @@ impl OpacityTileBuilder {
fn tile_transform(&self, allocator: &TextureAllocator) -> Transform2F { fn tile_transform(&self, allocator: &TextureAllocator) -> Transform2F {
let texture_scale = allocator.page_scale(self.tile_location.page); let texture_scale = allocator.page_scale(self.tile_location.page);
let matrix = Matrix2x2F::from_scale(texture_scale.scale(16.0)); let matrix = Matrix2x2F::from_scale(texture_scale * 16.0);
let vector = rect_to_uv(self.tile_location.rect, texture_scale).origin(); let vector = rect_to_uv(self.tile_location.rect, texture_scale).origin();
Transform2F { matrix, vector } Transform2F { matrix, vector }
} }
@ -548,8 +547,7 @@ impl GradientTileBuilder {
render_commands.push(RenderCommand::UploadTexelData { render_commands.push(RenderCommand::UploadTexelData {
texels: Arc::new(tile.texels), texels: Arc::new(tile.texels),
location: TextureLocation { location: TextureLocation {
rect: RectI::new(Vector2I::zero(), rect: RectI::new(vec2i(0, 0), Vector2I::splat(GRADIENT_TILE_LENGTH as i32)),
Vector2I::splat(GRADIENT_TILE_LENGTH as i32)),
page: tile.page, page: tile.page,
}, },
}); });

View File

@ -177,7 +177,7 @@ impl Scene {
#[inline] #[inline]
pub(crate) fn effective_view_box(&self, render_options: &PreparedBuildOptions) -> RectF { pub(crate) fn effective_view_box(&self, render_options: &PreparedBuildOptions) -> RectF {
if render_options.subpixel_aa_enabled { if render_options.subpixel_aa_enabled {
self.view_box.scale_xy(vec2f(3.0, 1.0)) self.view_box * vec2f(3.0, 1.0)
} else { } else {
self.view_box self.view_box
} }

View File

@ -499,7 +499,7 @@ impl<'a> PackedTile<'a> {
} }
pub fn round_rect_out_to_tile_bounds(rect: RectF) -> RectI { pub fn round_rect_out_to_tile_bounds(rect: RectF) -> RectI {
rect.scale_xy(vec2f(1.0 / TILE_WIDTH as f32, 1.0 / TILE_HEIGHT as f32)).round_out().to_i32() (rect * vec2f(1.0 / TILE_WIDTH as f32, 1.0 / TILE_HEIGHT as f32)).round_out().to_i32()
} }
fn process_active_segment( fn process_active_segment(

View File

@ -13,7 +13,7 @@ use pathfinder_color::{ColorF, ColorU};
use pathfinder_content::fill::FillRule; use pathfinder_content::fill::FillRule;
use pathfinder_content::outline::{Outline, Contour}; use pathfinder_content::outline::{Outline, Contour};
use pathfinder_content::stroke::{OutlineStrokeToFill, StrokeStyle}; use pathfinder_content::stroke::{OutlineStrokeToFill, StrokeStyle};
use pathfinder_geometry::vector::{Vector2F, vec2f}; use pathfinder_geometry::vector::vec2f;
use pathfinder_renderer::scene::{DrawPath, Scene}; use pathfinder_renderer::scene::{DrawPath, Scene};
use swf_types::tags::SetBackgroundColor; use swf_types::tags::SetBackgroundColor;