Skip to content

Commit

Permalink
Add Canvas clearRect(), fix strokeRect()
Browse files Browse the repository at this point in the history
  • Loading branch information
TooTallNate committed Nov 29, 2023
1 parent 50e4168 commit 94697da
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 15 deletions.
5 changes: 5 additions & 0 deletions .changeset/smart-gifts-develop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'nxjs-runtime': patch
---

Add Canvas `clearRect()`, fix `strokeRect()`
37 changes: 35 additions & 2 deletions packages/runtime/src/canvas/canvas-rendering-context-2d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -396,10 +396,25 @@ export class CanvasRenderingContext2D {
}

/**
* Draws a rectangle that is filled according to the current `fillStyle`.
* Erases the pixels in a rectangular area by setting them to transparent black.
*
* @param x The x-axis coordinate of the rectangle's starting point.
* @param y The y-axis coordinate of the rectangle's starting point.
* @param width The rectangle's width. Positive values are to the right, and negative to the left.
* @param height The rectangle's height. Positive values are down, and negative are up.
* @see https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/clearRect
*/
clearRect(x: number, y: number, width: number, height: number): void {
stub();
}

/**
* Draws a rectangle that is filled according to the current
* {@link CanvasRenderingContext2D.fillStyle | `fillStyle`}.
*
* This method draws directly to the canvas without modifying the current path,
* so any subsequent `fill()` or `stroke()` calls will have no effect on it.
* so any subsequent {@link CanvasRenderingContext2D.fill | `fill()`} or
* {@link CanvasRenderingContext2D.stroke | `stroke()`} calls will have no effect on it.
*
* @param x The x-axis coordinate of the rectangle's starting point.
* @param y The y-axis coordinate of the rectangle's starting point.
Expand All @@ -411,6 +426,24 @@ export class CanvasRenderingContext2D {
stub();
}

/**
* Draws a rectangle that is stroked (outlined) according to the current
* {@link CanvasRenderingContext2D.strokeStyle | `strokeStyle`} and other context settings.
*
* This method draws directly to the canvas without modifying the current path,
* so any subsequent {@link CanvasRenderingContext2D.fill | `fill()`} or
* {@link CanvasRenderingContext2D.stroke | `stroke()`} calls will have no effect on it.
*
* @param x The x-axis coordinate of the rectangle's starting point.
* @param y The y-axis coordinate of the rectangle's starting point.
* @param width The rectangle's width. Positive values are to the right, and negative to the left.
* @param height The rectangle's height. Positive values are down, and negative are up.
* @see https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/strokeRect
*/
strokeRect(x: number, y: number, width: number, height: number): void {
stub();
}

