Make SVG stroke width more accurate, and switch to XCAA by default.

Partially addresses #57.
This commit is contained in:
Patrick Walton 2017-12-20 10:40:21 -08:00
parent 797b935f35
commit 6a81ec4893
3 changed files with 23 additions and 11 deletions

View File

@ -56,10 +56,10 @@
<select id="pf-aa-level-select" class="form-control custom-select">
<option value="none">None</option>
<option value="ssaa-2">2&times;SSAA</option>
<option value="ssaa-4" selected>4&times;SSAA</option>
<option value="ssaa-4">4&times;SSAA</option>
<option value="ssaa-8">8&times;SSAA</option>
<option value="ssaa-16">16&times;SSAA</option>
<option value="xcaa">XCAA (experimental)</option>
<option value="xcaa" selected>XCAA</option>
</select>
</div>
</form>

View File

@ -15,7 +15,7 @@ import * as _ from 'lodash';
import 'path-data-polyfill.js';
import {parseServerTiming, PathfinderMeshData} from "./meshes";
import {AlphaMaskCompositingOperation, RenderTask, RenderTaskType} from './render-task';
import {panic, Range, unwrapNull, unwrapUndef} from "./utils";
import {panic, Range, unwrapNull, unwrapUndef, lerp} from "./utils";
export const BUILTIN_SVG_URI: string = "/svg/demo";
@ -23,9 +23,6 @@ const parseColor = require('parse-color');
const PARTITION_SVG_PATHS_ENDPOINT_URL: string = "/partition-svg-paths";
/// The minimum size of a stroke.
const HAIRLINE_STROKE_WIDTH: number = 0.25;
declare class SVGPathSegment {
type: string;
values: number[];
@ -62,7 +59,20 @@ export class SVGStroke extends SVGPath {
super(element, 'stroke');
const style = window.getComputedStyle(element);
this.width = parseInt(style.strokeWidth!, 10);
const ctm = element.getCTM();
const strokeWidthString = unwrapNull(style.strokeWidth);
const matches = /^(\d+\.?\d*)(.*)$/.exec(strokeWidthString);
let strokeWidth;
if (matches == null) {
strokeWidth = 0.0;
} else {
strokeWidth = parseFloat(matches[1]);
if (matches[2] === 'px')
strokeWidth *= lerp(ctm.a, ctm.d, 0.5);
}
this.width = strokeWidth;
}
}
@ -179,7 +189,7 @@ export class SVGLoader {
this.pathBounds.push(pathBounds);
} else if (instance instanceof SVGStroke) {
this.paths.push({
kind: { Stroke: Math.max(HAIRLINE_STROKE_WIDTH, instance.width) },
kind: { Stroke: instance.width },
segments: segments,
});
this.pathBounds.push(pathBounds);

View File

@ -56,6 +56,8 @@ impl Stroke {
/// TODO(pcwalton): Miter and round joins.
fn offset_subpath(&self, output: &mut PathBuffer, input: &PathBuffer, subpath_index: u32) {
let radius = self.width * 0.5;
let subpath = &input.subpaths[subpath_index as usize];
let mut prev_position = None;
@ -65,7 +67,7 @@ impl Stroke {
if let Some(ref prev_position) = prev_position {
if endpoint.control_point_index == u32::MAX {
let offset_line = Line::new(&prev_position, position).offset(self.width);
let offset_line = Line::new(&prev_position, position).offset(radius);
output.endpoints.extend_from_slice(&[
Endpoint {
position: offset_line.endpoints[0],
@ -87,9 +89,9 @@ impl Stroke {
let control_point_position =
&input.control_points[endpoint.control_point_index as usize];
let offset_line_0 =
Line::new(&prev_position, control_point_position).offset(self.width);
Line::new(&prev_position, control_point_position).offset(radius);
let offset_line_1 =
Line::new(control_point_position, position).offset(self.width);
Line::new(control_point_position, position).offset(radius);
// FIXME(pcwalton): Can the `None` case ever happen?
let offset_control_point =