[canvas] Set transform matrix as part of primitive and don't replay push/pop during render
This commit is contained in:
parent
b24de5d969
commit
074b17b743
553
src/graphics.c
553
src/graphics.c
|
@ -74,8 +74,6 @@ typedef struct mg_canvas_data
|
|||
|
||||
u64 frameCounter;
|
||||
|
||||
mg_mat2x3 transform;
|
||||
mp_rect clip;
|
||||
mg_attributes attributes;
|
||||
bool textFlip;
|
||||
|
||||
|
@ -90,24 +88,27 @@ typedef struct mg_canvas_data
|
|||
mp_rect clipStack[MG_CLIP_STACK_MAX_DEPTH];
|
||||
u32 clipStackSize;
|
||||
|
||||
vec4 shapeExtents;
|
||||
u32 nextShapeIndex;
|
||||
u32 primitiveCount;
|
||||
mg_primitive primitives[MG_MAX_PRIMITIVE_COUNT];
|
||||
|
||||
u32 shapeFirstVertexIndex;
|
||||
u32 vertexCount;
|
||||
u32 indexCount;
|
||||
|
||||
mg_image currentImage;
|
||||
mp_rect currentSrcRegion;
|
||||
|
||||
mg_resource_pool imagePool;
|
||||
|
||||
vec2 atlasPos;
|
||||
u32 atlasLineHeight;
|
||||
mg_image blankImage;
|
||||
|
||||
//NOTE: these are used at render time
|
||||
mp_rect clip;
|
||||
mg_mat2x3 transform;
|
||||
mg_image currentImage;
|
||||
mp_rect currentSrcRegion;
|
||||
|
||||
vec4 shapeExtents;
|
||||
u32 nextShapeIndex;
|
||||
u32 shapeFirstVertexIndex;
|
||||
u32 vertexCount;
|
||||
u32 indexCount;
|
||||
|
||||
mg_canvas_backend* backend;
|
||||
|
||||
} mg_canvas_data;
|
||||
|
@ -565,12 +566,51 @@ vec2 mg_mat2x3_mul(mg_mat2x3 m, vec2 p)
|
|||
return((vec2){x, y});
|
||||
}
|
||||
|
||||
mg_mat2x3 mg_matrix_stack_top(mg_canvas_data* canvas)
|
||||
{
|
||||
if(canvas->matrixStackSize == 0)
|
||||
{
|
||||
return((mg_mat2x3){1, 0, 0,
|
||||
0, 1, 0});
|
||||
}
|
||||
else
|
||||
{
|
||||
return(canvas->matrixStack[canvas->matrixStackSize-1]);
|
||||
}
|
||||
}
|
||||
|
||||
void mg_matrix_stack_push(mg_canvas_data* canvas, mg_mat2x3 transform)
|
||||
{
|
||||
if(canvas->matrixStackSize >= MG_MATRIX_STACK_MAX_DEPTH)
|
||||
{
|
||||
LOG_ERROR("matrix stack overflow\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
canvas->matrixStack[canvas->matrixStackSize] = transform;
|
||||
canvas->matrixStackSize++;
|
||||
}
|
||||
}
|
||||
|
||||
void mg_matrix_stack_pop(mg_canvas_data* canvas)
|
||||
{
|
||||
if(canvas->matrixStackSize == 0)
|
||||
{
|
||||
LOG_ERROR("matrix stack underflow\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
canvas->matrixStackSize--;
|
||||
mg_matrix_stack_top(canvas);
|
||||
}
|
||||
}
|
||||
|
||||
void mg_push_command(mg_canvas_data* canvas, mg_primitive primitive)
|
||||
{
|
||||
//NOTE(martin): push primitive and updates current stream, eventually patching a pending jump.
|
||||
ASSERT(canvas->primitiveCount < MG_MAX_PRIMITIVE_COUNT);
|
||||
canvas->primitives[canvas->primitiveCount] = primitive;
|
||||
canvas->primitives[canvas->primitiveCount].transform = mg_matrix_stack_top(canvas);
|
||||
canvas->primitiveCount++;
|
||||
}
|
||||
|
||||
|
@ -675,7 +715,7 @@ int* mg_reserve_indices(mg_canvas_data* canvas, u32 indexCount)
|
|||
return(base);
|
||||
}
|
||||
|
||||
void mg_push_vertex(mg_canvas_data* canvas, vec2 pos, vec4 cubic)
|
||||
void mg_push_vertex_cubic(mg_canvas_data* canvas, vec2 pos, vec4 cubic)
|
||||
{
|
||||
canvas->shapeExtents.x = minimum(canvas->shapeExtents.x, pos.x);
|
||||
canvas->shapeExtents.y = minimum(canvas->shapeExtents.y, pos.y);
|
||||
|
@ -689,14 +729,17 @@ void mg_push_vertex(mg_canvas_data* canvas, vec2 pos, vec4 cubic)
|
|||
DEBUG_ASSERT(canvas->nextShapeIndex > 0);
|
||||
|
||||
int shapeIndex = maximum(0, canvas->nextShapeIndex-1);
|
||||
|
||||
u32 index = canvas->vertexCount;
|
||||
canvas->vertexCount++;
|
||||
|
||||
*(vec2*)(((char*)layout->posBuffer) + index*layout->posStride) = screenPos;
|
||||
*(vec4*)(((char*)layout->cubicBuffer) + index*layout->cubicStride) = cubic;
|
||||
*(u32*)(((char*)layout->shapeIndexBuffer) + index*layout->shapeIndexStride) = shapeIndex;
|
||||
}
|
||||
|
||||
canvas->vertexCount++;
|
||||
void mg_push_vertex(mg_canvas_data* canvas, vec2 pos)
|
||||
{
|
||||
mg_push_vertex_cubic(canvas, pos, (vec4){1, 1, 1, 1});
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
// Path Filling
|
||||
|
@ -712,17 +755,9 @@ void mg_render_fill_quadratic(mg_canvas_data* canvas, vec2 p[3])
|
|||
|
||||
i32* indices = mg_reserve_indices(canvas, 3);
|
||||
|
||||
mg_push_vertex(canvas,
|
||||
(vec2){p[0].x, p[0].y},
|
||||
(vec4){0, 0, 0, 1});
|
||||
|
||||
mg_push_vertex(canvas,
|
||||
(vec2){p[1].x, p[1].y},
|
||||
(vec4){0.5, 0, 0.5, 1});
|
||||
|
||||
mg_push_vertex(canvas,
|
||||
(vec2){p[2].x, p[2].y},
|
||||
(vec4){1, 1, 1, 1});
|
||||
mg_push_vertex_cubic(canvas, (vec2){p[0].x, p[0].y}, (vec4){0, 0, 0, 1});
|
||||
mg_push_vertex_cubic(canvas, (vec2){p[1].x, p[1].y}, (vec4){0.5, 0, 0.5, 1});
|
||||
mg_push_vertex_cubic(canvas, (vec2){p[2].x, p[2].y}, (vec4){1, 1, 1, 1});
|
||||
|
||||
indices[0] = baseIndex + 0;
|
||||
indices[1] = baseIndex + 1;
|
||||
|
@ -763,17 +798,9 @@ void mg_split_and_fill_cubic(mg_canvas_data* canvas, vec2 p[4], f32 tSplit)
|
|||
u32 baseIndex = mg_vertices_base_index(canvas);
|
||||
i32* indices = mg_reserve_indices(canvas, 3);
|
||||
|
||||
mg_push_vertex(canvas,
|
||||
(vec2){p[0].x, p[0].y},
|
||||
(vec4){1, 1, 1, 1});
|
||||
|
||||
mg_push_vertex(canvas,
|
||||
(vec2){split.x, split.y},
|
||||
(vec4){1, 1, 1, 1});
|
||||
|
||||
mg_push_vertex(canvas,
|
||||
(vec2){p[3].x, p[3].y},
|
||||
(vec4){1, 1, 1, 1});
|
||||
mg_push_vertex(canvas, (vec2){p[0].x, p[0].y});
|
||||
mg_push_vertex(canvas, (vec2){split.x, split.y});
|
||||
mg_push_vertex(canvas, (vec2){p[3].x, p[3].y});
|
||||
|
||||
indices[0] = baseIndex + 0;
|
||||
indices[1] = baseIndex + 1;
|
||||
|
@ -781,8 +808,6 @@ void mg_split_and_fill_cubic(mg_canvas_data* canvas, vec2 p[4], f32 tSplit)
|
|||
|
||||
mg_render_fill_cubic(canvas, subPointsLow);
|
||||
mg_render_fill_cubic(canvas, subPointsHigh);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void mg_render_fill_cubic(mg_canvas_data* canvas, vec2 p[4])
|
||||
|
@ -1141,8 +1166,7 @@ void mg_render_fill_cubic(mg_canvas_data* canvas, vec2 p[4])
|
|||
{
|
||||
vec4 cubic = testCoords[orderedHullIndices[i]];
|
||||
cubic.w = outsideTest;
|
||||
mg_push_vertex(canvas, p[orderedHullIndices[i]], cubic);
|
||||
|
||||
mg_push_vertex_cubic(canvas, p[orderedHullIndices[i]], cubic);
|
||||
indices[i] = baseIndex + i;
|
||||
}
|
||||
}
|
||||
|
@ -1168,27 +1192,27 @@ void mg_render_fill_cubic(mg_canvas_data* canvas, vec2 p[4])
|
|||
u32 baseIndex = mg_vertices_base_index(canvas);
|
||||
i32* indices = mg_reserve_indices(canvas, 6);
|
||||
|
||||
mg_push_vertex(canvas,
|
||||
mg_push_vertex_cubic(canvas,
|
||||
p[orderedHullIndices[0]],
|
||||
(vec4){vec4_expand_xyz(testCoords[orderedHullIndices[0]]), outsideTest1});
|
||||
|
||||
mg_push_vertex(canvas,
|
||||
mg_push_vertex_cubic(canvas,
|
||||
p[orderedHullIndices[1]],
|
||||
(vec4){vec4_expand_xyz(testCoords[orderedHullIndices[1]]), outsideTest1});
|
||||
|
||||
mg_push_vertex(canvas,
|
||||
mg_push_vertex_cubic(canvas,
|
||||
p[orderedHullIndices[2]],
|
||||
(vec4){vec4_expand_xyz(testCoords[orderedHullIndices[2]]), outsideTest1});
|
||||
|
||||
mg_push_vertex(canvas,
|
||||
mg_push_vertex_cubic(canvas,
|
||||
p[orderedHullIndices[0]],
|
||||
(vec4){vec4_expand_xyz(testCoords[orderedHullIndices[0]]), outsideTest2});
|
||||
|
||||
mg_push_vertex(canvas,
|
||||
mg_push_vertex_cubic(canvas,
|
||||
p[orderedHullIndices[2]],
|
||||
(vec4){vec4_expand_xyz(testCoords[orderedHullIndices[2]]), outsideTest2});
|
||||
|
||||
mg_push_vertex(canvas,
|
||||
mg_push_vertex_cubic(canvas,
|
||||
p[orderedHullIndices[3]],
|
||||
(vec4){vec4_expand_xyz(testCoords[orderedHullIndices[3]]), outsideTest2});
|
||||
|
||||
|
@ -1213,7 +1237,7 @@ void mg_render_fill_cubic(mg_canvas_data* canvas, vec2 p[4])
|
|||
|
||||
for(int i=0; i<4; i++)
|
||||
{
|
||||
mg_push_vertex(canvas,
|
||||
mg_push_vertex_cubic(canvas,
|
||||
p[orderedHullIndices[i]],
|
||||
(vec4){vec4_expand_xyz(testCoords[orderedHullIndices[i]]), outsideTest});
|
||||
}
|
||||
|
@ -1275,11 +1299,9 @@ void mg_render_fill(mg_canvas_data* canvas, mg_path_elt* elements, mg_path_descr
|
|||
u32 baseIndex = mg_vertices_base_index(canvas);
|
||||
int* indices = mg_reserve_indices(canvas, 3);
|
||||
|
||||
vec4 cubic = {1, 1, 1, 1};
|
||||
|
||||
mg_push_vertex(canvas, startPoint, cubic);
|
||||
mg_push_vertex(canvas, currentPoint, cubic);
|
||||
mg_push_vertex(canvas, endPoint, cubic);
|
||||
mg_push_vertex(canvas, startPoint);
|
||||
mg_push_vertex(canvas, currentPoint);
|
||||
mg_push_vertex(canvas, endPoint);
|
||||
|
||||
indices[0] = baseIndex;
|
||||
indices[1] = baseIndex + 1;
|
||||
|
@ -1307,21 +1329,10 @@ void mg_render_stroke_line(mg_canvas_data* canvas, vec2 p[2], mg_attributes* att
|
|||
u32 baseIndex = mg_vertices_base_index(canvas);
|
||||
i32* indices = mg_reserve_indices(canvas, 6);
|
||||
|
||||
mg_push_vertex(canvas,
|
||||
(vec2){p[0].x + n0.x, p[0].y + n0.y},
|
||||
(vec4){1, 1, 1, 1});
|
||||
|
||||
mg_push_vertex(canvas,
|
||||
(vec2){p[1].x + n0.x, p[1].y + n0.y},
|
||||
(vec4){1, 1, 1, 1});
|
||||
|
||||
mg_push_vertex(canvas,
|
||||
(vec2){p[1].x - n0.x, p[1].y - n0.y},
|
||||
(vec4){1, 1, 1, 1});
|
||||
|
||||
mg_push_vertex(canvas,
|
||||
(vec2){p[0].x - n0.x, p[0].y - n0.y},
|
||||
(vec4){1, 1, 1, 1});
|
||||
mg_push_vertex(canvas, (vec2){p[0].x + n0.x, p[0].y + n0.y});
|
||||
mg_push_vertex(canvas, (vec2){p[1].x + n0.x, p[1].y + n0.y});
|
||||
mg_push_vertex(canvas, (vec2){p[1].x - n0.x, p[1].y - n0.y});
|
||||
mg_push_vertex(canvas, (vec2){p[0].x - n0.x, p[0].y - n0.y});
|
||||
|
||||
indices[0] = baseIndex;
|
||||
indices[1] = baseIndex + 1;
|
||||
|
@ -1517,21 +1528,10 @@ void mg_render_stroke_quadratic(mg_canvas_data* canvas, vec2 p[4], mg_attributes
|
|||
u32 baseIndex = mg_vertices_base_index(canvas);
|
||||
i32* indices = mg_reserve_indices(canvas, 6);
|
||||
|
||||
mg_push_vertex(canvas,
|
||||
positiveOffsetHull[0],
|
||||
(vec4){1, 1, 1, 1});
|
||||
|
||||
mg_push_vertex(canvas,
|
||||
positiveOffsetHull[2],
|
||||
(vec4){1, 1, 1, 1});
|
||||
|
||||
mg_push_vertex(canvas,
|
||||
negativeOffsetHull[2],
|
||||
(vec4){1, 1, 1, 1});
|
||||
|
||||
mg_push_vertex(canvas,
|
||||
negativeOffsetHull[0],
|
||||
(vec4){1, 1, 1, 1});
|
||||
mg_push_vertex(canvas, positiveOffsetHull[0]);
|
||||
mg_push_vertex(canvas, positiveOffsetHull[2]);
|
||||
mg_push_vertex(canvas, negativeOffsetHull[2]);
|
||||
mg_push_vertex(canvas, negativeOffsetHull[0]);
|
||||
|
||||
indices[0] = baseIndex + 0;
|
||||
indices[1] = baseIndex + 1;
|
||||
|
@ -1668,22 +1668,10 @@ void mg_render_stroke_cubic(mg_canvas_data* canvas, vec2 p[4], mg_attributes* at
|
|||
u32 baseIndex = mg_vertices_base_index(canvas);
|
||||
i32* indices = mg_reserve_indices(canvas, 6);
|
||||
|
||||
|
||||
mg_push_vertex(canvas,
|
||||
positiveOffsetHull[0],
|
||||
(vec4){1, 1, 1, 1});
|
||||
|
||||
mg_push_vertex(canvas,
|
||||
positiveOffsetHull[3],
|
||||
(vec4){1, 1, 1, 1});
|
||||
|
||||
mg_push_vertex(canvas,
|
||||
negativeOffsetHull[3],
|
||||
(vec4){1, 1, 1, 1});
|
||||
|
||||
mg_push_vertex(canvas,
|
||||
negativeOffsetHull[0],
|
||||
(vec4){1, 1, 1, 1});
|
||||
mg_push_vertex(canvas, positiveOffsetHull[0]);
|
||||
mg_push_vertex(canvas, positiveOffsetHull[3]);
|
||||
mg_push_vertex(canvas, negativeOffsetHull[3]);
|
||||
mg_push_vertex(canvas, negativeOffsetHull[0]);
|
||||
|
||||
indices[0] = baseIndex + 0;
|
||||
indices[1] = baseIndex + 1;
|
||||
|
@ -1713,21 +1701,10 @@ void mg_stroke_cap(mg_canvas_data* canvas, vec2 p0, vec2 direction, mg_attribute
|
|||
u32 baseIndex = mg_vertices_base_index(canvas);
|
||||
i32* indices = mg_reserve_indices(canvas, 6);
|
||||
|
||||
mg_push_vertex(canvas,
|
||||
(vec2){p0.x + n0.x, p0.y + n0.y},
|
||||
(vec4){1, 1, 1, 1});
|
||||
|
||||
mg_push_vertex(canvas,
|
||||
(vec2){p0.x + n0.x + m0.x, p0.y + n0.y + m0.y},
|
||||
(vec4){1, 1, 1, 1});
|
||||
|
||||
mg_push_vertex(canvas,
|
||||
(vec2){p0.x - n0.x + m0.x, p0.y - n0.y + m0.y},
|
||||
(vec4){1, 1, 1, 1});
|
||||
|
||||
mg_push_vertex(canvas,
|
||||
(vec2){p0.x - n0.x, p0.y - n0.y},
|
||||
(vec4){1, 1, 1, 1});
|
||||
mg_push_vertex(canvas, (vec2){p0.x + n0.x, p0.y + n0.y});
|
||||
mg_push_vertex(canvas, (vec2){p0.x + n0.x + m0.x, p0.y + n0.y + m0.y});
|
||||
mg_push_vertex(canvas, (vec2){p0.x - n0.x + m0.x, p0.y - n0.y + m0.y});
|
||||
mg_push_vertex(canvas, (vec2){p0.x - n0.x, p0.y - n0.y});
|
||||
|
||||
indices[0] = baseIndex;
|
||||
indices[1] = baseIndex + 1;
|
||||
|
@ -1789,21 +1766,10 @@ void mg_stroke_joint(mg_canvas_data* canvas,
|
|||
u32 baseIndex = mg_vertices_base_index(canvas);
|
||||
i32* indices = mg_reserve_indices(canvas, 6);
|
||||
|
||||
mg_push_vertex(canvas,
|
||||
p0,
|
||||
(vec4){1, 1, 1, 1});
|
||||
|
||||
mg_push_vertex(canvas,
|
||||
(vec2){p0.x + n0.x*halfW, p0.y + n0.y*halfW},
|
||||
(vec4){1, 1, 1, 1});
|
||||
|
||||
mg_push_vertex(canvas,
|
||||
mitterPoint,
|
||||
(vec4){1, 1, 1, 1});
|
||||
|
||||
mg_push_vertex(canvas,
|
||||
(vec2){p0.x + n1.x*halfW, p0.y + n1.y*halfW},
|
||||
(vec4){1, 1, 1, 1});
|
||||
mg_push_vertex(canvas, p0);
|
||||
mg_push_vertex(canvas, (vec2){p0.x + n0.x*halfW, p0.y + n0.y*halfW});
|
||||
mg_push_vertex(canvas, mitterPoint);
|
||||
mg_push_vertex(canvas, (vec2){p0.x + n1.x*halfW, p0.y + n1.y*halfW});
|
||||
|
||||
indices[0] = baseIndex;
|
||||
indices[1] = baseIndex + 1;
|
||||
|
@ -1818,17 +1784,9 @@ void mg_stroke_joint(mg_canvas_data* canvas,
|
|||
u32 baseIndex = mg_vertices_base_index(canvas);
|
||||
i32* indices = mg_reserve_indices(canvas, 3);
|
||||
|
||||
mg_push_vertex(canvas,
|
||||
p0,
|
||||
(vec4){1, 1, 1, 1});
|
||||
|
||||
mg_push_vertex(canvas,
|
||||
(vec2){p0.x + n0.x*halfW, p0.y + n0.y*halfW},
|
||||
(vec4){1, 1, 1, 1});
|
||||
|
||||
mg_push_vertex(canvas,
|
||||
(vec2){p0.x + n1.x*halfW, p0.y + n1.y*halfW},
|
||||
(vec4){1, 1, 1, 1});
|
||||
mg_push_vertex(canvas, p0);
|
||||
mg_push_vertex(canvas, (vec2){p0.x + n0.x*halfW, p0.y + n0.y*halfW});
|
||||
mg_push_vertex(canvas, (vec2){p0.x + n1.x*halfW, p0.y + n1.y*halfW});
|
||||
|
||||
DEBUG_ASSERT(!isnan(n0.x) && !isnan(n0.y) && !isnan(n1.x) && !isnan(n1.y));
|
||||
|
||||
|
@ -1983,16 +1941,11 @@ void mg_render_rectangle_fill(mg_canvas_data* canvas, mp_rect rect, mg_attribute
|
|||
|
||||
mg_next_shape(canvas, attributes);
|
||||
|
||||
vec2 points[4] = {{rect.x, rect.y},
|
||||
{rect.x + rect.w, rect.y},
|
||||
{rect.x + rect.w, rect.y + rect.h},
|
||||
{rect.x, rect.y + rect.h}};
|
||||
mg_push_vertex(canvas, (vec2){rect.x, rect.y});
|
||||
mg_push_vertex(canvas, (vec2){rect.x + rect.w, rect.y});
|
||||
mg_push_vertex(canvas, (vec2){rect.x + rect.w, rect.y + rect.h});
|
||||
mg_push_vertex(canvas, (vec2){rect.x, rect.y + rect.h});
|
||||
|
||||
vec4 cubic = {1, 1, 1, 1};
|
||||
for(int i=0; i<4; i++)
|
||||
{
|
||||
mg_push_vertex(canvas, points[i], cubic);
|
||||
}
|
||||
indices[0] = baseIndex + 0;
|
||||
indices[1] = baseIndex + 1;
|
||||
indices[2] = baseIndex + 2;
|
||||
|
@ -2013,26 +1966,17 @@ void mg_render_rectangle_stroke(mg_canvas_data* canvas, mp_rect rect, mg_attribu
|
|||
f32 width = minimum(attributes->width, minimum(rect.w, rect.h));
|
||||
f32 halfW = width/2;
|
||||
|
||||
vec2 outerPoints[4] = {{rect.x - halfW, rect.y - halfW},
|
||||
{rect.x + rect.w + halfW, rect.y - halfW},
|
||||
{rect.x + rect.w + halfW, rect.y + rect.h + halfW},
|
||||
{rect.x - halfW, rect.y + rect.h + halfW}};
|
||||
// outer points
|
||||
mg_push_vertex(canvas, (vec2){rect.x - halfW, rect.y - halfW});
|
||||
mg_push_vertex(canvas, (vec2){rect.x + rect.w + halfW, rect.y - halfW});
|
||||
mg_push_vertex(canvas, (vec2){rect.x + rect.w + halfW, rect.y + rect.h + halfW});
|
||||
mg_push_vertex(canvas, (vec2){rect.x - halfW, rect.y + rect.h + halfW});
|
||||
|
||||
vec2 innerPoints[4] = {{rect.x + halfW, rect.y + halfW},
|
||||
{rect.x + rect.w - halfW, rect.y + halfW},
|
||||
{rect.x + rect.w - halfW, rect.y + rect.h - halfW},
|
||||
{rect.x + halfW, rect.y + rect.h - halfW}};
|
||||
|
||||
vec4 cubic = {1, 1, 1, 1};
|
||||
for(int i=0; i<4; i++)
|
||||
{
|
||||
mg_push_vertex(canvas, outerPoints[i], cubic);
|
||||
}
|
||||
|
||||
for(int i=0; i<4; i++)
|
||||
{
|
||||
mg_push_vertex(canvas, innerPoints[i], cubic);
|
||||
}
|
||||
// innter points
|
||||
mg_push_vertex(canvas, (vec2){rect.x + halfW, rect.y + halfW});
|
||||
mg_push_vertex(canvas, (vec2){rect.x + rect.w - halfW, rect.y + halfW});
|
||||
mg_push_vertex(canvas, (vec2){rect.x + rect.w - halfW, rect.y + rect.h - halfW});
|
||||
mg_push_vertex(canvas, (vec2){rect.x + halfW, rect.y + rect.h - halfW});
|
||||
|
||||
indices[0] = baseIndex + 0;
|
||||
indices[1] = baseIndex + 1;
|
||||
|
@ -2054,23 +1998,14 @@ void mg_render_fill_arc_corner(mg_canvas_data* canvas, f32 x, f32 y, f32 rx, f32
|
|||
u32 baseIndex = mg_vertices_base_index(canvas);
|
||||
i32* indices = mg_reserve_indices(canvas, 6);
|
||||
|
||||
static const vec4 cubics[4] = {{-3.76797, -9.76362, 5.47912, -1},
|
||||
{-4.19896, -9.45223, 7.534, -1},
|
||||
{-4.19896, -7.534, 9.45223, -1},
|
||||
{-3.76797, -5.47912, 9.76362, -1}};
|
||||
|
||||
f32 cx = rx*4*(sqrt(2)-1)/3;
|
||||
f32 cy = ry*4*(sqrt(2)-1)/3;
|
||||
|
||||
vec2 points[4] = {{x, y + ry},
|
||||
{x, y + ry - cy},
|
||||
{x + rx - cx, y},
|
||||
{x + rx, y}};
|
||||
mg_push_vertex_cubic(canvas, (vec2){x, y + ry}, (vec4){-3.76797, -9.76362, 5.47912, -1});
|
||||
mg_push_vertex_cubic(canvas, (vec2){x, y + ry - cy}, (vec4){-4.19896, -9.45223, 7.534, -1});
|
||||
mg_push_vertex_cubic(canvas, (vec2){x + rx - cx, y}, (vec4){-4.19896, -7.534, 9.45223, -1});
|
||||
mg_push_vertex_cubic(canvas, (vec2){x + rx, y}, (vec4){-3.76797, -5.47912, 9.76362, -1});
|
||||
|
||||
for(int i=0; i<4; i++)
|
||||
{
|
||||
mg_push_vertex(canvas, points[i], cubics[i]);
|
||||
}
|
||||
indices[0] = baseIndex + 0;
|
||||
indices[1] = baseIndex + 1;
|
||||
indices[2] = baseIndex + 2;
|
||||
|
@ -2089,21 +2024,14 @@ void mg_render_rounded_rectangle_fill_path(mg_canvas_data* canvas,
|
|||
i32* indices = mg_reserve_indices(canvas, 18);
|
||||
|
||||
//NOTE(martin): inner cutted corner rectangle
|
||||
vec2 points[8] = {{rect.x + rect.r, rect.y},
|
||||
{rect.x + rect.w - rect.r, rect.y},
|
||||
{rect.x + rect.w, rect.y + rect.r},
|
||||
{rect.x + rect.w, rect.y + rect.h - rect.r},
|
||||
{rect.x + rect.w - rect.r, rect.y + rect.h},
|
||||
{rect.x + rect.r, rect.y + rect.h},
|
||||
{rect.x, rect.y + rect.h - rect.r},
|
||||
{rect.x, rect.y + rect.r}};
|
||||
|
||||
vec4 cubic = {1, 1, 1, 1};
|
||||
|
||||
for(int i=0; i<8; i++)
|
||||
{
|
||||
mg_push_vertex(canvas, points[i], cubic);
|
||||
}
|
||||
mg_push_vertex(canvas, (vec2){rect.x + rect.r, rect.y});
|
||||
mg_push_vertex(canvas, (vec2){rect.x + rect.w - rect.r, rect.y});
|
||||
mg_push_vertex(canvas, (vec2){rect.x + rect.w, rect.y + rect.r});
|
||||
mg_push_vertex(canvas, (vec2){rect.x + rect.w, rect.y + rect.h - rect.r});
|
||||
mg_push_vertex(canvas, (vec2){rect.x + rect.w - rect.r, rect.y + rect.h});
|
||||
mg_push_vertex(canvas, (vec2){rect.x + rect.r, rect.y + rect.h});
|
||||
mg_push_vertex(canvas, (vec2){rect.x, rect.y + rect.h - rect.r});
|
||||
mg_push_vertex(canvas, (vec2){rect.x, rect.y + rect.r});
|
||||
|
||||
static const i32 fanIndices[18] = { 0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 5, 0, 5, 6, 0, 6, 7 }; // inner fan
|
||||
for(int i=0; i<18; i++)
|
||||
|
@ -2153,17 +2081,10 @@ void mg_render_ellipse_fill_path(mg_canvas_data* canvas, mp_rect rect)
|
|||
i32* indices = mg_reserve_indices(canvas, 6);
|
||||
|
||||
//NOTE(martin): inner diamond
|
||||
vec2 points[4] = {{rect.x, rect.y + ry},
|
||||
{rect.x + rx, rect.y},
|
||||
{rect.x + rect.w, rect.y + ry},
|
||||
{rect.x + rx, rect.y + rect.h}};
|
||||
|
||||
vec4 cubic = {1, 1, 1, 1};
|
||||
|
||||
for(int i=0; i<4; i++)
|
||||
{
|
||||
mg_push_vertex(canvas, points[i], cubic);
|
||||
}
|
||||
mg_push_vertex(canvas, (vec2){rect.x, rect.y + ry});
|
||||
mg_push_vertex(canvas, (vec2){rect.x + rx, rect.y});
|
||||
mg_push_vertex(canvas, (vec2){rect.x + rect.w, rect.y + ry});
|
||||
mg_push_vertex(canvas, (vec2){rect.x + rx, rect.y + rect.h});
|
||||
|
||||
indices[0] = baseIndex + 0;
|
||||
indices[1] = baseIndex + 1;
|
||||
|
@ -2746,46 +2667,6 @@ mg_canvas mg_canvas_set_current(mg_canvas canvas)
|
|||
}
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
mg_mat2x3 mg_matrix_stack_top(mg_canvas_data* canvas)
|
||||
{
|
||||
if(canvas->matrixStackSize == 0)
|
||||
{
|
||||
return((mg_mat2x3){1, 0, 0,
|
||||
0, 1, 0});
|
||||
}
|
||||
else
|
||||
{
|
||||
return(canvas->matrixStack[canvas->matrixStackSize-1]);
|
||||
}
|
||||
}
|
||||
|
||||
void mg_matrix_stack_push(mg_canvas_data* canvas, mg_mat2x3 transform)
|
||||
{
|
||||
if(canvas->matrixStackSize >= MG_MATRIX_STACK_MAX_DEPTH)
|
||||
{
|
||||
LOG_ERROR("matrix stack overflow\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
canvas->matrixStack[canvas->matrixStackSize] = transform;
|
||||
canvas->matrixStackSize++;
|
||||
canvas->transform = transform;
|
||||
}
|
||||
}
|
||||
|
||||
void mg_matrix_stack_pop(mg_canvas_data* canvas)
|
||||
{
|
||||
if(canvas->matrixStackSize == 0)
|
||||
{
|
||||
LOG_ERROR("matrix stack underflow\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
canvas->matrixStackSize--;
|
||||
canvas->transform = mg_matrix_stack_top(canvas);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
mp_rect mg_clip_stack_top(mg_canvas_data* canvas)
|
||||
{
|
||||
|
@ -2878,8 +2759,7 @@ void mg_flush_commands(int primitiveCount, mg_primitive* primitives, mg_path_elt
|
|||
u32 nextIndex = 0;
|
||||
|
||||
mg_reset_shape_index(canvas);
|
||||
canvas->transform = (mg_mat2x3){1, 0, 0,
|
||||
0, 1, 0};
|
||||
|
||||
canvas->clip = (mp_rect){-FLT_MAX/2, -FLT_MAX/2, FLT_MAX, FLT_MAX};
|
||||
|
||||
canvas->currentImage = mg_image_nil();
|
||||
|
@ -2896,6 +2776,8 @@ void mg_flush_commands(int primitiveCount, mg_primitive* primitives, mg_path_elt
|
|||
mg_primitive* primitive = &(primitives[nextIndex]);
|
||||
nextIndex++;
|
||||
|
||||
canvas->transform = primitive->transform;
|
||||
|
||||
if(i && primitive->attributes.image.h != canvas->currentImage.h)
|
||||
{
|
||||
mg_image_data* imageData = mg_image_data_from_handle(canvas, canvas->currentImage);
|
||||
|
@ -2973,17 +2855,6 @@ void mg_flush_commands(int primitiveCount, mg_primitive* primitives, mg_path_elt
|
|||
}
|
||||
} break;
|
||||
|
||||
case MG_CMD_MATRIX_PUSH:
|
||||
{
|
||||
mg_mat2x3 transform = mg_matrix_stack_top(canvas);
|
||||
mg_matrix_stack_push(canvas, mg_mat2x3_mul_m(transform, primitive->matrix));
|
||||
} break;
|
||||
|
||||
case MG_CMD_MATRIX_POP:
|
||||
{
|
||||
mg_matrix_stack_pop(canvas);
|
||||
} break;
|
||||
|
||||
case MG_CMD_CLIP_PUSH:
|
||||
{
|
||||
//TODO(martin): use only aligned rect and avoid this
|
||||
|
@ -3034,42 +2905,39 @@ void mg_flush()
|
|||
void mg_matrix_push(mg_mat2x3 matrix)
|
||||
{
|
||||
mg_canvas_data* canvas = __mgCurrentCanvas;
|
||||
if(!canvas)
|
||||
if(canvas)
|
||||
{
|
||||
return;
|
||||
mg_mat2x3 transform = mg_matrix_stack_top(canvas);
|
||||
mg_matrix_stack_push(canvas, mg_mat2x3_mul_m(transform, matrix));
|
||||
}
|
||||
mg_push_command(canvas, (mg_primitive){.cmd = MG_CMD_MATRIX_PUSH, .matrix = matrix});
|
||||
}
|
||||
|
||||
void mg_matrix_pop()
|
||||
{
|
||||
mg_canvas_data* canvas = __mgCurrentCanvas;
|
||||
if(!canvas)
|
||||
if(canvas)
|
||||
{
|
||||
return;
|
||||
mg_matrix_stack_pop(canvas);
|
||||
}
|
||||
mg_push_command(canvas, (mg_primitive){.cmd = MG_CMD_MATRIX_POP});
|
||||
}
|
||||
|
||||
void mg_clip_push(f32 x, f32 y, f32 w, f32 h)
|
||||
{
|
||||
mg_canvas_data* canvas = __mgCurrentCanvas;
|
||||
if(!canvas)
|
||||
if(canvas)
|
||||
{
|
||||
return;
|
||||
}
|
||||
mg_push_command(canvas, (mg_primitive){.cmd = MG_CMD_CLIP_PUSH,
|
||||
mg_push_command(canvas, (mg_primitive){.cmd = MG_CMD_CLIP_PUSH,
|
||||
.rect = (mp_rect){x, y, w, h}});
|
||||
}
|
||||
}
|
||||
|
||||
void mg_clip_pop()
|
||||
{
|
||||
mg_canvas_data* canvas = __mgCurrentCanvas;
|
||||
if(!canvas)
|
||||
if(canvas)
|
||||
{
|
||||
return;
|
||||
mg_push_command(canvas, (mg_primitive){.cmd = MG_CMD_CLIP_POP});
|
||||
}
|
||||
mg_push_command(canvas, (mg_primitive){.cmd = MG_CMD_CLIP_POP});
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------
|
||||
|
@ -3488,23 +3356,18 @@ void mg_text_outlines(str8 text)
|
|||
void mg_clear()
|
||||
{
|
||||
mg_canvas_data* canvas = __mgCurrentCanvas;
|
||||
if(!canvas)
|
||||
if(canvas)
|
||||
{
|
||||
return;
|
||||
mg_push_command(canvas, (mg_primitive){.cmd = MG_CMD_CLEAR, .attributes = canvas->attributes});
|
||||
}
|
||||
mg_push_command(canvas, (mg_primitive){.cmd = MG_CMD_CLEAR, .attributes = canvas->attributes});
|
||||
}
|
||||
|
||||
void mg_fill()
|
||||
{
|
||||
mg_canvas_data* canvas = __mgCurrentCanvas;
|
||||
if(!canvas)
|
||||
if(canvas && canvas->path.count)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(canvas->path.count)
|
||||
{
|
||||
mg_push_command(canvas, ((mg_primitive){.cmd = MG_CMD_FILL, .path = canvas->path, .attributes = canvas->attributes}));
|
||||
mg_push_command(canvas, (mg_primitive){.cmd = MG_CMD_FILL, .path = canvas->path, .attributes = canvas->attributes});
|
||||
mg_new_path(canvas);
|
||||
}
|
||||
}
|
||||
|
@ -3512,13 +3375,9 @@ void mg_fill()
|
|||
void mg_stroke()
|
||||
{
|
||||
mg_canvas_data* canvas = __mgCurrentCanvas;
|
||||
if(!canvas)
|
||||
if(canvas && canvas->path.count)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(canvas->path.count)
|
||||
{
|
||||
mg_push_command(canvas, ((mg_primitive){.cmd = MG_CMD_STROKE, .path = canvas->path, .attributes = canvas->attributes}));
|
||||
mg_push_command(canvas, (mg_primitive){.cmd = MG_CMD_STROKE, .path = canvas->path, .attributes = canvas->attributes});
|
||||
mg_new_path(canvas);
|
||||
}
|
||||
}
|
||||
|
@ -3528,107 +3387,97 @@ void mg_stroke()
|
|||
//------------------------------------------------------------------------------------------
|
||||
void mg_rectangle_fill(f32 x, f32 y, f32 w, f32 h)
|
||||
{
|
||||
// DEBUG_ASSERT(w>=0 && h>=0);
|
||||
|
||||
mg_canvas_data* canvas = __mgCurrentCanvas;
|
||||
if(!canvas)
|
||||
if(canvas)
|
||||
{
|
||||
return;
|
||||
mg_primitive primitive = {.cmd = MG_CMD_RECT_FILL, .rect = (mp_rect){x, y, w, h}, .attributes = canvas->attributes};
|
||||
mg_push_command(canvas, primitive);
|
||||
}
|
||||
mg_push_command(canvas,
|
||||
((mg_primitive){.cmd = MG_CMD_RECT_FILL, .rect = (mp_rect){x, y, w, h}, .attributes = canvas->attributes}));
|
||||
}
|
||||
|
||||
void mg_rectangle_stroke(f32 x, f32 y, f32 w, f32 h)
|
||||
{
|
||||
// DEBUG_ASSERT(w>=0 && h>=0);
|
||||
|
||||
mg_canvas_data* canvas = __mgCurrentCanvas;
|
||||
if(!canvas)
|
||||
if(canvas)
|
||||
{
|
||||
return;
|
||||
mg_primitive primitive = {.cmd = MG_CMD_RECT_STROKE, .rect = (mp_rect){x, y, w, h}, .attributes = canvas->attributes};
|
||||
mg_push_command(canvas, primitive);
|
||||
}
|
||||
mg_push_command(canvas,
|
||||
((mg_primitive){.cmd = MG_CMD_RECT_STROKE, .rect = (mp_rect){x, y, w, h}, .attributes = canvas->attributes}));
|
||||
}
|
||||
|
||||
void mg_rounded_rectangle_fill(f32 x, f32 y, f32 w, f32 h, f32 r)
|
||||
{
|
||||
mg_canvas_data* canvas = __mgCurrentCanvas;
|
||||
if(!canvas)
|
||||
if(canvas)
|
||||
{
|
||||
return;
|
||||
mg_primitive primitive = {.cmd = MG_CMD_ROUND_RECT_FILL,
|
||||
.roundedRect = (mg_rounded_rect){x, y, w, h, r},
|
||||
.attributes = canvas->attributes};
|
||||
mg_push_command(canvas, primitive);
|
||||
}
|
||||
mg_push_command(canvas,
|
||||
((mg_primitive){.cmd = MG_CMD_ROUND_RECT_FILL,
|
||||
.roundedRect = (mg_rounded_rect){x, y, w, h, r},
|
||||
.attributes = canvas->attributes}));
|
||||
}
|
||||
|
||||
void mg_rounded_rectangle_stroke(f32 x, f32 y, f32 w, f32 h, f32 r)
|
||||
{
|
||||
mg_canvas_data* canvas = __mgCurrentCanvas;
|
||||
if(!canvas)
|
||||
if(canvas)
|
||||
{
|
||||
return;
|
||||
mg_primitive primitive = {.cmd = MG_CMD_ROUND_RECT_STROKE,
|
||||
.roundedRect = (mg_rounded_rect){x, y, w, h, r},
|
||||
.attributes = canvas->attributes};
|
||||
mg_push_command(canvas, primitive);
|
||||
}
|
||||
mg_push_command(canvas,
|
||||
((mg_primitive){.cmd = MG_CMD_ROUND_RECT_STROKE,
|
||||
.roundedRect = (mg_rounded_rect){x, y, w, h, r},
|
||||
.attributes = canvas->attributes}));
|
||||
}
|
||||
|
||||
void mg_circle_fill(f32 x, f32 y, f32 r)
|
||||
{
|
||||
mg_canvas_data* canvas = __mgCurrentCanvas;
|
||||
if(!canvas)
|
||||
if(canvas)
|
||||
{
|
||||
return;
|
||||
mg_primitive primitive = {.cmd = MG_CMD_ELLIPSE_FILL,
|
||||
.rect = (mp_rect){x-r, y-r, 2*r, 2*r},
|
||||
.attributes = canvas->attributes};
|
||||
mg_push_command(canvas, primitive);
|
||||
}
|
||||
mg_push_command(canvas,
|
||||
((mg_primitive){.cmd = MG_CMD_ELLIPSE_FILL,
|
||||
.rect = (mp_rect){x-r, y-r, 2*r, 2*r},
|
||||
.attributes = canvas->attributes}));
|
||||
}
|
||||
|
||||
void mg_circle_stroke(f32 x, f32 y, f32 r)
|
||||
{
|
||||
mg_canvas_data* canvas = __mgCurrentCanvas;
|
||||
if(!canvas)
|
||||
if(canvas)
|
||||
{
|
||||
return;
|
||||
mg_primitive primitive = {.cmd = MG_CMD_ELLIPSE_STROKE,
|
||||
.rect = (mp_rect){x-r, y-r, 2*r, 2*r},
|
||||
.attributes = canvas->attributes};
|
||||
mg_push_command(canvas, primitive);
|
||||
}
|
||||
mg_push_command(canvas,
|
||||
((mg_primitive){.cmd = MG_CMD_ELLIPSE_STROKE,
|
||||
.rect = (mp_rect){x-r, y-r, 2*r, 2*r},
|
||||
.attributes = canvas->attributes}));
|
||||
}
|
||||
|
||||
void mg_ellipse_fill(f32 x, f32 y, f32 rx, f32 ry)
|
||||
{
|
||||
mg_canvas_data* canvas = __mgCurrentCanvas;
|
||||
if(!canvas)
|
||||
if(canvas)
|
||||
{
|
||||
return;
|
||||
mg_primitive primitive = {.cmd = MG_CMD_ELLIPSE_FILL,
|
||||
.rect = (mp_rect){x-rx, y-ry, 2*rx, 2*ry},
|
||||
.attributes = canvas->attributes};
|
||||
mg_push_command(canvas, primitive);
|
||||
}
|
||||
mg_push_command(canvas,
|
||||
((mg_primitive){.cmd = MG_CMD_ELLIPSE_FILL,
|
||||
.rect = (mp_rect){x-rx, y-ry, 2*rx, 2*ry},
|
||||
.attributes = canvas->attributes}));
|
||||
}
|
||||
|
||||
void mg_ellipse_stroke(f32 x, f32 y, f32 rx, f32 ry)
|
||||
{
|
||||
mg_canvas_data* canvas = __mgCurrentCanvas;
|
||||
if(!canvas)
|
||||
if(canvas)
|
||||
{
|
||||
return;
|
||||
mg_primitive primitive = {.cmd = MG_CMD_ELLIPSE_STROKE,
|
||||
.rect = (mp_rect){x-rx, y-ry, 2*rx, 2*ry},
|
||||
.attributes = canvas->attributes};
|
||||
mg_push_command(canvas, primitive);
|
||||
}
|
||||
mg_push_command(canvas,
|
||||
((mg_primitive){.cmd = MG_CMD_ELLIPSE_STROKE,
|
||||
.rect = (mp_rect){x-rx, y-ry, 2*rx, 2*ry},
|
||||
.attributes = canvas->attributes}));
|
||||
}
|
||||
|
||||
//TODO: change to arc_to?
|
||||
void mg_arc(f32 x, f32 y, f32 r, f32 arcAngle, f32 startAngle)
|
||||
{
|
||||
f32 endAngle = startAngle + arcAngle;
|
||||
|
@ -3651,7 +3500,7 @@ void mg_arc(f32 x, f32 y, f32 r, f32 arcAngle, f32 startAngle)
|
|||
f32 rotSin = sin(rotAngle);
|
||||
|
||||
mg_mat2x3 t = {r*rotCos, -r*rotSin, x,
|
||||
r*rotSin, r*rotCos, y};
|
||||
r*rotSin, r*rotCos, y};
|
||||
|
||||
v0 = mg_mat2x3_mul(t, v0);
|
||||
v1 = mg_mat2x3_mul(t, v1);
|
||||
|
@ -3811,36 +3660,4 @@ MP_API void mg_image_draw_rounded(mg_image image, mp_rect rect, f32 roundness)
|
|||
mg_image_draw_region_rounded(image, (mp_rect){0, 0, size.x, size.y}, rect, roundness);
|
||||
}
|
||||
|
||||
/*
|
||||
void mg_image_draw(mg_image image, mp_rect rect)
|
||||
{
|
||||
mg_canvas_data* canvas = __mgCurrentCanvas;
|
||||
if(!canvas)
|
||||
{
|
||||
return;
|
||||
}
|
||||
mg_primitive primitive = {.cmd = MG_CMD_IMAGE_DRAW,
|
||||
.rect = (mp_rect){rect.x, rect.y, rect.w, rect.h},
|
||||
.attributes = canvas->attributes};
|
||||
primitive.attributes.image = image;
|
||||
mg_push_command(canvas, primitive);
|
||||
}
|
||||
|
||||
void mg_rounded_image_draw(mg_image image, mp_rect rect, f32 roundness)
|
||||
{
|
||||
mg_canvas_data* canvas = __mgCurrentCanvas;
|
||||
if(!canvas)
|
||||
{
|
||||
return;
|
||||
}
|
||||
mg_primitive primitive = {.cmd = MG_CMD_ROUNDED_IMAGE_DRAW,
|
||||
.roundedRect = {rect.x, rect.y, rect.w, rect.h, roundness},
|
||||
.attributes = canvas->attributes};
|
||||
primitive.attributes.image = image;
|
||||
|
||||
mg_push_command(canvas, primitive);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
#undef LOG_SUBSYSTEM
|
||||
|
|
|
@ -110,8 +110,6 @@ typedef enum { MG_CMD_CLEAR = 0,
|
|||
MG_CMD_ELLIPSE_FILL,
|
||||
MG_CMD_ELLIPSE_STROKE,
|
||||
MG_CMD_JUMP,
|
||||
MG_CMD_MATRIX_PUSH,
|
||||
MG_CMD_MATRIX_POP,
|
||||
MG_CMD_CLIP_PUSH,
|
||||
MG_CMD_CLIP_POP,
|
||||
} mg_primitive_cmd;
|
||||
|
@ -120,6 +118,7 @@ typedef struct mg_primitive
|
|||
{
|
||||
mg_primitive_cmd cmd;
|
||||
mg_attributes attributes;
|
||||
mg_mat2x3 transform;
|
||||
|
||||
union
|
||||
{
|
||||
|
@ -128,7 +127,7 @@ typedef struct mg_primitive
|
|||
mg_rounded_rect roundedRect;
|
||||
utf32 codePoint;
|
||||
u32 jump;
|
||||
mg_mat2x3 matrix;
|
||||
mg_mat2x3 matrix; //TODO remove when we use transform everywhere
|
||||
};
|
||||
|
||||
} mg_primitive;
|
||||
|
|
Loading…
Reference in New Issue