createImageData(
sw: number,
sh: number,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,31 @@ export class OffscreenCanvasRenderingContext2D {
$.canvasContext2dSetFont(this, font, px);
}

/**
* Strokes (outlines) the current or given path with the current stroke style.
*
* @param path A {@link Path2D | `Path2D`} path to stroke.
* @see https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/stroke
*/
stroke(path?: Path2D): void {
stub();
}

/**
* Fills the current or given path with the current {@link CanvasRenderingContext2D.fillStyle | `fillStyle`}.
*
* @param fillRule
* @see https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/fill
*/
fill(fillRule?: CanvasFillRule): void;
fill(path: Path2D, fillRule?: CanvasFillRule): void;
fill(
fillRuleOrPath?: CanvasFillRule | Path2D,
fillRule?: CanvasFillRule
): void {
stub();
}

/**
* Specifies the color, gradient, or pattern to use inside shapes.
*
Expand Down Expand Up @@ -367,10 +392,25 @@ export class OffscreenCanvasRenderingContext2D {
}

/**
* Draws a rectangle that is filled according to the current `fillStyle`.
* Erases the pixels in a rectangular area by setting them to transparent black.
*
* @param x The x-axis coordinate of the rectangle's starting point.
* @param y The y-axis coordinate of the rectangle's starting point.
* @param width The rectangle's width. Positive values are to the right, and negative to the left.
* @param height The rectangle's height. Positive values are down, and negative are up.
* @see https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/clearRect
*/
clearRect(x: number, y: number, width: number, height: number): void {
stub();
}

/**
* Draws a rectangle that is filled according to the current
* {@link CanvasRenderingContext2D.fillStyle | `fillStyle`}.
*
* This method draws directly to the canvas without modifying the current path,
* so any subsequent `fill()` or `stroke()` calls will have no effect on it.
* so any subsequent {@link CanvasRenderingContext2D.fill | `fill()`} or
* {@link CanvasRenderingContext2D.stroke | `stroke()`} calls will have no effect on it.
*
* @param x The x-axis coordinate of the rectangle's starting point.
* @param y The y-axis coordinate of the rectangle's starting point.
Expand All @@ -382,6 +422,24 @@ export class OffscreenCanvasRenderingContext2D {
stub();
}

/**
* Draws a rectangle that is stroked (outlined) according to the current
* {@link CanvasRenderingContext2D.strokeStyle | `strokeStyle`} and other context settings.
*
* This method draws directly to the canvas without modifying the current path,
* so any subsequent {@link CanvasRenderingContext2D.fill | `fill()`} or
* {@link CanvasRenderingContext2D.stroke | `stroke()`} calls will have no effect on it.
*
* @param x The x-axis coordinate of the rectangle's starting point.
* @param y The y-axis coordinate of the rectangle's starting point.
* @param width The rectangle's width. Positive values are to the right, and negative to the left.
* @param height The rectangle's height. Positive values are down, and negative are up.
* @see https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/strokeRect
*/
strokeRect(x: number, y: number, width: number, height: number): void {
stub();
}

createImageData(
sw: number,
sh: number,
Expand Down
49 changes: 38 additions & 11 deletions source/canvas.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,19 @@ static void set_fill_rule(JSContext *ctx, JSValueConst fill_rule, cairo_t *cctx)
cairo_set_fill_rule(cctx, rule);
}

static void save_path(nx_canvas_context_2d_t *context)
{
context->path = cairo_copy_path_flat(context->ctx);
cairo_new_path(context->ctx);
}

static void restore_path(nx_canvas_context_2d_t *context)
{
cairo_new_path(context->ctx);
cairo_append_path(context->ctx, context->path);
cairo_path_destroy(context->path);
}

static void fill(nx_canvas_context_2d_t *context)
{
// TODO: support fill pattern / fill gradient / shadow
Expand Down Expand Up @@ -478,12 +491,31 @@ static JSValue nx_canvas_context_2d_get_transform(JSContext *ctx, JSValueConst t

static JSValue nx_canvas_context_2d_stroke_rect(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
{
CANVAS_CONTEXT;
RECT_ARGS;
CANVAS_CONTEXT_THIS;
RECT_ARGS2;
if (width && height)
{
save_path(context);
cairo_rectangle(context->ctx, x, y, width, height);
stroke(context);
restore_path(context);
}
return JS_UNDEFINED;
}

static JSValue nx_canvas_context_2d_clear_rect(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
{
CANVAS_CONTEXT_THIS;
RECT_ARGS2;
if (width && height)
{
cairo_save(context->ctx);
save_path(context);
cairo_rectangle(context->ctx, x, y, width, height);
cairo_set_operator(context->ctx, CAIRO_OPERATOR_CLEAR);
cairo_fill(context->ctx);
restore_path(context);
cairo_restore(context->ctx);
}
return JS_UNDEFINED;
}
Expand Down Expand Up @@ -1056,19 +1088,13 @@ static JSValue nx_canvas_context_2d_fill_rect(JSContext *ctx, JSValueConst this_
RECT_ARGS2;
if (width && height)
{
// save path
context->path = cairo_copy_path_flat(context->ctx);
cairo_new_path(context->ctx);

save_path(context);
cairo_rectangle(context->ctx, x, y, width, height);

// TODO: support gradient / pattern
fill(context);

// restore path
cairo_new_path(context->ctx);
cairo_append_path(context->ctx, context->path);
cairo_path_destroy(context->path);
restore_path(context);
}
return JS_UNDEFINED;
}
Expand Down Expand Up @@ -1705,6 +1731,7 @@ static JSValue nx_canvas_context_2d_init_class(JSContext *ctx, JSValueConst this
NX_DEF_FUNC(proto, "arcTo", nx_canvas_context_2d_arc_to, 5);
NX_DEF_FUNC(proto, "beginPath", nx_canvas_context_2d_begin_path, 0);
NX_DEF_FUNC(proto, "bezierCurveTo", nx_canvas_context_2d_bezier_curve_to, 6);
NX_DEF_FUNC(proto, "clearRect", nx_canvas_context_2d_clear_rect, 4);
NX_DEF_FUNC(proto, "closePath", nx_canvas_context_2d_close_path, 0);
NX_DEF_FUNC(proto, "clip", nx_canvas_context_2d_clip, 0);
NX_DEF_FUNC(proto, "drawImage", nx_canvas_context_2d_draw_image, 3);
Expand All @@ -1726,7 +1753,7 @@ static JSValue nx_canvas_context_2d_init_class(JSContext *ctx, JSValueConst this
NX_DEF_FUNC(proto, "scale", nx_canvas_context_2d_scale, 2);
NX_DEF_FUNC(proto, "setLineDash", nx_canvas_context_2d_set_line_dash, 1);
NX_DEF_FUNC(proto, "stroke", nx_canvas_context_2d_stroke, 0);
NX_DEF_FUNC(proto, "strokeRect", nx_canvas_context_2d_stroke_rect, 0);
NX_DEF_FUNC(proto, "strokeRect", nx_canvas_context_2d_stroke_rect, 4);
NX_DEF_FUNC(proto, "transform", nx_canvas_context_2d_transform, 6);
NX_DEF_FUNC(proto, "translate", nx_canvas_context_2d_translate, 2);
JS_FreeValue(ctx, proto);
Expand Down

0 comments on commit 94697da

Please sign in to comment.