forked from mirrors/gecko-dev
Bug 1859736 - Update wpf-gpu-raster. r=gfx-reviewers,lsalzman
Differential Revision: https://phabricator.services.mozilla.com/D191282
This commit is contained in:
parent
121847341b
commit
715ea35965
14 changed files with 26 additions and 490 deletions
|
|
@ -10,9 +10,9 @@ git = "https://github.com/FirefoxGraphics/aa-stroke"
|
|||
rev = "ed4206ea11703580cd1d4fc63371a527b29d8252"
|
||||
replace-with = "vendored-sources"
|
||||
|
||||
[source."git+https://github.com/FirefoxGraphics/wpf-gpu-raster?rev=5ab6fe33d00021325ee920b3c10526dc8301cf46"]
|
||||
[source."git+https://github.com/FirefoxGraphics/wpf-gpu-raster?rev=99979da091fd58fba8477e7fcdf5ec0727102916"]
|
||||
git = "https://github.com/FirefoxGraphics/wpf-gpu-raster"
|
||||
rev = "5ab6fe33d00021325ee920b3c10526dc8301cf46"
|
||||
rev = "99979da091fd58fba8477e7fcdf5ec0727102916"
|
||||
replace-with = "vendored-sources"
|
||||
|
||||
[source."git+https://github.com/chris-zen/coremidi.git?rev=fc68464b5445caf111e41f643a2e69ccce0b4f83"]
|
||||
|
|
|
|||
2
Cargo.lock
generated
2
Cargo.lock
generated
|
|
@ -6522,7 +6522,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "wpf-gpu-raster"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/FirefoxGraphics/wpf-gpu-raster?rev=5ab6fe33d00021325ee920b3c10526dc8301cf46#5ab6fe33d00021325ee920b3c10526dc8301cf46"
|
||||
source = "git+https://github.com/FirefoxGraphics/wpf-gpu-raster?rev=99979da091fd58fba8477e7fcdf5ec0727102916#99979da091fd58fba8477e7fcdf5ec0727102916"
|
||||
dependencies = [
|
||||
"typed-arena-nomut",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
{"files":{".github/workflows/coverage.yml":"90aaa068c16cb778b24badaff78baf2a313637780a723be09596abde0f4c827a",".github/workflows/rust.yml":"905954be896d052ced621eedb9d5b9d35795490f27071ac1147e75ac3b3711ec","CHANGES.md":"5f54e553a1c4ef21c5be6109b25df9d1d63c4547627723fe044c73dbddf0db2f","Cargo.toml":"0f7a5c9814bde552a5113f118da3c1f0f897fb7199e2bfe11c3b1a31bc2f8d5d","LICENSE":"ae48df11a335dc1a615f4f938b69cba73bcf4485c4f97af49b38efb0f216353b","README.md":"e14b7ddbd29b6f87d956921999da1cf7bc3add0166cacf21e8b1ac1d9092a90d","examples/draw.rs":"52fee9e2f2c11e1c891b30cb460be2a0ec65974f38dc0c08fd48391caf1e4247","examples/obj-output.rs":"6fc549022aa715eee74ea1cafb89ca33189e9dbe914ea6b2c46160049bda68f3","examples/simple.rs":"99fb566414cbd4a0eb69a2774c9780d7cd17e5cdaa14837b280fba319c053f22","notes":"48e636c646d697e213b3a79e31063e11b6ffc7493592d31f3929b1db495870b8","src/aacoverage.rs":"fdadadd208caa986cc386797f937a976b5a315174c7c0782b87c0334d6474a97","src/aarasterizer.rs":"283bed1e22917118f332b24731cb6bd11334a4f0ba0d88821cfeb6b607de12da","src/bezier.rs":"f089ab04e30077ce4e0fe59dfa602948b989aa53d51ad207fbc30c1edd24086b","src/c_bindings.rs":"9c5ab638cf0a14220d93528e37cdc0f6d83277eaa10acf9ce36f32a28e30c02b","src/fix.rs":"7ccf63db5bab4ab0135d92691f7c2272a27866b9792dd55ec98b2d1c1b7c0358","src/geometry_sink.rs":"9025569f77f475a1e47fd470e8f53dcdf88ef57e3a5b8a51268fff892da8b1a7","src/helpers.rs":"220294dac335943518f249c4a27ad803f8226ed62cd780f517e95be6343a1f2f","src/hwrasterizer.rs":"82b2d6d35488a6ad7de4d82f3ee38c6f09f4b6de06b4f98eea61b3abdd72eb62","src/hwvertexbuffer.rs":"f3dd54f17570eb530c9c827b24a53b755a2dfa6028e9b83f9d7a4ba9945c2ecf","src/lib.rs":"8cd659ff6e2165884eaa1657462e1a5bf15a68a83cb768c2dff2f433ff0a022c","src/matrix.rs":"1ac44bc5d073f96ab64b1b5c6077fd0d47fe61db8243bd9a55fc91d8eae1dd92","src/notes":"d50d49e0b5660bc6350d8055f25f26700c937558de0af690e1fc4f50ed7e05c9","src/nullable_ref.rs":"789fe0e59b7d4a925faecbf2362be93643ea8382b4424ca0e60866f9bf83c3cd","src/real.rs":"73a2d1a77613364e9514fd7ead4d708a554d2b7343645cdb4cb8a2b3b640e057","src/tri_rasterize.rs":"30821a3465cea3c5ac578590013b530c03ea3010225f580d6cf609e39910c412","src/types.rs":"b840212a99a212ef38211aaf1bd801ec83416569541941d15fd95285d1342b99"},"package":null}
|
||||
{"files":{"Cargo.toml":"16a2fc5b725d83b7a3547d0eab6df5ec5a710a9f87fca37ae473eab210b13113","LICENSE":"ae48df11a335dc1a615f4f938b69cba73bcf4485c4f97af49b38efb0f216353b","README.md":"e14b7ddbd29b6f87d956921999da1cf7bc3add0166cacf21e8b1ac1d9092a90d","src/aacoverage.rs":"fdadadd208caa986cc386797f937a976b5a315174c7c0782b87c0334d6474a97","src/aarasterizer.rs":"283bed1e22917118f332b24731cb6bd11334a4f0ba0d88821cfeb6b607de12da","src/bezier.rs":"f089ab04e30077ce4e0fe59dfa602948b989aa53d51ad207fbc30c1edd24086b","src/c_bindings.rs":"deac1f9eac8e77d1b26bb3e8348fed97bb02e5bfedb8c1dede408e51126ba63d","src/fix.rs":"7ccf63db5bab4ab0135d92691f7c2272a27866b9792dd55ec98b2d1c1b7c0358","src/geometry_sink.rs":"9025569f77f475a1e47fd470e8f53dcdf88ef57e3a5b8a51268fff892da8b1a7","src/helpers.rs":"220294dac335943518f249c4a27ad803f8226ed62cd780f517e95be6343a1f2f","src/hwrasterizer.rs":"82b2d6d35488a6ad7de4d82f3ee38c6f09f4b6de06b4f98eea61b3abdd72eb62","src/hwvertexbuffer.rs":"f3dd54f17570eb530c9c827b24a53b755a2dfa6028e9b83f9d7a4ba9945c2ecf","src/lib.rs":"9a09fd5f6a1ba9469c3ddfd38493e315ef94f0bc0a4e58724d146c3658d9ab1d","src/matrix.rs":"1ac44bc5d073f96ab64b1b5c6077fd0d47fe61db8243bd9a55fc91d8eae1dd92","src/notes":"d50d49e0b5660bc6350d8055f25f26700c937558de0af690e1fc4f50ed7e05c9","src/nullable_ref.rs":"789fe0e59b7d4a925faecbf2362be93643ea8382b4424ca0e60866f9bf83c3cd","src/real.rs":"73a2d1a77613364e9514fd7ead4d708a554d2b7343645cdb4cb8a2b3b640e057","src/tri_rasterize.rs":"30821a3465cea3c5ac578590013b530c03ea3010225f580d6cf609e39910c412","src/types.rs":"b840212a99a212ef38211aaf1bd801ec83416569541941d15fd95285d1342b99"},"package":null}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
name: Coverage
|
||||
|
||||
on: [pull_request, push]
|
||||
|
||||
jobs:
|
||||
coverage:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install Rust
|
||||
run: rustup toolchain install stable --component llvm-tools-preview
|
||||
- name: Install cargo-llvm-cov
|
||||
uses: taiki-e/install-action@cargo-llvm-cov
|
||||
- name: Generate code coverage
|
||||
run: cargo llvm-cov --all-features --workspace --lcov --output-path lcov.info
|
||||
- name: Upload coverage to Codecov
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos
|
||||
files: lcov.info
|
||||
fail_ci_if_error: true
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
name: Rust
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Build
|
||||
run: cargo build --verbose
|
||||
- name: Run tests
|
||||
run: cargo test --verbose
|
||||
|
||||
aarch64:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Install toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
override: true
|
||||
target: aarch64-unknown-linux-gnu
|
||||
|
||||
- name: Install cross
|
||||
run: cargo install cross
|
||||
|
||||
- name: Run tests with Neon
|
||||
run: cross test --target aarch64-unknown-linux-gnu
|
||||
22
third_party/rust/wpf-gpu-raster/CHANGES.md
vendored
22
third_party/rust/wpf-gpu-raster/CHANGES.md
vendored
|
|
@ -1,22 +0,0 @@
|
|||
Changes for Safety
|
||||
------------------
|
||||
|
||||
`CEdgeStore` is replaced by `typed_arena_nomut::Arena<CEdge>`.
|
||||
|
||||
`CEdgeStore` is an arena with built-in stack storage for the first allocation
|
||||
of the arena. It exposes the allocated buffers to support very fast allocation,
|
||||
and supports fast enumeration by returning pointers to each allocation.
|
||||
|
||||
`CCoverageBuffer` also now uses a `typed_arena_nomut::Arena<CEdge>` but uses it
|
||||
to allocate `CCoverageIntervalBuffer`'s. We currently lack support for
|
||||
the builtin stack storage. Storing these in an Arena is not ideal, we'd rather
|
||||
just heap allocate them individually.
|
||||
|
||||
|
||||
Changes for performance
|
||||
-----------------------
|
||||
|
||||
Switched from using triangle strips to triangle lists. This lets
|
||||
us use a single triangle to draw each line segement which reduces
|
||||
the amount of geometry per line segment from 6 vertices to 3.
|
||||
Direct2D also made this switch in later versions.
|
||||
5
third_party/rust/wpf-gpu-raster/Cargo.toml
vendored
5
third_party/rust/wpf-gpu-raster/Cargo.toml
vendored
|
|
@ -13,6 +13,11 @@
|
|||
edition = "2021"
|
||||
name = "wpf-gpu-raster"
|
||||
version = "0.1.0"
|
||||
include = [
|
||||
"src/**/*",
|
||||
"LICENSE",
|
||||
"README.md",
|
||||
]
|
||||
readme = "README.md"
|
||||
license = "MIT"
|
||||
|
||||
|
|
|
|||
354
third_party/rust/wpf-gpu-raster/examples/draw.rs
vendored
354
third_party/rust/wpf-gpu-raster/examples/draw.rs
vendored
|
|
@ -1,354 +0,0 @@
|
|||
/* The rasterization code here is based off of piglit/tests/general/triangle-rasterization.cpp:
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2012 VMware, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
*/
|
||||
|
||||
#![allow(non_camel_case_types)]
|
||||
#![allow(non_snake_case)]
|
||||
use euclid::{default::Transform2D, point2};
|
||||
use wpf_gpu_raster::{PathBuilder};
|
||||
|
||||
|
||||
use std::ops::Index;
|
||||
|
||||
|
||||
const WIDTH: u32 = 800;
|
||||
const HEIGHT: u32 = 800;
|
||||
|
||||
|
||||
fn over(src: u32, dst: u32) -> u32 {
|
||||
let a = src >> 24;
|
||||
let a = 255 - a;
|
||||
let mask = 0xff00ff;
|
||||
let t = (dst & mask) * a + 0x800080;
|
||||
let mut rb = (t + ((t >> 8) & mask)) >> 8;
|
||||
rb &= mask;
|
||||
|
||||
rb += src & mask;
|
||||
|
||||
// saturate
|
||||
rb |= 0x1000100 - ((rb >> 8) & mask);
|
||||
rb &= mask;
|
||||
|
||||
let t = ((dst >> 8) & mask) * a + 0x800080;
|
||||
let mut ag = (t + ((t >> 8) & mask)) >> 8;
|
||||
ag &= mask;
|
||||
ag += (src >> 8) & mask;
|
||||
|
||||
// saturate
|
||||
ag |= 0x1000100 - ((ag >> 8) & mask);
|
||||
ag &= mask;
|
||||
|
||||
(ag << 8) + rb
|
||||
}
|
||||
|
||||
pub fn alpha_mul(x: u32, a: u32) -> u32 {
|
||||
let mask = 0xFF00FF;
|
||||
|
||||
let src_rb = ((x & mask) * a) >> 8;
|
||||
let src_ag = ((x >> 8) & mask) * a;
|
||||
|
||||
(src_rb & mask) | (src_ag & !mask)
|
||||
}
|
||||
|
||||
fn write_image(data: &[u32], path: &str) {
|
||||
use std::path::Path;
|
||||
use std::fs::File;
|
||||
use std::io::BufWriter;
|
||||
|
||||
let mut png_data: Vec<u8> = vec![0; (WIDTH * HEIGHT * 3) as usize];
|
||||
let mut i = 0;
|
||||
for pixel in data {
|
||||
png_data[i] = ((pixel >> 16) & 0xff) as u8;
|
||||
png_data[i + 1] = ((pixel >> 8) & 0xff) as u8;
|
||||
png_data[i + 2] = ((pixel >> 0) & 0xff) as u8;
|
||||
i += 3;
|
||||
}
|
||||
|
||||
|
||||
let path = Path::new(path);
|
||||
let file = File::create(path).unwrap();
|
||||
let w = &mut BufWriter::new(file);
|
||||
|
||||
let mut encoder = png::Encoder::new(w, WIDTH, HEIGHT); // Width is 2 pixels and height is 1.
|
||||
encoder.set_color(png::ColorType::Rgb);
|
||||
encoder.set_depth(png::BitDepth::Eight);
|
||||
let mut writer = encoder.write_header().unwrap();
|
||||
|
||||
writer.write_image_data(&png_data).unwrap(); // Save
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Vertex {
|
||||
x: f32,
|
||||
y: f32,
|
||||
coverage: f32
|
||||
}
|
||||
#[derive(Debug)]
|
||||
struct Triangle {
|
||||
v: [Vertex; 3],
|
||||
}
|
||||
|
||||
impl Index<usize> for Triangle {
|
||||
type Output = Vertex;
|
||||
|
||||
fn index(&self, index: usize) -> &Self::Output {
|
||||
&self.v[index]
|
||||
}
|
||||
}
|
||||
|
||||
// D3D11 mandates 8 bit subpixel precision:
|
||||
// https://microsoft.github.io/DirectX-Specs/d3d/archive/D3D11_3_FunctionalSpec.htm#CoordinateSnapping
|
||||
const FIXED_SHIFT: i32 = 8;
|
||||
const FIXED_ONE: f32 = (1 << FIXED_SHIFT) as f32;
|
||||
|
||||
/* Proper rounding of float to integer */
|
||||
fn iround(mut v: f32) -> i64 {
|
||||
if v > 0.0 {
|
||||
v += 0.5;
|
||||
}
|
||||
if v < 0.0 {
|
||||
v -= 0.5;
|
||||
}
|
||||
return v as i64
|
||||
}
|
||||
|
||||
/* Based on http://devmaster.net/forums/topic/1145-advanced-rasterization */
|
||||
fn rast_triangle(buffer: &mut [u32], stride: usize, tri: &Triangle, color: u32) {
|
||||
let center_offset = -0.5;
|
||||
|
||||
let mut coverage1 = tri[0].coverage;
|
||||
let mut coverage2 = tri[1].coverage;
|
||||
let mut coverage3 = tri[2].coverage;
|
||||
|
||||
/* fixed point coordinates */
|
||||
let mut x1 = iround(FIXED_ONE * (tri[0].x + center_offset));
|
||||
let x2 = iround(FIXED_ONE * (tri[1].x + center_offset));
|
||||
let mut x3 = iround(FIXED_ONE * (tri[2].x + center_offset));
|
||||
|
||||
let mut y1 = iround(FIXED_ONE * (tri[0].y + center_offset));
|
||||
let y2 = iround(FIXED_ONE * (tri[1].y + center_offset));
|
||||
let mut y3 = iround(FIXED_ONE * (tri[2].y + center_offset));
|
||||
|
||||
|
||||
/* Force correct vertex order */
|
||||
let cross = (x2 - x1) * (y3 - y2) - (y2 - y1) * (x3 - x2);
|
||||
if cross > 0 {
|
||||
std::mem::swap(&mut x1, &mut x3);
|
||||
std::mem::swap(&mut y1, &mut y3);
|
||||
// I don't understand why coverage 2 and 3 are swapped instead of 1 and 3
|
||||
std::mem::swap(&mut coverage2, &mut coverage3);
|
||||
} else {
|
||||
std::mem::swap(&mut coverage1, &mut coverage3);
|
||||
}
|
||||
|
||||
/* Deltas */
|
||||
let dx12 = x1 - x2;
|
||||
let dx23 = x2 - x3;
|
||||
let dx31 = x3 - x1;
|
||||
|
||||
let dy12 = y1 - y2;
|
||||
let dy23 = y2 - y3;
|
||||
let dy31 = y3 - y1;
|
||||
|
||||
/* Fixed-point deltas */
|
||||
let fdx12 = dx12 << FIXED_SHIFT;
|
||||
let fdx23 = dx23 << FIXED_SHIFT;
|
||||
let fdx31 = dx31 << FIXED_SHIFT;
|
||||
|
||||
let fdy12 = dy12 << FIXED_SHIFT;
|
||||
let fdy23 = dy23 << FIXED_SHIFT;
|
||||
let fdy31 = dy31 << FIXED_SHIFT;
|
||||
|
||||
/* Bounding rectangle */
|
||||
let mut minx = x1.min(x2).min(x3) >> FIXED_SHIFT;
|
||||
let mut maxx = x1.max(x2).max(x3) >> FIXED_SHIFT;
|
||||
|
||||
let mut miny = y1.min(y2).min(y3) >> FIXED_SHIFT;
|
||||
let mut maxy = y1.max(y2).max(y3) >> FIXED_SHIFT;
|
||||
|
||||
minx = minx.max(0);
|
||||
maxx = maxx.min(WIDTH as i64 - 1);
|
||||
|
||||
miny = miny.max(0);
|
||||
maxy = maxy.min(HEIGHT as i64 - 1);
|
||||
|
||||
/* Half-edge constants */
|
||||
let mut c1 = dy12 * x1 - dx12 * y1;
|
||||
let mut c2 = dy23 * x2 - dx23 * y2;
|
||||
let mut c3 = dy31 * x3 - dx31 * y3;
|
||||
|
||||
/* Correct for top-left filling convention */
|
||||
if dy12 < 0 || (dy12 == 0 && dx12 < 0) { c1 += 1 }
|
||||
if dy23 < 0 || (dy23 == 0 && dx23 < 0) { c2 += 1 }
|
||||
if dy31 < 0 || (dy31 == 0 && dx31 < 0) { c3 += 1 }
|
||||
|
||||
let mut cy1 = c1 + dx12 * (miny << FIXED_SHIFT) - dy12 * (minx << FIXED_SHIFT);
|
||||
let mut cy2 = c2 + dx23 * (miny << FIXED_SHIFT) - dy23 * (minx << FIXED_SHIFT);
|
||||
let mut cy3 = c3 + dx31 * (miny << FIXED_SHIFT) - dy31 * (minx << FIXED_SHIFT);
|
||||
|
||||
/* Perform rasterization */
|
||||
let mut buffer = &mut buffer[miny as usize * stride..];
|
||||
for _y in miny..=maxy {
|
||||
let mut cx1 = cy1;
|
||||
let mut cx2 = cy2;
|
||||
let mut cx3 = cy3;
|
||||
|
||||
for x in minx..=maxx {
|
||||
if cx1 > 0 && cx2 > 0 && cx3 > 0 {
|
||||
// cross is equal to 2*area of the triangle.
|
||||
// we can normalize cx by 2*area to get barycentric coords.
|
||||
let area = cross.abs() as f32;
|
||||
let bary = (cx1 as f32 / area, cx2 as f32/ area, cx3 as f32 / area);
|
||||
|
||||
let coverages = coverage1 * bary.0 + coverage2 * bary.1 + coverage3 * bary.2;
|
||||
|
||||
let color = alpha_mul(color, (coverages * 256. + 0.5) as u32);
|
||||
buffer[x as usize] = over(color, buffer[x as usize]);
|
||||
}
|
||||
|
||||
cx1 -= fdy12;
|
||||
cx2 -= fdy23;
|
||||
cx3 -= fdy31;
|
||||
}
|
||||
|
||||
cy1 += fdx12;
|
||||
cy2 += fdx23;
|
||||
cy3 += fdx31;
|
||||
|
||||
buffer = &mut buffer[stride..];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn main() {
|
||||
let opt = usvg::Options::default();
|
||||
|
||||
let rtree = usvg::Tree::from_file("tiger.svg", &opt).unwrap();
|
||||
|
||||
let mut image = vec![0; (WIDTH * HEIGHT) as usize];
|
||||
for _ in 0..1 {
|
||||
let mut total_vertex_count = 0;
|
||||
let mut total_time = std::time::Duration::default();
|
||||
for node in rtree.root().descendants() {
|
||||
use usvg::NodeExt;
|
||||
let t = node.transform();
|
||||
let transform = Transform2D::new(
|
||||
t.a as f32, t.b as f32,
|
||||
t.c as f32, t.d as f32,
|
||||
t.e as f32, t.f as f32,
|
||||
);
|
||||
|
||||
|
||||
let s = 1.;
|
||||
if let usvg::NodeKind::Path(ref usvg_path) = *node.borrow() {
|
||||
let color = match usvg_path.fill {
|
||||
Some(ref fill) => {
|
||||
match fill.paint {
|
||||
usvg::Paint::Color(c) => 0xff000000 | (c.red as u32) << 16 | (c.green as u32) << 8 | c.blue as u32,
|
||||
_ => 0xff00ff00,
|
||||
}
|
||||
}
|
||||
None => {
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let mut builder = PathBuilder::new();
|
||||
//dbg!(&usvg_path.segments);
|
||||
for segment in &usvg_path.segments {
|
||||
match *segment {
|
||||
usvg::PathSegment::MoveTo { x, y } => {
|
||||
let p = transform.transform_point(point2(x as f32, y as f32)) * s;
|
||||
builder.move_to(p.x, p.y);
|
||||
}
|
||||
usvg::PathSegment::LineTo { x, y } => {
|
||||
let p = transform.transform_point(point2(x as f32, y as f32)) * s;
|
||||
builder.line_to(p.x, p.y);
|
||||
}
|
||||
usvg::PathSegment::CurveTo { x1, y1, x2, y2, x, y, } => {
|
||||
let c1 = transform.transform_point(point2(x1 as f32, y1 as f32)) * s;
|
||||
let c2 = transform.transform_point(point2(x2 as f32, y2 as f32)) * s;
|
||||
let p = transform.transform_point(point2(x as f32, y as f32)) * s;
|
||||
builder.curve_to(
|
||||
c1.x, c1.y,
|
||||
c2.x, c2.y,
|
||||
p.x, p.y,
|
||||
);
|
||||
}
|
||||
usvg::PathSegment::ClosePath => {
|
||||
builder.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
let start = std::time::Instant::now();
|
||||
let result = builder.rasterize_to_tri_list(0, 0, WIDTH as i32, HEIGHT as i32);
|
||||
let end = std::time::Instant::now();
|
||||
total_time += end - start;
|
||||
|
||||
println!("vertices {}", result.len());
|
||||
total_vertex_count += result.len();
|
||||
if result.len() == 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
for n in (0..result.len()).step_by(3) {
|
||||
let vertices = {
|
||||
[&result[n], &result[n+1], &result[n+2]]
|
||||
};
|
||||
|
||||
let src = color;
|
||||
let tri = Triangle { v: [
|
||||
Vertex { x: vertices[0].x, y: vertices[0].y, coverage: vertices[0].coverage},
|
||||
Vertex { x: vertices[1].x, y: vertices[1].y, coverage: vertices[1].coverage},
|
||||
Vertex { x: vertices[2].x, y: vertices[2].y, coverage: vertices[2].coverage}
|
||||
]
|
||||
};
|
||||
rast_triangle(&mut image, WIDTH as usize, &tri, src);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
println!("total vertex count {}, took {}ms", total_vertex_count, total_time.as_secs_f32()*1000.);
|
||||
}
|
||||
|
||||
|
||||
write_image(&image, "out.png");
|
||||
use std::{hash::{Hash, Hasher}, collections::hash_map::DefaultHasher};
|
||||
use crate::*;
|
||||
fn calculate_hash<T: Hash>(t: &T) -> u64 {
|
||||
let mut s = DefaultHasher::new();
|
||||
t.hash(&mut s);
|
||||
s.finish()
|
||||
}
|
||||
|
||||
assert_eq!(calculate_hash(&image),
|
||||
if cfg!(debug_assertions) { 0x5973c52a1c0232f3 } else { 0xf15821a5bebc5ecf});
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
// Output an .obj file of the generated mesh. Viewable at https://3dviewer.net/
|
||||
|
||||
fn output_obj_file(data: &[OutputVertex]) {
|
||||
for v in data {
|
||||
let color = v.coverage;
|
||||
println!("v {} {} {} {} {} {}", v.x, v.y, 0., color, color, color);
|
||||
}
|
||||
|
||||
// output a standard triangle strip face list
|
||||
for n in (1..data.len()-1).step_by(3) {
|
||||
println!("f {} {} {}", n, n+1, n+2);
|
||||
}
|
||||
}
|
||||
|
||||
use wpf_gpu_raster::{PathBuilder, OutputVertex};
|
||||
fn main() {
|
||||
let mut p = PathBuilder::new();
|
||||
p.move_to(10., 10.0);
|
||||
p.line_to(30., 10.);
|
||||
p.line_to(50., 20.);
|
||||
p.line_to(30., 30.);
|
||||
p.line_to(10., 30.);
|
||||
p.close();
|
||||
let result = p.rasterize_to_tri_list(0, 0, 100, 100);
|
||||
output_obj_file(&result)
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
use wpf_gpu_raster::PathBuilder;
|
||||
fn main() {
|
||||
let mut p = PathBuilder::new();
|
||||
p.move_to(10., 10.);
|
||||
p.line_to(10., 30.);
|
||||
p.line_to(30., 30.);
|
||||
p.line_to(30., 10.);
|
||||
p.close();
|
||||
let _result = p.rasterize_to_tri_list(0, 0, 100, 100);
|
||||
//dbg!(result);
|
||||
}
|
||||
8
third_party/rust/wpf-gpu-raster/notes
vendored
8
third_party/rust/wpf-gpu-raster/notes
vendored
|
|
@ -1,8 +0,0 @@
|
|||
bezier flattening
|
||||
-----------------
|
||||
if we make sure we flatten beziers to integer y values we can avoid having to hit
|
||||
the slow complex coverage path
|
||||
|
||||
We can probably do this by using a skia style flattener.
|
||||
Normally we compute a series of line segments using partial differencing.
|
||||
I think we can adjust the line towards an integer y value by having small partial differences that we can move by.
|
||||
|
|
@ -7,6 +7,11 @@ pub extern "C" fn wgr_new_builder() -> *mut PathBuilder {
|
|||
Box::into_raw(Box::new(pb))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wgr_builder_reset(pb: &mut PathBuilder) {
|
||||
pb.reset();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wgr_builder_move_to(pb: &mut PathBuilder, x: f32, y: f32) {
|
||||
pb.move_to(x, y);
|
||||
|
|
|
|||
13
third_party/rust/wpf-gpu-raster/src/lib.rs
vendored
13
third_party/rust/wpf-gpu-raster/src/lib.rs
vendored
|
|
@ -114,6 +114,15 @@ impl PathBuilder {
|
|||
rasterization_truncates: false,
|
||||
}
|
||||
}
|
||||
fn reset(&mut self) {
|
||||
*self = Self {
|
||||
points: std::mem::take(&mut self.points),
|
||||
types: std::mem::take(&mut self.types),
|
||||
..Self::new()
|
||||
};
|
||||
self.points.clear();
|
||||
self.types.clear();
|
||||
}
|
||||
fn add_point(&mut self, x: f32, y: f32) {
|
||||
self.current_point = Some(MilPoint2F{X: x, Y: y});
|
||||
// Transform from pixel corner at 0.0 to pixel center at 0.0. Scale into 28.4 range.
|
||||
|
|
@ -237,8 +246,8 @@ impl PathBuilder {
|
|||
if self.valid_range && !self.points.is_empty() && !self.types.is_empty() {
|
||||
Some(OutputPath {
|
||||
fill_mode: self.fill_mode,
|
||||
points: std::mem::take(&mut self.points).into_boxed_slice(),
|
||||
types: std::mem::take(&mut self.types).into_boxed_slice(),
|
||||
points: Box::from(self.points.as_slice()),
|
||||
types: Box::from(self.types.as_slice()),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ localization-ffi = { path = "../../../../intl/l10n/rust/localization-ffi" }
|
|||
processtools = { path = "../../../components/processtools" }
|
||||
qcms = { path = "../../../../gfx/qcms", features = ["c_bindings", "neon"], default-features = false }
|
||||
|
||||
wpf-gpu-raster = { git = "https://github.com/FirefoxGraphics/wpf-gpu-raster", rev = "5ab6fe33d00021325ee920b3c10526dc8301cf46" }
|
||||
wpf-gpu-raster = { git = "https://github.com/FirefoxGraphics/wpf-gpu-raster", rev = "99979da091fd58fba8477e7fcdf5ec0727102916" }
|
||||
aa-stroke = { git = "https://github.com/FirefoxGraphics/aa-stroke", rev = "ed4206ea11703580cd1d4fc63371a527b29d8252" }
|
||||
|
||||
# Force url to stay at 2.1.0. See bug 1734538.
|
||||
|
|
|
|||
Loading…
Reference in a new issue