renumber tiles, etc

This commit is contained in:
Patrick Walton 2018-12-19 15:58:54 -08:00
parent 56c7a76d98
commit 0e0064eff1
1 changed files with 81 additions and 89 deletions

View File

@ -85,14 +85,16 @@ fn main() {
println!("{:.3}ms elapsed", elapsed_ms / runs as f64);
println!("{} fill primitives generated", built_scene.fills.len());
println!("{} tiles ({} solid, {} mask) generated",
built_scene.tiles.len(),
built_scene.solid_tile_indices.len(),
built_scene.mask_tile_indices.len());
built_scene.solid_tiles.len() + built_scene.mask_tiles.len(),
built_scene.solid_tiles.len(),
built_scene.mask_tiles.len());
/*
println!("solid tiles:");
for &index in &built_scene.solid_tile_indices {
println!("... {}: {:?}", index, built_scene.tiles[index as usize]);
for (index, tile) in built_scene.solid_tiles.iter().enumerate() {
println!("... {}: {:?}", index, tile);
}
*/
if let Some(output_path) = output_path {
built_scene.write(&mut BufWriter::new(File::create(output_path).unwrap())).unwrap();
@ -317,7 +319,6 @@ impl Scene {
}
fn push_svg_path(&mut self, value: &str, style: StyleId, name: String) {
/*
if self.get_style(style).stroke_width > 0.0 {
let computed_style = self.get_style(style);
let mut path_parser = PathParser::from(&*value);
@ -335,7 +336,6 @@ impl Scene {
self.bounds = self.bounds.union(&outline.bounds);
self.objects.push(PathObject::new(outline, color, style, name.clone()));
}
*/
if self.get_style(style).fill_color.is_some() {
let computed_style = self.get_style(style);
@ -416,19 +416,16 @@ impl Outline {
&mut bounding_points);
}
PathEvent::QuadraticTo(ctrl, to) => {
/*
current_contour.push_transformed_point(&ctrl,
PointFlags::CONTROL_POINT_0,
&transform,
&mut bounding_points);
*/
current_contour.push_transformed_point(&to,
PointFlags::empty(),
&transform,
&mut bounding_points);
}
PathEvent::CubicTo(ctrl0, ctrl1, to) => {
/*
current_contour.push_transformed_point(&ctrl0,
PointFlags::CONTROL_POINT_0,
&transform,
@ -437,7 +434,6 @@ impl Outline {
PointFlags::CONTROL_POINT_1,
&transform,
&mut bounding_points);
*/
current_contour.push_transformed_point(&to,
PointFlags::empty(),
&transform,
@ -794,14 +790,10 @@ impl Segment {
}
fn generate_fill_primitives(&self,
first_tile_index: u32,
strip_origin: &Point2D<f32>,
primitives: &mut Vec<FillPrimitive>) {
if let Some(ref line_segment) = self.as_line_segment() {
generate_fill_primitives_for_line(line_segment,
first_tile_index,
strip_origin,
primitives);
generate_fill_primitives_for_line(line_segment, strip_origin, primitives);
return;
}
@ -810,15 +802,11 @@ impl Segment {
let flattener = Flattened::new(segment, FLATTENING_TOLERANCE);
let mut from = self.from;
for to in flattener {
generate_fill_primitives_for_line(&LineSegment { from, to },
first_tile_index,
strip_origin,
primitives);
generate_fill_primitives_for_line(&LineSegment { from, to }, strip_origin, primitives);
from = to;
}
fn generate_fill_primitives_for_line(segment: &LineSegment<f32>,
first_tile_index: u32,
strip_origin: &Point2D<f32>,
primitives: &mut Vec<FillPrimitive>) {
let mut segment = *segment;
@ -838,7 +826,7 @@ impl Segment {
primitives.push(FillPrimitive {
from: segment.from - tile_offset,
to: segment.to - tile_offset,
tile_index: first_tile_index + from_tile_index,
tile_index: from_tile_index,
});
break;
}
@ -854,7 +842,7 @@ impl Segment {
primitives.push(FillPrimitive {
from: prev_segment.from - tile_offset,
to: prev_segment.to - tile_offset,
tile_index: first_tile_index + from_tile_index,
tile_index: from_tile_index,
});
from_tile_index = next_tile_index;
@ -962,14 +950,13 @@ impl<'o, 'p> Tiler<'o, 'p> {
let strip_right_extent = f32::ceil(bounds.max_x() / TILE_WIDTH) * TILE_WIDTH;
let tiles_across = ((strip_right_extent - strip_origin.x) / TILE_WIDTH) as usize;
let mut strip_fills = vec![];
let mut strip_tiles = Vec::with_capacity(tiles_across);
let mut used_strip_tiles = FixedBitSet::with_capacity(tiles_across);
// Generate strips.
while strip_origin.y < bounds.max_y() {
// Determine the first tile index.
let first_tile_index = self.built_scene.tiles.len() as u32;
// Determine strip bounds.
let strip_extent = Point2D::new(strip_right_extent, strip_origin.y + TILE_HEIGHT);
let strip_bounds = Rect::new(strip_origin,
@ -982,13 +969,16 @@ impl<'o, 'p> Tiler<'o, 'p> {
None => false,
};
// Allocate tiles.
// Reset strip info.
strip_fills.clear();
strip_tiles.clear();
used_strip_tiles.clear();
// Allocate tiles.
let mut tile_left = strip_origin.x;
while tile_left < strip_right_extent {
let strip_origin = Point2D::new(tile_left, strip_origin.y);
strip_tiles.push(TilePrimitive::new(&strip_origin, self.fill_color));
strip_tiles.push(MaskTilePrimitive::new(&strip_origin, self.fill_color));
tile_left += TILE_WIDTH;
}
@ -1016,11 +1006,10 @@ impl<'o, 'p> Tiler<'o, 'p> {
} else {
let left = Point2D::new(interval.start, strip_origin.y);
let right = Point2D::new(interval.end, strip_origin.y);
let global_tile_index = first_tile_index + strip_tile_index as u32;
self.built_scene.fills.push(FillPrimitive {
strip_fills.push(FillPrimitive {
from: if interval.winding < 0.0 { left } else { right },
to: if interval.winding < 0.0 { right } else { left },
tile_index: global_tile_index,
tile_index: strip_tile_index as u32,
});
}
@ -1030,10 +1019,9 @@ impl<'o, 'p> Tiler<'o, 'p> {
// Process old active edges.
for active_edge in &mut self.active_edges {
let fills = if above_view_box { None } else { Some(&mut self.built_scene.fills) };
let fills = if above_view_box { None } else { Some(&mut strip_fills) };
process_active_edge(active_edge,
&strip_bounds,
first_tile_index,
fills,
&mut self.active_intervals,
&mut used_strip_tiles)
@ -1051,15 +1039,9 @@ impl<'o, 'p> Tiler<'o, 'p> {
if !segment.is_degenerate() {
if let Some(mut segment) = segment.clip_x(strip_range) {
let fills = if above_view_box {
None
} else {
Some(&mut self.built_scene.fills)
};
let fills = if above_view_box { None } else { Some(&mut strip_fills) };
process_active_edge(&mut segment,
&strip_bounds,
first_tile_index,
fills,
&mut self.active_intervals,
&mut used_strip_tiles);
@ -1073,20 +1055,33 @@ impl<'o, 'p> Tiler<'o, 'p> {
next_edge_index_index += 1;
}
// Flush tiles.
// Finalize tiles.
if !above_view_box {
for tile_index in 0..tiles_across {
self.built_scene.tiles.push(strip_tiles[tile_index]);
// Flush tiles.
for (tile_index, tile) in strip_tiles.iter().enumerate() {
if used_strip_tiles.contains(tile_index) {
self.built_scene
.mask_tile_indices
.push(first_tile_index + tile_index as u32)
} else if strip_tiles[tile_index].backdrop != 0.0 {
self.built_scene
.solid_tile_indices
.push(first_tile_index + tile_index as u32)
self.built_scene.mask_tiles.push(*tile);
} else if tile.backdrop != 0.0 {
self.built_scene.solid_tiles.push(SolidTilePrimitive {
position: tile.position,
color: tile.color,
});
}
}
// Flush fills.
//
// TODO(pcwalton): Don't use a temporary vector to hold these.
let first_tile_index = self.built_scene.mask_tiles.len() as u32;
for fill in &strip_fills {
let real_tile_index = first_tile_index +
used_strip_tiles.count_ones(0..(fill.tile_index as usize)) as u32;
self.built_scene.fills.push(FillPrimitive {
from: fill.from,
to: fill.to,
tile_index: real_tile_index,
});
}
}
strip_origin.y = strip_extent.y;
@ -1096,7 +1091,6 @@ impl<'o, 'p> Tiler<'o, 'p> {
fn process_active_edge(active_edge: &mut Segment,
strip_bounds: &Rect<f32>,
first_tile_index: u32,
mut fills: Option<&mut Vec<FillPrimitive>>,
active_intervals: &mut Intervals,
used_tiles: &mut FixedBitSet) {
@ -1113,9 +1107,7 @@ fn process_active_edge(active_edge: &mut Segment,
if segment.from.y < strip_extent.y || segment.to.y < strip_extent.y {
if let Some(ref mut fills) = fills {
active_edge.generate_fill_primitives(first_tile_index,
&strip_bounds.origin,
*fills);
active_edge.generate_fill_primitives(&strip_bounds.origin, *fills);
}
// FIXME(pcwalton): Assumes x-monotonicity!
@ -1155,9 +1147,8 @@ fn process_active_edge(active_edge: &mut Segment,
#[derive(Debug)]
struct BuiltScene {
fills: Vec<FillPrimitive>,
tiles: Vec<TilePrimitive>,
solid_tile_indices: Vec<u32>,
mask_tile_indices: Vec<u32>,
solid_tiles: Vec<SolidTilePrimitive>,
mask_tiles: Vec<MaskTilePrimitive>,
}
#[derive(Clone, Copy, Debug)]
@ -1168,12 +1159,18 @@ struct FillPrimitive {
}
#[derive(Clone, Copy, Debug)]
struct TilePrimitive {
struct SolidTilePrimitive {
position: Point2D<f32>,
backdrop: f32,
color: ColorU,
}
#[derive(Clone, Copy, Debug)]
struct MaskTilePrimitive {
position: Point2D<f32>,
color: ColorU,
backdrop: f32,
}
#[derive(Clone, Copy, Debug)]
struct ColorU {
r: u8,
@ -1184,26 +1181,19 @@ struct ColorU {
impl BuiltScene {
fn new() -> BuiltScene {
BuiltScene {
fills: vec![],
tiles: vec![],
solid_tile_indices: vec![],
mask_tile_indices: vec![],
}
BuiltScene { fills: vec![], solid_tiles: vec![], mask_tiles: vec![] }
}
fn write<W>(&self, writer: &mut W) -> io::Result<()> where W: Write {
writer.write_all(b"RIFF")?;
let fill_size = self.fills.len() * mem::size_of::<FillPrimitive>();
let tile_size = self.tiles.len() * mem::size_of::<TilePrimitive>();
let solid_tile_indices_size = self.solid_tile_indices.len() * mem::size_of::<u32>();
let mask_tile_indices_size = self.mask_tile_indices.len() * mem::size_of::<u32>();
let solid_tiles_size = self.solid_tiles.len() * mem::size_of::<SolidTilePrimitive>();
let mask_tiles_size = self.mask_tiles.len() * mem::size_of::<MaskTilePrimitive>();
writer.write_u32::<LittleEndian>((4 +
8 + fill_size +
8 + tile_size +
8 + solid_tile_indices_size +
8 + mask_tile_indices_size) as u32)?;
8 + solid_tiles_size +
8 + mask_tiles_size) as u32)?;
writer.write_all(b"PF3S")?;
@ -1215,27 +1205,23 @@ impl BuiltScene {
writer.write_u32::<LittleEndian>(fill_primitive.tile_index)?;
}
writer.write_all(b"tile")?;
writer.write_u32::<LittleEndian>(tile_size as u32)?;
for tile_primitive in &self.tiles {
writer.write_all(b"soli")?;
writer.write_u32::<LittleEndian>(solid_tiles_size as u32)?;
for &tile_primitive in &self.solid_tiles {
let color = tile_primitive.color;
write_point(writer, &tile_primitive.position)?;
writer.write_all(&[color.r, color.g, color.b, color.a]).unwrap();
}
writer.write_all(b"mask")?;
writer.write_u32::<LittleEndian>(mask_tiles_size as u32)?;
for &tile_primitive in &self.mask_tiles {
let color = tile_primitive.color;
write_point(writer, &tile_primitive.position)?;
writer.write_f32::<LittleEndian>(tile_primitive.backdrop)?;
writer.write_all(&[color.r, color.g, color.b, color.a]).unwrap();
}
writer.write_all(b"soli")?;
writer.write_u32::<LittleEndian>(solid_tile_indices_size as u32)?;
for &index in &self.solid_tile_indices {
writer.write_u32::<LittleEndian>(index)?;
}
writer.write_all(b"mask")?;
writer.write_u32::<LittleEndian>(mask_tile_indices_size as u32)?;
for &index in &self.mask_tile_indices {
writer.write_u32::<LittleEndian>(index)?;
}
return Ok(());
fn write_point<W>(writer: &mut W, point: &Point2D<f32>) -> io::Result<()> where W: Write {
@ -1246,9 +1232,15 @@ impl BuiltScene {
}
}
impl TilePrimitive {
fn new(position: &Point2D<f32>, color: ColorU) -> TilePrimitive {
TilePrimitive { position: *position, backdrop: 0.0, color }
impl SolidTilePrimitive {
fn new(position: &Point2D<f32>, color: ColorU) -> SolidTilePrimitive {
SolidTilePrimitive { position: *position, color }
}
}
impl MaskTilePrimitive {
fn new(position: &Point2D<f32>, color: ColorU) -> MaskTilePrimitive {
MaskTilePrimitive { position: *position, backdrop: 0.0, color }
}
}