mirror of
https://github.com/italicsjenga/vello.git
synced 2025-01-10 12:41:30 +11:00
Progress on wiring up fills
Write the right_edge to the binning output. More work on encoding the fill/stroke distinction and plumbing that through the pipeline. This is a bit unsatisfying because of the code duplication; having an extra fill/stroke bool might be better, but I want to avoid making the structs bigger (this could be solved by better packing in the struct encoding). Fills are plumbed through to the last stage. Backdrop is WIP.
This commit is contained in:
parent
03da52cff8
commit
076e6d600d
|
@ -3,7 +3,14 @@ use piet_gpu_derive::piet_gpu;
|
|||
piet_gpu! {
|
||||
#[gpu_write]
|
||||
mod annotated {
|
||||
struct AnnoLineSeg {
|
||||
struct AnnoFillLineSeg {
|
||||
p0: [f32; 2],
|
||||
p1: [f32; 2],
|
||||
// A note: the layout of this struct is shared with
|
||||
// AnnoStrokeLineSeg. In that case, we actually write
|
||||
// [0.0, 0.0] as the stroke field, to minimize divergence.
|
||||
}
|
||||
struct AnnoStrokeLineSeg {
|
||||
p0: [f32; 2],
|
||||
p1: [f32; 2],
|
||||
// halfwidth in both x and y for binning
|
||||
|
@ -35,8 +42,8 @@ piet_gpu! {
|
|||
}
|
||||
enum Annotated {
|
||||
Nop,
|
||||
// The segments need a flag to indicate fill/stroke
|
||||
Line(AnnoLineSeg),
|
||||
FillLine(AnnoFillLineSeg),
|
||||
StrokeLine(AnnoStrokeLineSeg),
|
||||
Quad(AnnoQuadSeg),
|
||||
Cubic(AnnoCubicSeg),
|
||||
Stroke(AnnoStroke),
|
||||
|
|
|
@ -7,6 +7,9 @@ piet_gpu! {
|
|||
mod bins {
|
||||
struct BinInstance {
|
||||
element_ix: u32,
|
||||
// Right edge of the bounding box of the associated fill
|
||||
// element; used in backdrop computation.
|
||||
right_edge: f32,
|
||||
}
|
||||
|
||||
struct BinChunk {
|
||||
|
|
|
@ -85,8 +85,15 @@ piet_gpu! {
|
|||
}
|
||||
enum Element {
|
||||
Nop,
|
||||
// The segments need a flag to indicate fill/stroke
|
||||
Line(LineSeg),
|
||||
// Another approach to encoding would be to use a single
|
||||
// variant but have a bool for fill/stroke. This could be
|
||||
// packed into the tag, so the on-the-wire representation
|
||||
// would be very similar to what's here.
|
||||
StrokeLine(LineSeg),
|
||||
FillLine(LineSeg),
|
||||
|
||||
// Note: we'll need to handle the stroke/fill distinction
|
||||
// for these as well, when we do flattening on the GPU.
|
||||
Quad(QuadSeg),
|
||||
Cubic(CubicSeg),
|
||||
Stroke(Stroke),
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
// Code auto-generated by piet-gpu-derive
|
||||
|
||||
struct AnnoLineSegRef {
|
||||
struct AnnoFillLineSegRef {
|
||||
uint offset;
|
||||
};
|
||||
|
||||
struct AnnoStrokeLineSegRef {
|
||||
uint offset;
|
||||
};
|
||||
|
||||
|
@ -24,16 +28,27 @@ struct AnnotatedRef {
|
|||
uint offset;
|
||||
};
|
||||
|
||||
struct AnnoLineSeg {
|
||||
struct AnnoFillLineSeg {
|
||||
vec2 p0;
|
||||
vec2 p1;
|
||||
};
|
||||
|
||||
#define AnnoFillLineSeg_size 16
|
||||
|
||||
AnnoFillLineSegRef AnnoFillLineSeg_index(AnnoFillLineSegRef ref, uint index) {
|
||||
return AnnoFillLineSegRef(ref.offset + index * AnnoFillLineSeg_size);
|
||||
}
|
||||
|
||||
struct AnnoStrokeLineSeg {
|
||||
vec2 p0;
|
||||
vec2 p1;
|
||||
vec2 stroke;
|
||||
};
|
||||
|
||||
#define AnnoLineSeg_size 24
|
||||
#define AnnoStrokeLineSeg_size 24
|
||||
|
||||
AnnoLineSegRef AnnoLineSeg_index(AnnoLineSegRef ref, uint index) {
|
||||
return AnnoLineSegRef(ref.offset + index * AnnoLineSeg_size);
|
||||
AnnoStrokeLineSegRef AnnoStrokeLineSeg_index(AnnoStrokeLineSegRef ref, uint index) {
|
||||
return AnnoStrokeLineSegRef(ref.offset + index * AnnoStrokeLineSeg_size);
|
||||
}
|
||||
|
||||
struct AnnoQuadSeg {
|
||||
|
@ -87,18 +102,39 @@ AnnoStrokeRef AnnoStroke_index(AnnoStrokeRef ref, uint index) {
|
|||
}
|
||||
|
||||
#define Annotated_Nop 0
|
||||
#define Annotated_Line 1
|
||||
#define Annotated_Quad 2
|
||||
#define Annotated_Cubic 3
|
||||
#define Annotated_Stroke 4
|
||||
#define Annotated_Fill 5
|
||||
#define Annotated_FillLine 1
|
||||
#define Annotated_StrokeLine 2
|
||||
#define Annotated_Quad 3
|
||||
#define Annotated_Cubic 4
|
||||
#define Annotated_Stroke 5
|
||||
#define Annotated_Fill 6
|
||||
#define Annotated_size 44
|
||||
|
||||
AnnotatedRef Annotated_index(AnnotatedRef ref, uint index) {
|
||||
return AnnotatedRef(ref.offset + index * Annotated_size);
|
||||
}
|
||||
|
||||
AnnoLineSeg AnnoLineSeg_read(AnnoLineSegRef ref) {
|
||||
AnnoFillLineSeg AnnoFillLineSeg_read(AnnoFillLineSegRef ref) {
|
||||
uint ix = ref.offset >> 2;
|
||||
uint raw0 = annotated[ix + 0];
|
||||
uint raw1 = annotated[ix + 1];
|
||||
uint raw2 = annotated[ix + 2];
|
||||
uint raw3 = annotated[ix + 3];
|
||||
AnnoFillLineSeg s;
|
||||
s.p0 = vec2(uintBitsToFloat(raw0), uintBitsToFloat(raw1));
|
||||
s.p1 = vec2(uintBitsToFloat(raw2), uintBitsToFloat(raw3));
|
||||
return s;
|
||||
}
|
||||
|
||||
void AnnoFillLineSeg_write(AnnoFillLineSegRef ref, AnnoFillLineSeg s) {
|
||||
uint ix = ref.offset >> 2;
|
||||
annotated[ix + 0] = floatBitsToUint(s.p0.x);
|
||||
annotated[ix + 1] = floatBitsToUint(s.p0.y);
|
||||
annotated[ix + 2] = floatBitsToUint(s.p1.x);
|
||||
annotated[ix + 3] = floatBitsToUint(s.p1.y);
|
||||
}
|
||||
|
||||
AnnoStrokeLineSeg AnnoStrokeLineSeg_read(AnnoStrokeLineSegRef ref) {
|
||||
uint ix = ref.offset >> 2;
|
||||
uint raw0 = annotated[ix + 0];
|
||||
uint raw1 = annotated[ix + 1];
|
||||
|
@ -106,14 +142,14 @@ AnnoLineSeg AnnoLineSeg_read(AnnoLineSegRef ref) {
|
|||
uint raw3 = annotated[ix + 3];
|
||||
uint raw4 = annotated[ix + 4];
|
||||
uint raw5 = annotated[ix + 5];
|
||||
AnnoLineSeg s;
|
||||
AnnoStrokeLineSeg s;
|
||||
s.p0 = vec2(uintBitsToFloat(raw0), uintBitsToFloat(raw1));
|
||||
s.p1 = vec2(uintBitsToFloat(raw2), uintBitsToFloat(raw3));
|
||||
s.stroke = vec2(uintBitsToFloat(raw4), uintBitsToFloat(raw5));
|
||||
return s;
|
||||
}
|
||||
|
||||
void AnnoLineSeg_write(AnnoLineSegRef ref, AnnoLineSeg s) {
|
||||
void AnnoStrokeLineSeg_write(AnnoStrokeLineSegRef ref, AnnoStrokeLineSeg s) {
|
||||
uint ix = ref.offset >> 2;
|
||||
annotated[ix + 0] = floatBitsToUint(s.p0.x);
|
||||
annotated[ix + 1] = floatBitsToUint(s.p0.y);
|
||||
|
@ -239,8 +275,12 @@ uint Annotated_tag(AnnotatedRef ref) {
|
|||
return annotated[ref.offset >> 2];
|
||||
}
|
||||
|
||||
AnnoLineSeg Annotated_Line_read(AnnotatedRef ref) {
|
||||
return AnnoLineSeg_read(AnnoLineSegRef(ref.offset + 4));
|
||||
AnnoFillLineSeg Annotated_FillLine_read(AnnotatedRef ref) {
|
||||
return AnnoFillLineSeg_read(AnnoFillLineSegRef(ref.offset + 4));
|
||||
}
|
||||
|
||||
AnnoStrokeLineSeg Annotated_StrokeLine_read(AnnotatedRef ref) {
|
||||
return AnnoStrokeLineSeg_read(AnnoStrokeLineSegRef(ref.offset + 4));
|
||||
}
|
||||
|
||||
AnnoQuadSeg Annotated_Quad_read(AnnotatedRef ref) {
|
||||
|
@ -263,9 +303,14 @@ void Annotated_Nop_write(AnnotatedRef ref) {
|
|||
annotated[ref.offset >> 2] = Annotated_Nop;
|
||||
}
|
||||
|
||||
void Annotated_Line_write(AnnotatedRef ref, AnnoLineSeg s) {
|
||||
annotated[ref.offset >> 2] = Annotated_Line;
|
||||
AnnoLineSeg_write(AnnoLineSegRef(ref.offset + 4), s);
|
||||
void Annotated_FillLine_write(AnnotatedRef ref, AnnoFillLineSeg s) {
|
||||
annotated[ref.offset >> 2] = Annotated_FillLine;
|
||||
AnnoFillLineSeg_write(AnnoFillLineSegRef(ref.offset + 4), s);
|
||||
}
|
||||
|
||||
void Annotated_StrokeLine_write(AnnotatedRef ref, AnnoStrokeLineSeg s) {
|
||||
annotated[ref.offset >> 2] = Annotated_StrokeLine;
|
||||
AnnoStrokeLineSeg_write(AnnoStrokeLineSegRef(ref.offset + 4), s);
|
||||
}
|
||||
|
||||
void Annotated_Quad_write(AnnotatedRef ref, AnnoQuadSeg s) {
|
||||
|
|
|
@ -84,8 +84,9 @@ void main() {
|
|||
int x0 = 0, y0 = 0, x1 = 0, y1 = 0;
|
||||
float my_right_edge = INFINITY;
|
||||
switch (tag) {
|
||||
case Annotated_Line:
|
||||
AnnoLineSeg line = Annotated_Line_read(ref);
|
||||
case Annotated_FillLine:
|
||||
case Annotated_StrokeLine:
|
||||
AnnoStrokeLineSeg line = Annotated_StrokeLine_read(ref);
|
||||
x0 = int(floor((min(line.p0.x, line.p1.x) - line.stroke.x) * SX));
|
||||
y0 = int(floor((min(line.p0.y, line.p1.y) - line.stroke.y) * SY));
|
||||
x1 = int(ceil((max(line.p0.x, line.p1.x) + line.stroke.x) * SX));
|
||||
|
@ -107,7 +108,7 @@ void main() {
|
|||
// If the last element in this partition is a fill edge, then we need to do a
|
||||
// look-forward to find the right edge of its corresponding fill. That data is
|
||||
// recorded in aggregates computed in the element processing pass.
|
||||
if (gl_LocalInvocationID.x == N_TILE - 1 && tag == Annotated_Line) {
|
||||
if (gl_LocalInvocationID.x == N_TILE - 1 && tag == Annotated_FillLine) {
|
||||
uint aggregate_ix = (my_tile + 1) * ELEMENT_BINNING_RATIO;
|
||||
// This is sequential but the expectation is that the amount of
|
||||
// look-forward is small (performance may degrade in the case
|
||||
|
@ -165,9 +166,9 @@ void main() {
|
|||
uint chunk_new_start;
|
||||
// Refactor to reduce code duplication?
|
||||
if (chunk_n > 0) {
|
||||
uint next_chunk = chunk_ref.offset + BinChunk_size + chunk_n * 4;
|
||||
if (next_chunk + BinChunk_size + min(24, element_count * 4) > wr_limit) {
|
||||
uint alloc_amount = max(BIN_ALLOC, BinChunk_size + element_count * 4);
|
||||
uint next_chunk = chunk_ref.offset + BinChunk_size + chunk_n * BinInstance_size;
|
||||
if (next_chunk + BinChunk_size + min(24, element_count * BinInstance_size) > wr_limit) {
|
||||
uint alloc_amount = max(BIN_ALLOC, BinChunk_size + element_count * BinInstance_size);
|
||||
// could try to reduce fragmentation if BIN_ALLOC is only a bit above needed
|
||||
next_chunk = atomicAdd(alloc, alloc_amount);
|
||||
wr_limit = next_chunk + alloc_amount;
|
||||
|
@ -176,10 +177,10 @@ void main() {
|
|||
chunk_ref = BinChunkRef(next_chunk);
|
||||
}
|
||||
BinInstanceRef instance_ref = BinInstanceRef(chunk_ref.offset + BinChunk_size);
|
||||
if (instance_ref.offset + element_count * 4 > wr_limit) {
|
||||
if (instance_ref.offset + element_count * BinInstance_size > wr_limit) {
|
||||
chunk_end = wr_limit;
|
||||
chunk_n = (wr_limit - instance_ref.offset) / 4;
|
||||
uint alloc_amount = max(BIN_ALLOC, BinChunk_size + (element_count - chunk_n) * 4);
|
||||
chunk_n = (wr_limit - instance_ref.offset) / BinInstance_size;
|
||||
uint alloc_amount = max(BIN_ALLOC, BinChunk_size + (element_count - chunk_n) * BinInstance_size);
|
||||
chunk_new_start = atomicAdd(alloc, alloc_amount);
|
||||
wr_limit = chunk_new_start + alloc_amount;
|
||||
BinChunk_write(chunk_ref, BinChunk(chunk_n, BinChunkRef(chunk_new_start)));
|
||||
|
@ -209,11 +210,11 @@ void main() {
|
|||
if (my_slice > 0) {
|
||||
idx += count[my_slice - 1][bin_ix];
|
||||
}
|
||||
uint out_offset = sh_chunk_start[bin_ix] + idx * 4;
|
||||
uint out_offset = sh_chunk_start[bin_ix] + idx * BinInstance_size;
|
||||
if (out_offset >= sh_chunk_end[bin_ix]) {
|
||||
out_offset += sh_chunk_jump[bin_ix];
|
||||
}
|
||||
BinInstance_write(BinInstanceRef(out_offset), BinInstance(element_ix));
|
||||
BinInstance_write(BinInstanceRef(out_offset), BinInstance(element_ix, my_right_edge));
|
||||
}
|
||||
x++;
|
||||
if (x == x1) {
|
||||
|
|
Binary file not shown.
|
@ -10,9 +10,10 @@ struct BinChunkRef {
|
|||
|
||||
struct BinInstance {
|
||||
uint element_ix;
|
||||
float right_edge;
|
||||
};
|
||||
|
||||
#define BinInstance_size 4
|
||||
#define BinInstance_size 8
|
||||
|
||||
BinInstanceRef BinInstance_index(BinInstanceRef ref, uint index) {
|
||||
return BinInstanceRef(ref.offset + index * BinInstance_size);
|
||||
|
@ -32,14 +33,17 @@ BinChunkRef BinChunk_index(BinChunkRef ref, uint index) {
|
|||
BinInstance BinInstance_read(BinInstanceRef ref) {
|
||||
uint ix = ref.offset >> 2;
|
||||
uint raw0 = bins[ix + 0];
|
||||
uint raw1 = bins[ix + 1];
|
||||
BinInstance s;
|
||||
s.element_ix = raw0;
|
||||
s.right_edge = uintBitsToFloat(raw1);
|
||||
return s;
|
||||
}
|
||||
|
||||
void BinInstance_write(BinInstanceRef ref, BinInstance s) {
|
||||
uint ix = ref.offset >> 2;
|
||||
bins[ix + 0] = s.element_ix;
|
||||
bins[ix + 1] = floatBitsToUint(s.right_edge);
|
||||
}
|
||||
|
||||
BinChunk BinChunk_read(BinChunkRef ref) {
|
||||
|
|
|
@ -30,6 +30,7 @@ layout(set = 0, binding = 3) buffer PtclBuf {
|
|||
#define N_RINGBUF 512
|
||||
|
||||
shared uint sh_elements[N_RINGBUF];
|
||||
shared float sh_right_edge[N_RINGBUF];
|
||||
shared uint sh_chunk[N_WG];
|
||||
shared uint sh_chunk_next[N_WG];
|
||||
shared uint sh_chunk_n[N_WG];
|
||||
|
@ -41,6 +42,7 @@ shared uint sh_selected_n;
|
|||
shared uint sh_elements_ref;
|
||||
|
||||
shared uint sh_bitmaps[N_SLICE][N_TILE];
|
||||
shared uint sh_backdrop[N_SLICE][N_TILE];
|
||||
|
||||
// scale factors useful for converting coordinates to tiles
|
||||
#define SX (1.0 / float(TILE_WIDTH_PX))
|
||||
|
@ -113,6 +115,7 @@ void main() {
|
|||
while (true) {
|
||||
for (uint i = 0; i < N_SLICE; i++) {
|
||||
sh_bitmaps[i][th_ix] = 0;
|
||||
sh_backdrop[i][th_ix] = 0;
|
||||
}
|
||||
|
||||
while (wr_ix - rd_ix <= N_TILE) {
|
||||
|
@ -157,8 +160,10 @@ void main() {
|
|||
}
|
||||
BinInstanceRef inst_ref = BinInstanceRef(sh_elements_ref);
|
||||
if (th_ix < chunk_n) {
|
||||
uint el = BinInstance_read(BinInstance_index(inst_ref, th_ix)).element_ix;
|
||||
sh_elements[(wr_ix + th_ix) % N_RINGBUF] = el;
|
||||
BinInstance inst = BinInstance_read(BinInstance_index(inst_ref, th_ix));
|
||||
uint wr_el_ix = (wr_ix + th_ix) % N_RINGBUF;
|
||||
sh_elements[wr_el_ix] = inst.element_ix;
|
||||
sh_right_edge[wr_el_ix] = inst.right_edge;
|
||||
}
|
||||
wr_ix += chunk_n;
|
||||
}
|
||||
|
@ -180,8 +185,9 @@ void main() {
|
|||
// Bounding box of element in pixel coordinates.
|
||||
float xmin, xmax, ymin, ymax;
|
||||
switch (tag) {
|
||||
case Annotated_Line:
|
||||
AnnoLineSeg line = Annotated_Line_read(ref);
|
||||
case Annotated_FillLine:
|
||||
case Annotated_StrokeLine:
|
||||
AnnoStrokeLineSeg line = Annotated_StrokeLine_read(ref);
|
||||
xmin = min(line.p0.x, line.p1.x) - line.stroke.x;
|
||||
xmax = max(line.p0.x, line.p1.x) + line.stroke.x;
|
||||
ymin = min(line.p0.y, line.p1.y) - line.stroke.y;
|
||||
|
@ -214,7 +220,7 @@ void main() {
|
|||
break;
|
||||
}
|
||||
|
||||
// Draw the coverage area into the bitmaks. This uses an algorithm
|
||||
// Draw the coverage area into the bitmasks. This uses an algorithm
|
||||
// that computes the coverage of a span for given scanline.
|
||||
|
||||
// Compute bounding box in tiles and clip to this bin.
|
||||
|
@ -263,15 +269,27 @@ void main() {
|
|||
tag = Annotated_tag(ref);
|
||||
|
||||
switch (tag) {
|
||||
case Annotated_Line:
|
||||
AnnoLineSeg line = Annotated_Line_read(ref);
|
||||
case Annotated_FillLine:
|
||||
case Annotated_StrokeLine:
|
||||
AnnoStrokeLineSeg line = Annotated_StrokeLine_read(ref);
|
||||
Segment seg = Segment(line.p0, line.p1);
|
||||
alloc_chunk(chunk_n_segs, seg_chunk_ref, first_seg_chunk, seg_limit);
|
||||
Segment_write(SegmentRef(seg_chunk_ref.offset + SegChunk_size + Segment_size * chunk_n_segs), seg);
|
||||
chunk_n_segs++;
|
||||
break;
|
||||
case Annotated_Fill:
|
||||
if (chunk_n_segs > 0) {
|
||||
AnnoFill fill = Annotated_Fill_read(ref);
|
||||
SegChunk_write(seg_chunk_ref, SegChunk(chunk_n_segs, SegChunkRef(0)));
|
||||
seg_chunk_ref.offset += SegChunk_size + Segment_size * chunk_n_segs;
|
||||
CmdFill cmd_fill;
|
||||
cmd_fill.seg_ref = first_seg_chunk.offset;
|
||||
cmd_fill.rgba_color = fill.rgba_color;
|
||||
alloc_cmd(cmd_ref, cmd_limit);
|
||||
Cmd_Fill_write(cmd_ref, cmd_fill);
|
||||
cmd_ref.offset += Cmd_size;
|
||||
chunk_n_segs = 0;
|
||||
}
|
||||
break;
|
||||
case Annotated_Stroke:
|
||||
if (chunk_n_segs > 0) {
|
||||
|
|
Binary file not shown.
|
@ -98,8 +98,9 @@ State map_element(ElementRef ref) {
|
|||
c.linewidth = 1.0; // TODO should be 0.0
|
||||
c.flags = 0;
|
||||
switch (tag) {
|
||||
case Element_Line:
|
||||
LineSeg line = Element_Line_read(ref);
|
||||
case Element_FillLine:
|
||||
case Element_StrokeLine:
|
||||
LineSeg line = Element_FillLine_read(ref);
|
||||
c.bbox.xy = min(line.p0, line.p1);
|
||||
c.bbox.zw = max(line.p0, line.p1);
|
||||
break;
|
||||
|
@ -272,13 +273,22 @@ void main() {
|
|||
AnnotatedRef out_ref = AnnotatedRef((ix + i) * Annotated_size);
|
||||
uint tag = Element_tag(this_ref);
|
||||
switch (tag) {
|
||||
case Element_Line:
|
||||
LineSeg line = Element_Line_read(this_ref);
|
||||
AnnoLineSeg anno_line;
|
||||
case Element_FillLine:
|
||||
case Element_StrokeLine:
|
||||
LineSeg line = Element_StrokeLine_read(this_ref);
|
||||
AnnoStrokeLineSeg anno_line;
|
||||
anno_line.p0 = st.mat.xz * line.p0.x + st.mat.yw * line.p0.y + st.translate;
|
||||
anno_line.p1 = st.mat.xz * line.p1.x + st.mat.yw * line.p1.y + st.translate;
|
||||
if (tag == Element_StrokeLine) {
|
||||
anno_line.stroke = get_linewidth(st);
|
||||
Annotated_Line_write(out_ref, anno_line);
|
||||
} else {
|
||||
anno_line.stroke = vec2(0.0);
|
||||
}
|
||||
// We do encoding a bit by hand to minimize divergence. Another approach
|
||||
// would be to have a fill/stroke bool.
|
||||
uint out_tag = tag == Element_FillLine ? Annotated_FillLine : Annotated_StrokeLine;
|
||||
annotated[out_ref.offset >> 2] = out_tag;
|
||||
AnnoStrokeLineSeg_write(AnnoStrokeLineSegRef(out_ref.offset + 4), anno_line);
|
||||
break;
|
||||
case Element_Stroke:
|
||||
Stroke stroke = Element_Stroke_read(this_ref);
|
||||
|
|
Binary file not shown.
|
@ -238,13 +238,14 @@ TransformRef Transform_index(TransformRef ref, uint index) {
|
|||
}
|
||||
|
||||
#define Element_Nop 0
|
||||
#define Element_Line 1
|
||||
#define Element_Quad 2
|
||||
#define Element_Cubic 3
|
||||
#define Element_Stroke 4
|
||||
#define Element_Fill 5
|
||||
#define Element_SetLineWidth 6
|
||||
#define Element_Transform 7
|
||||
#define Element_StrokeLine 1
|
||||
#define Element_FillLine 2
|
||||
#define Element_Quad 3
|
||||
#define Element_Cubic 4
|
||||
#define Element_Stroke 5
|
||||
#define Element_Fill 6
|
||||
#define Element_SetLineWidth 7
|
||||
#define Element_Transform 8
|
||||
#define Element_size 36
|
||||
|
||||
ElementRef Element_index(ElementRef ref, uint index) {
|
||||
|
@ -446,7 +447,11 @@ uint Element_tag(ElementRef ref) {
|
|||
return scene[ref.offset >> 2];
|
||||
}
|
||||
|
||||
LineSeg Element_Line_read(ElementRef ref) {
|
||||
LineSeg Element_StrokeLine_read(ElementRef ref) {
|
||||
return LineSeg_read(LineSegRef(ref.offset + 4));
|
||||
}
|
||||
|
||||
LineSeg Element_FillLine_read(ElementRef ref) {
|
||||
return LineSeg_read(LineSegRef(ref.offset + 4));
|
||||
}
|
||||
|
||||
|
|
|
@ -61,8 +61,8 @@ impl PicoSvg {
|
|||
for item in &self.items {
|
||||
match item {
|
||||
Item::Fill(fill_item) => {
|
||||
//rc.fill(&fill_item.path, &fill_item.color);
|
||||
rc.stroke(&fill_item.path, &fill_item.color, 1.0);
|
||||
rc.fill(&fill_item.path, &fill_item.color);
|
||||
//rc.stroke(&fill_item.path, &fill_item.color, 1.0);
|
||||
}
|
||||
Item::Stroke(stroke_item) => {
|
||||
rc.stroke(&stroke_item.path, &stroke_item.color, stroke_item.width);
|
||||
|
|
|
@ -94,7 +94,7 @@ impl RenderContext for PietGpuRenderContext {
|
|||
}
|
||||
let brush = brush.make_brush(self, || shape.bounding_box()).into_owned();
|
||||
let path = shape.to_bez_path(TOLERANCE);
|
||||
self.encode_path(path);
|
||||
self.encode_path(path, false);
|
||||
match brush {
|
||||
PietGpuBrush::Solid(rgba_color) => {
|
||||
let stroke = Stroke { rgba_color };
|
||||
|
@ -116,7 +116,7 @@ impl RenderContext for PietGpuRenderContext {
|
|||
fn fill(&mut self, shape: impl Shape, brush: &impl IntoBrush<Self>) {
|
||||
let brush = brush.make_brush(self, || shape.bounding_box()).into_owned();
|
||||
let path = shape.to_bez_path(TOLERANCE);
|
||||
self.encode_path(path);
|
||||
self.encode_path(path, true);
|
||||
match brush {
|
||||
PietGpuBrush::Solid(rgba_color) => {
|
||||
let fill = Fill { rgba_color };
|
||||
|
@ -198,7 +198,15 @@ impl RenderContext for PietGpuRenderContext {
|
|||
}
|
||||
|
||||
impl PietGpuRenderContext {
|
||||
fn encode_path(&mut self, path: impl Iterator<Item = PathEl>) {
|
||||
fn encode_line_seg(&mut self, seg: LineSeg, is_fill: bool) {
|
||||
if is_fill {
|
||||
self.elements.push(Element::FillLine(seg));
|
||||
} else {
|
||||
self.elements.push(Element::StrokeLine(seg));
|
||||
}
|
||||
}
|
||||
|
||||
fn encode_path(&mut self, path: impl Iterator<Item = PathEl>, is_fill: bool) {
|
||||
let flatten = true;
|
||||
if flatten {
|
||||
let mut start_pt = None;
|
||||
|
@ -215,7 +223,7 @@ impl PietGpuRenderContext {
|
|||
p0: last_pt.unwrap(),
|
||||
p1: scene_pt,
|
||||
};
|
||||
self.elements.push(Element::Line(seg));
|
||||
self.encode_line_seg(seg, is_fill);
|
||||
last_pt = Some(scene_pt);
|
||||
}
|
||||
PathEl::ClosePath => {
|
||||
|
@ -224,7 +232,7 @@ impl PietGpuRenderContext {
|
|||
p0: last,
|
||||
p1: start,
|
||||
};
|
||||
self.elements.push(Element::Line(seg));
|
||||
self.encode_line_seg(seg, is_fill);
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
|
@ -246,7 +254,7 @@ impl PietGpuRenderContext {
|
|||
p0: last_pt.unwrap(),
|
||||
p1: scene_pt,
|
||||
};
|
||||
self.elements.push(Element::Line(seg));
|
||||
self.encode_line_seg(seg, is_fill);
|
||||
last_pt = Some(scene_pt);
|
||||
}
|
||||
PathEl::QuadTo(p1, p2) => {
|
||||
|
@ -279,7 +287,7 @@ impl PietGpuRenderContext {
|
|||
p0: last,
|
||||
p1: start,
|
||||
};
|
||||
self.elements.push(Element::Line(seg));
|
||||
self.encode_line_seg(seg, is_fill);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue