Make SVG stroke width more accurate, and switch to XCAA by default.
Partially addresses #57.
This commit is contained in:
parent
797b935f35
commit
6a81ec4893
|
@ -56,10 +56,10 @@
|
||||||
<select id="pf-aa-level-select" class="form-control custom-select">
|
<select id="pf-aa-level-select" class="form-control custom-select">
|
||||||
<option value="none">None</option>
|
<option value="none">None</option>
|
||||||
<option value="ssaa-2">2×SSAA</option>
|
<option value="ssaa-2">2×SSAA</option>
|
||||||
<option value="ssaa-4" selected>4×SSAA</option>
|
<option value="ssaa-4">4×SSAA</option>
|
||||||
<option value="ssaa-8">8×SSAA</option>
|
<option value="ssaa-8">8×SSAA</option>
|
||||||
<option value="ssaa-16">16×SSAA</option>
|
<option value="ssaa-16">16×SSAA</option>
|
||||||
<option value="xcaa">XCAA (experimental)</option>
|
<option value="xcaa" selected>XCAA</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -15,7 +15,7 @@ import * as _ from 'lodash';
|
||||||
import 'path-data-polyfill.js';
|
import 'path-data-polyfill.js';
|
||||||
import {parseServerTiming, PathfinderMeshData} from "./meshes";
|
import {parseServerTiming, PathfinderMeshData} from "./meshes";
|
||||||
import {AlphaMaskCompositingOperation, RenderTask, RenderTaskType} from './render-task';
|
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";
|
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";
|
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 {
|
declare class SVGPathSegment {
|
||||||
type: string;
|
type: string;
|
||||||
values: number[];
|
values: number[];
|
||||||
|
@ -62,7 +59,20 @@ export class SVGStroke extends SVGPath {
|
||||||
super(element, 'stroke');
|
super(element, 'stroke');
|
||||||
|
|
||||||
const style = window.getComputedStyle(element);
|
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);
|
this.pathBounds.push(pathBounds);
|
||||||
} else if (instance instanceof SVGStroke) {
|
} else if (instance instanceof SVGStroke) {
|
||||||
this.paths.push({
|
this.paths.push({
|
||||||
kind: { Stroke: Math.max(HAIRLINE_STROKE_WIDTH, instance.width) },
|
kind: { Stroke: instance.width },
|
||||||
segments: segments,
|
segments: segments,
|
||||||
});
|
});
|
||||||
this.pathBounds.push(pathBounds);
|
this.pathBounds.push(pathBounds);
|
||||||
|
|
|
@ -56,6 +56,8 @@ impl Stroke {
|
||||||
|
|
||||||
/// TODO(pcwalton): Miter and round joins.
|
/// TODO(pcwalton): Miter and round joins.
|
||||||
fn offset_subpath(&self, output: &mut PathBuffer, input: &PathBuffer, subpath_index: u32) {
|
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 subpath = &input.subpaths[subpath_index as usize];
|
||||||
|
|
||||||
let mut prev_position = None;
|
let mut prev_position = None;
|
||||||
|
@ -65,7 +67,7 @@ impl Stroke {
|
||||||
|
|
||||||
if let Some(ref prev_position) = prev_position {
|
if let Some(ref prev_position) = prev_position {
|
||||||
if endpoint.control_point_index == u32::MAX {
|
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(&[
|
output.endpoints.extend_from_slice(&[
|
||||||
Endpoint {
|
Endpoint {
|
||||||
position: offset_line.endpoints[0],
|
position: offset_line.endpoints[0],
|
||||||
|
@ -87,9 +89,9 @@ impl Stroke {
|
||||||
let control_point_position =
|
let control_point_position =
|
||||||
&input.control_points[endpoint.control_point_index as usize];
|
&input.control_points[endpoint.control_point_index as usize];
|
||||||
let offset_line_0 =
|
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 =
|
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?
|
// FIXME(pcwalton): Can the `None` case ever happen?
|
||||||
let offset_control_point =
|
let offset_control_point =
|
||||||
|
|
Loading…
Reference in New Issue