[canvas] Allow setting image source region
This commit is contained in:
parent
50569a1427
commit
b24de5d969
|
@ -74,19 +74,24 @@ int main()
|
||||||
mg_set_color_rgba(0, 1, 1, 1);
|
mg_set_color_rgba(0, 1, 1, 1);
|
||||||
mg_clear();
|
mg_clear();
|
||||||
|
|
||||||
mg_set_color_rgba(1, 0, 1, 1);
|
mg_set_color_rgba(1, 1, 1, 1);
|
||||||
|
|
||||||
mg_matrix_push((mg_mat2x3){0.707, -0.707, 200,
|
mg_matrix_push((mg_mat2x3){0.707, -0.707, 200,
|
||||||
0.707, 0.707, 100});
|
0.707, 0.707, 100});
|
||||||
|
|
||||||
mg_set_image(image);
|
mg_set_image(image);
|
||||||
|
mg_set_image_source_region((mp_rect){500, 500, 2000, 1400});
|
||||||
|
|
||||||
|
// mg_rectangle_fill(100, 100, imageSize.x/8, imageSize.y/8);
|
||||||
|
|
||||||
mg_move_to(0, 0);
|
mg_move_to(0, 0);
|
||||||
mg_line_to(100, 0);
|
mg_line_to(200, 0);
|
||||||
mg_line_to(150, 50);
|
mg_line_to(300, 100);
|
||||||
|
mg_line_to(200, 200);
|
||||||
|
mg_line_to(0, 200);
|
||||||
mg_line_to(100, 100);
|
mg_line_to(100, 100);
|
||||||
mg_line_to(0, 100);
|
|
||||||
mg_line_to(50, 50);
|
|
||||||
mg_fill();
|
mg_fill();
|
||||||
|
|
||||||
//mg_image_draw_rounded(image, (mp_rect){0, 0, imageSize.x/8, imageSize.y/8}, 40.);
|
//mg_image_draw_rounded(image, (mp_rect){0, 0, imageSize.x/8, imageSize.y/8}, 40.);
|
||||||
|
|
||||||
mg_matrix_pop();
|
mg_matrix_pop();
|
||||||
|
|
|
@ -100,6 +100,7 @@ typedef struct mg_canvas_data
|
||||||
u32 indexCount;
|
u32 indexCount;
|
||||||
|
|
||||||
mg_image currentImage;
|
mg_image currentImage;
|
||||||
|
mp_rect currentSrcRegion;
|
||||||
|
|
||||||
mg_resource_pool imagePool;
|
mg_resource_pool imagePool;
|
||||||
|
|
||||||
|
@ -601,18 +602,14 @@ void mg_reset_shape_index(mg_canvas_data* canvas)
|
||||||
canvas->shapeExtents = (vec4){FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX};
|
canvas->shapeExtents = (vec4){FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX};
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 mg_next_shape_textured(mg_canvas_data* canvas, vec2 uv, mg_color color)
|
void mg_finalize_shape(mg_canvas_data* canvas)
|
||||||
{
|
{
|
||||||
mg_vertex_layout* layout = &canvas->backend->vertexLayout;
|
|
||||||
|
|
||||||
if(canvas->nextShapeIndex)
|
if(canvas->nextShapeIndex)
|
||||||
{
|
{
|
||||||
//NOTE: set shape's bounding box for the _previous_ shape
|
//NOTE: set shape's uv transform for the _current_ shape
|
||||||
int prevIndex = canvas->nextShapeIndex-1;
|
|
||||||
|
|
||||||
vec2 texSize = mg_image_size(canvas->currentImage);
|
vec2 texSize = mg_image_size(canvas->currentImage);
|
||||||
|
|
||||||
mp_rect srcRegion = {0, 0, texSize.x, texSize.y};
|
mp_rect srcRegion = canvas->currentSrcRegion;
|
||||||
|
|
||||||
mp_rect destRegion = {canvas->shapeExtents.x,
|
mp_rect destRegion = {canvas->shapeExtents.x,
|
||||||
canvas->shapeExtents.y,
|
canvas->shapeExtents.y,
|
||||||
|
@ -632,9 +629,19 @@ u32 mg_next_shape_textured(mg_canvas_data* canvas, vec2 uv, mg_color color)
|
||||||
uvTransform = mg_mat2x3_mul_m(uvTransform, userToDestRegion);
|
uvTransform = mg_mat2x3_mul_m(uvTransform, userToDestRegion);
|
||||||
uvTransform = mg_mat2x3_mul_m(uvTransform, screenToUser);
|
uvTransform = mg_mat2x3_mul_m(uvTransform, screenToUser);
|
||||||
|
|
||||||
*(mg_mat2x3*)(layout->uvTransformBuffer + prevIndex*layout->uvTransformStride) = uvTransform;
|
int index = canvas->nextShapeIndex-1;
|
||||||
|
mg_vertex_layout* layout = &canvas->backend->vertexLayout;
|
||||||
|
*(mg_mat2x3*)(layout->uvTransformBuffer + index*layout->uvTransformStride) = uvTransform;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 mg_next_shape(mg_canvas_data* canvas, mg_attributes* attributes)
|
||||||
|
{
|
||||||
|
mg_finalize_shape(canvas);
|
||||||
|
|
||||||
|
canvas->currentSrcRegion = attributes->srcRegion;
|
||||||
|
|
||||||
|
mg_vertex_layout* layout = &canvas->backend->vertexLayout;
|
||||||
int index = canvas->nextShapeIndex;
|
int index = canvas->nextShapeIndex;
|
||||||
canvas->nextShapeIndex++;
|
canvas->nextShapeIndex++;
|
||||||
canvas->shapeFirstVertexIndex = canvas->vertexCount;
|
canvas->shapeFirstVertexIndex = canvas->vertexCount;
|
||||||
|
@ -645,17 +652,11 @@ u32 mg_next_shape_textured(mg_canvas_data* canvas, vec2 uv, mg_color color)
|
||||||
canvas->clip.y + canvas->clip.h - 1};
|
canvas->clip.y + canvas->clip.h - 1};
|
||||||
|
|
||||||
*(mp_rect*)(((char*)layout->clipBuffer) + index*layout->clipStride) = clip;
|
*(mp_rect*)(((char*)layout->clipBuffer) + index*layout->clipStride) = clip;
|
||||||
*(mg_color*)(((char*)layout->colorBuffer) + index*layout->colorStride) = color;
|
*(mg_color*)(((char*)layout->colorBuffer) + index*layout->colorStride) = attributes->color;
|
||||||
|
|
||||||
|
|
||||||
return(index);
|
return(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 mg_next_shape(mg_canvas_data* canvas, mg_color color)
|
|
||||||
{
|
|
||||||
return(mg_next_shape_textured(canvas, (vec2){0, 0}, color));
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO(martin): rename with something more explicit
|
//TODO(martin): rename with something more explicit
|
||||||
u32 mg_vertices_base_index(mg_canvas_data* canvas)
|
u32 mg_vertices_base_index(mg_canvas_data* canvas)
|
||||||
{
|
{
|
||||||
|
@ -1507,7 +1508,7 @@ void mg_render_stroke_quadratic(mg_canvas_data* canvas, vec2 p[4], mg_attributes
|
||||||
{
|
{
|
||||||
//NOTE(martin): push the actual fill commands for the offset contour
|
//NOTE(martin): push the actual fill commands for the offset contour
|
||||||
|
|
||||||
mg_next_shape(canvas, attributes->color);
|
mg_next_shape(canvas, attributes);
|
||||||
|
|
||||||
mg_render_fill_quadratic(canvas, positiveOffsetHull);
|
mg_render_fill_quadratic(canvas, positiveOffsetHull);
|
||||||
mg_render_fill_quadratic(canvas, negativeOffsetHull);
|
mg_render_fill_quadratic(canvas, negativeOffsetHull);
|
||||||
|
@ -1658,7 +1659,7 @@ void mg_render_stroke_cubic(mg_canvas_data* canvas, vec2 p[4], mg_attributes* at
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//NOTE(martin): push the actual fill commands for the offset contour
|
//NOTE(martin): push the actual fill commands for the offset contour
|
||||||
mg_next_shape(canvas, attributes->color);
|
mg_next_shape(canvas, attributes);
|
||||||
|
|
||||||
mg_render_fill_cubic(canvas, positiveOffsetHull);
|
mg_render_fill_cubic(canvas, positiveOffsetHull);
|
||||||
mg_render_fill_cubic(canvas, negativeOffsetHull);
|
mg_render_fill_cubic(canvas, negativeOffsetHull);
|
||||||
|
@ -1707,7 +1708,7 @@ void mg_stroke_cap(mg_canvas_data* canvas, vec2 p0, vec2 direction, mg_attribute
|
||||||
vec2 m0 = {alpha*direction.x,
|
vec2 m0 = {alpha*direction.x,
|
||||||
alpha*direction.y};
|
alpha*direction.y};
|
||||||
|
|
||||||
mg_next_shape(canvas, attributes->color);
|
mg_next_shape(canvas, attributes);
|
||||||
|
|
||||||
u32 baseIndex = mg_vertices_base_index(canvas);
|
u32 baseIndex = mg_vertices_base_index(canvas);
|
||||||
i32* indices = mg_reserve_indices(canvas, 6);
|
i32* indices = mg_reserve_indices(canvas, 6);
|
||||||
|
@ -1765,7 +1766,7 @@ void mg_stroke_joint(mg_canvas_data* canvas,
|
||||||
n1.y *= -1;
|
n1.y *= -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
mg_next_shape(canvas, attributes->color);
|
mg_next_shape(canvas, attributes);
|
||||||
|
|
||||||
//NOTE(martin): use the same code as hull offset to find mitter point...
|
//NOTE(martin): use the same code as hull offset to find mitter point...
|
||||||
/*NOTE(martin): let vector u = (n0+n1) and vector v = pIntersect - p1
|
/*NOTE(martin): let vector u = (n0+n1) and vector v = pIntersect - p1
|
||||||
|
@ -1847,7 +1848,7 @@ void mg_render_stroke_element(mg_canvas_data* canvas,
|
||||||
{
|
{
|
||||||
vec2 controlPoints[4] = {currentPoint, element->p[0], element->p[1], element->p[2]};
|
vec2 controlPoints[4] = {currentPoint, element->p[0], element->p[1], element->p[2]};
|
||||||
int endPointIndex = 0;
|
int endPointIndex = 0;
|
||||||
mg_next_shape(canvas, attributes->color);
|
mg_next_shape(canvas, attributes);
|
||||||
|
|
||||||
switch(element->type)
|
switch(element->type)
|
||||||
{
|
{
|
||||||
|
@ -1980,7 +1981,7 @@ void mg_render_rectangle_fill(mg_canvas_data* canvas, mp_rect rect, mg_attribute
|
||||||
u32 baseIndex = mg_vertices_base_index(canvas);
|
u32 baseIndex = mg_vertices_base_index(canvas);
|
||||||
i32* indices = mg_reserve_indices(canvas, 6);
|
i32* indices = mg_reserve_indices(canvas, 6);
|
||||||
|
|
||||||
mg_next_shape(canvas, attributes->color);
|
mg_next_shape(canvas, attributes);
|
||||||
|
|
||||||
vec2 points[4] = {{rect.x, rect.y},
|
vec2 points[4] = {{rect.x, rect.y},
|
||||||
{rect.x + rect.w, rect.y},
|
{rect.x + rect.w, rect.y},
|
||||||
|
@ -2006,7 +2007,7 @@ void mg_render_rectangle_stroke(mg_canvas_data* canvas, mp_rect rect, mg_attribu
|
||||||
u32 baseIndex = mg_vertices_base_index(canvas);
|
u32 baseIndex = mg_vertices_base_index(canvas);
|
||||||
i32* indices = mg_reserve_indices(canvas, 12);
|
i32* indices = mg_reserve_indices(canvas, 12);
|
||||||
|
|
||||||
mg_next_shape(canvas, attributes->color);
|
mg_next_shape(canvas, attributes);
|
||||||
|
|
||||||
//NOTE(martin): limit stroke width to the minimum dimension of the rectangle
|
//NOTE(martin): limit stroke width to the minimum dimension of the rectangle
|
||||||
f32 width = minimum(attributes->width, minimum(rect.w, rect.h));
|
f32 width = minimum(attributes->width, minimum(rect.w, rect.h));
|
||||||
|
@ -2121,7 +2122,7 @@ void mg_render_rounded_rectangle_fill(mg_canvas_data* canvas,
|
||||||
mg_rounded_rect rect,
|
mg_rounded_rect rect,
|
||||||
mg_attributes* attributes)
|
mg_attributes* attributes)
|
||||||
{
|
{
|
||||||
mg_next_shape(canvas, attributes->color);
|
mg_next_shape(canvas, attributes);
|
||||||
mg_render_rounded_rectangle_fill_path(canvas, rect);
|
mg_render_rounded_rectangle_fill_path(canvas, rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2136,7 +2137,7 @@ void mg_render_rounded_rectangle_stroke(mg_canvas_data* canvas,
|
||||||
mg_rounded_rect inner = {rect.x + halfW, rect.y + halfW, rect.w - width, rect.h - width, rect.r - halfW};
|
mg_rounded_rect inner = {rect.x + halfW, rect.y + halfW, rect.w - width, rect.h - width, rect.r - halfW};
|
||||||
mg_rounded_rect outer = {rect.x - halfW, rect.y - halfW, rect.w + width, rect.h + width, rect.r + halfW};
|
mg_rounded_rect outer = {rect.x - halfW, rect.y - halfW, rect.w + width, rect.h + width, rect.r + halfW};
|
||||||
|
|
||||||
mg_next_shape(canvas, attributes->color);
|
mg_next_shape(canvas, attributes);
|
||||||
mg_render_rounded_rectangle_fill_path(canvas, outer);
|
mg_render_rounded_rectangle_fill_path(canvas, outer);
|
||||||
mg_render_rounded_rectangle_fill_path(canvas, inner);
|
mg_render_rounded_rectangle_fill_path(canvas, inner);
|
||||||
}
|
}
|
||||||
|
@ -2179,7 +2180,7 @@ void mg_render_ellipse_fill_path(mg_canvas_data* canvas, mp_rect rect)
|
||||||
|
|
||||||
void mg_render_ellipse_fill(mg_canvas_data* canvas, mp_rect rect, mg_attributes* attributes)
|
void mg_render_ellipse_fill(mg_canvas_data* canvas, mp_rect rect, mg_attributes* attributes)
|
||||||
{
|
{
|
||||||
mg_next_shape(canvas, attributes->color);
|
mg_next_shape(canvas, attributes);
|
||||||
mg_render_ellipse_fill_path(canvas, rect);
|
mg_render_ellipse_fill_path(canvas, rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2192,7 +2193,7 @@ void mg_render_ellipse_stroke(mg_canvas_data* canvas, mp_rect rect, mg_attribute
|
||||||
mp_rect inner = {rect.x + halfW, rect.y + halfW, rect.w - width, rect.h - width};
|
mp_rect inner = {rect.x + halfW, rect.y + halfW, rect.w - width, rect.h - width};
|
||||||
mp_rect outer = {rect.x - halfW, rect.y - halfW, rect.w + width, rect.h + width};
|
mp_rect outer = {rect.x - halfW, rect.y - halfW, rect.w + width, rect.h + width};
|
||||||
|
|
||||||
mg_next_shape(canvas, attributes->color);
|
mg_next_shape(canvas, attributes);
|
||||||
mg_render_ellipse_fill_path(canvas, outer);
|
mg_render_ellipse_fill_path(canvas, outer);
|
||||||
mg_render_ellipse_fill_path(canvas, inner);
|
mg_render_ellipse_fill_path(canvas, inner);
|
||||||
}
|
}
|
||||||
|
@ -2852,12 +2853,11 @@ void mg_do_clip_push(mg_canvas_data* canvas, mp_rect clip)
|
||||||
|
|
||||||
void mg_flush_batch(mg_canvas_data* canvas, mg_image_data* image)
|
void mg_flush_batch(mg_canvas_data* canvas, mg_image_data* image)
|
||||||
{
|
{
|
||||||
//NOTE: finalize last shape
|
mg_finalize_shape(canvas);
|
||||||
int shapeCount = mg_next_shape(canvas, (mg_color){1, 1, 1, 1});
|
|
||||||
|
|
||||||
if(canvas->backend && canvas->backend->drawBatch && canvas->indexCount)
|
if(canvas->backend && canvas->backend->drawBatch && canvas->indexCount)
|
||||||
{
|
{
|
||||||
canvas->backend->drawBatch(canvas->backend, image, shapeCount, canvas->vertexCount, canvas->indexCount);
|
canvas->backend->drawBatch(canvas->backend, image, canvas->nextShapeIndex, canvas->vertexCount, canvas->indexCount);
|
||||||
}
|
}
|
||||||
mg_reset_shape_index(canvas);
|
mg_reset_shape_index(canvas);
|
||||||
canvas->vertexCount = 0;
|
canvas->vertexCount = 0;
|
||||||
|
@ -2916,7 +2916,7 @@ void mg_flush_commands(int primitiveCount, mg_primitive* primitives, mg_path_elt
|
||||||
|
|
||||||
case MG_CMD_FILL:
|
case MG_CMD_FILL:
|
||||||
{
|
{
|
||||||
mg_next_shape(canvas, primitive->attributes.color);
|
mg_next_shape(canvas, &primitive->attributes);
|
||||||
mg_render_fill(canvas,
|
mg_render_fill(canvas,
|
||||||
pathElements + primitive->path.startIndex,
|
pathElements + primitive->path.startIndex,
|
||||||
&primitive->path);
|
&primitive->path);
|
||||||
|
@ -3167,6 +3167,17 @@ void mg_set_image(mg_image image)
|
||||||
if(canvas)
|
if(canvas)
|
||||||
{
|
{
|
||||||
canvas->attributes.image = image;
|
canvas->attributes.image = image;
|
||||||
|
vec2 size = mg_image_size(image);
|
||||||
|
canvas->attributes.srcRegion = (mp_rect){0, 0, size.x, size.y};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mg_set_image_source_region(mp_rect region)
|
||||||
|
{
|
||||||
|
mg_canvas_data* canvas = __mgCurrentCanvas;
|
||||||
|
if(canvas)
|
||||||
|
{
|
||||||
|
canvas->attributes.srcRegion = region;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3764,11 +3775,11 @@ MP_API void mg_image_draw_region(mg_image image, mp_rect srcRegion, mp_rect dstR
|
||||||
if(canvas)
|
if(canvas)
|
||||||
{
|
{
|
||||||
mg_primitive primitive = {.cmd = MG_CMD_RECT_FILL,
|
mg_primitive primitive = {.cmd = MG_CMD_RECT_FILL,
|
||||||
.srcRegion = srcRegion,
|
|
||||||
.rect = dstRegion,
|
.rect = dstRegion,
|
||||||
.attributes = canvas->attributes};
|
.attributes = canvas->attributes};
|
||||||
primitive.attributes.image = image;
|
primitive.attributes.image = image;
|
||||||
primitive.attributes.color = (mg_color){1, 0, 1, 1};
|
primitive.attributes.color = (mg_color){1, 1, 1, 1};
|
||||||
|
primitive.attributes.srcRegion = srcRegion;
|
||||||
mg_push_command(canvas, primitive);
|
mg_push_command(canvas, primitive);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3779,10 +3790,11 @@ MP_API void mg_image_draw_region_rounded(mg_image image, mp_rect srcRegion, mp_r
|
||||||
if(canvas)
|
if(canvas)
|
||||||
{
|
{
|
||||||
mg_primitive primitive = {.cmd = MG_CMD_ROUND_RECT_FILL,
|
mg_primitive primitive = {.cmd = MG_CMD_ROUND_RECT_FILL,
|
||||||
.srcRegion = srcRegion,
|
|
||||||
.roundedRect = {dstRegion.x, dstRegion.y, dstRegion.w, dstRegion.h, roundness},
|
.roundedRect = {dstRegion.x, dstRegion.y, dstRegion.w, dstRegion.h, roundness},
|
||||||
.attributes = canvas->attributes};
|
.attributes = canvas->attributes};
|
||||||
primitive.attributes.image = image;
|
primitive.attributes.image = image;
|
||||||
|
primitive.attributes.color = (mg_color){1, 1, 1, 1};
|
||||||
|
primitive.attributes.srcRegion = srcRegion;
|
||||||
mg_push_command(canvas, primitive);
|
mg_push_command(canvas, primitive);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -194,6 +194,7 @@ MP_API void mg_set_font(mg_font font);
|
||||||
MP_API void mg_set_font_size(f32 size);
|
MP_API void mg_set_font_size(f32 size);
|
||||||
MP_API void mg_set_text_flip(bool flip);
|
MP_API void mg_set_text_flip(bool flip);
|
||||||
MP_API void mg_set_image(mg_image image);
|
MP_API void mg_set_image(mg_image image);
|
||||||
|
MP_API void mg_set_image_source_region(mp_rect region);
|
||||||
|
|
||||||
MP_API mg_color mg_get_color();
|
MP_API mg_color mg_get_color();
|
||||||
MP_API f32 mg_get_width();
|
MP_API f32 mg_get_width();
|
||||||
|
|
|
@ -85,6 +85,7 @@ typedef struct mg_attributes
|
||||||
f32 fontSize;
|
f32 fontSize;
|
||||||
|
|
||||||
mg_image image;
|
mg_image image;
|
||||||
|
mp_rect srcRegion;
|
||||||
|
|
||||||
mp_rect clip;
|
mp_rect clip;
|
||||||
|
|
||||||
|
@ -120,8 +121,6 @@ typedef struct mg_primitive
|
||||||
mg_primitive_cmd cmd;
|
mg_primitive_cmd cmd;
|
||||||
mg_attributes attributes;
|
mg_attributes attributes;
|
||||||
|
|
||||||
mp_rect srcRegion;
|
|
||||||
|
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
mg_path_descriptor path;
|
mg_path_descriptor path;
|
||||||
|
|
Loading…
Reference in New Issue