From 7a7536eaaedd06c1031487bdee19821d9c764d6e Mon Sep 17 00:00:00 2001 From: William Candillon Date: Wed, 5 Jan 2022 11:02:57 +0100 Subject: [PATCH] Fix rectangle processing (#82) --- docs/docs/shapes/polygons.md | 33 +++++++++++++++++-- example/src/Examples/API/Shapes2.tsx | 3 +- .../renderer/components/shaders/Shader.tsx | 5 +-- .../src/renderer/components/shapes/Rect.tsx | 26 ++++++++------- package/src/renderer/processors/Shapes.ts | 26 +++++++-------- package/src/renderer/typeddash.ts | 3 -- 6 files changed, 64 insertions(+), 32 deletions(-) diff --git a/docs/docs/shapes/polygons.md b/docs/docs/shapes/polygons.md index 7448f77135..42cf8703e7 100644 --- a/docs/docs/shapes/polygons.md +++ b/docs/docs/shapes/polygons.md @@ -15,8 +15,6 @@ Draws a rectangle. | y | `number` | Y coordinate. | | width | `number` | Width of the rectangle. | | height | `number` | Height of the rectangle. | -| rx? | `number` | Horizontal corner radius. Defaults to `ry` if specified or 0. | -| ry? | `number` | Vertical corner radius. Defaults to `rx` if specified or 0. | ```tsx twoslash import {Canvas, Rect} from "@shopify/react-native-skia"; @@ -25,6 +23,37 @@ const RectDemo = () => { return ( + + ); +}; +``` + +## RRect + +Draws a rounded rectangle. + +| Name | Type | Description | +|:-------|:---------|:--------------------------------------------------------------| +| x | `number` | X coordinate. | +| y | `number` | Y coordinate. | +| width | `number` | Width of the rectangle. | +| height | `number` | Height of the rectangle. | +| rx? | `number` | Horizontal corner radius. Defaults to `ry` if specified or 0. | +| ry? | `number` | Vertical corner radius. Defaults to `rx` if specified or 0. | + +```tsx twoslash +import {Canvas, RRect} from "@shopify/react-native-skia"; + +const RectDemo = () => { + return ( + + { - - hasProperty(obj, "x") && hasProperty(obj, "y"); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (obj as any).x !== undefined && (obj as any).y !== undefined; type Uniform = number | number[] | Vector; diff --git a/package/src/renderer/components/shapes/Rect.tsx b/package/src/renderer/components/shapes/Rect.tsx index cb896d1226..a63ce6d6b6 100644 --- a/package/src/renderer/components/shapes/Rect.tsx +++ b/package/src/renderer/components/shapes/Rect.tsx @@ -1,23 +1,27 @@ import React from "react"; import type { CustomPaintProps } from "../../processors"; -import type { RectOrRRectDef } from "../../processors/Shapes"; -import { isRRect } from "../../processors/Shapes"; -import type { IRect } from "../../../skia/Rect"; -import { processRectOrRRect } from "../../processors"; +import type { RectDef, RRectDef } from "../../processors/Shapes"; +import { processRect, processRRect } from "../../processors/Shapes"; import type { AnimatedProps } from "../../processors/Animations/Animations"; import { useDrawing } from "../../nodes/Drawing"; -export type RectProps = RectOrRRectDef & CustomPaintProps; +export type RectProps = RectDef & CustomPaintProps; export const Rect = (props: AnimatedProps) => { const onDraw = useDrawing(props, ({ canvas, paint }, rectProps) => { - const rect = processRectOrRRect(rectProps); - if (isRRect(rect)) { - canvas.drawRRect(rect, paint); - } else { - canvas.drawRect(rect as IRect, paint); - } + const rect = processRect(rectProps); + canvas.drawRect(rect, paint); + }); + return ; +}; + +export type RRectProps = RRectDef & CustomPaintProps; + +export const RRect = (props: AnimatedProps) => { + const onDraw = useDrawing(props, ({ canvas, paint }, rectProps) => { + const rrect = processRRect(rectProps); + canvas.drawRRect(rrect, paint); }); return ; }; diff --git a/package/src/renderer/processors/Shapes.ts b/package/src/renderer/processors/Shapes.ts index 5553a40ae2..275b326525 100644 --- a/package/src/renderer/processors/Shapes.ts +++ b/package/src/renderer/processors/Shapes.ts @@ -1,7 +1,9 @@ +// Here we use any because hasOwnProperty doesn't work on JSI instances not does the (key in obj) syntax +// And using Object.keys for such use-case is incredibly slow +/* eslint-disable @typescript-eslint/no-explicit-any */ import type { ReactNode } from "react"; import type { IRect, IRRect } from "../../skia"; -import { hasProperty } from "../typeddash"; import type { Vector as Point } from "./math/Vector"; import { vec } from "./math/Vector"; @@ -26,7 +28,7 @@ interface ScalarCircleDef { export type CircleDef = PointCircleDef | ScalarCircleDef; const isCircleScalarDef = (def: CircleDef): def is ScalarCircleDef => - hasProperty(def, "cx"); + (def as any).cx; export const processCircle = (def: CircleDef) => { if (isCircleScalarDef(def)) { return { c: vec(def.cx, def.cy), r: def.r }; @@ -64,12 +66,12 @@ export const center = (r: IRect | IRRect) => ? vec(r.rect.x + r.rect.width / 2, r.rect.y + r.rect.height / 2) : vec(r.x + r.width / 2, r.y + r.height / 2); -export const isRectCtor = (def: RectOrRRectDef): def is RectCtor => - !hasProperty(def, "rect"); -export const isRect = (def: RectOrRRectDef): def is IRect => - hasProperty(def, "rect"); -export const isRRect = (def: RectOrRRectDef): def is IRRect => - !isRectCtor(def) && hasProperty(def, "rx"); +export const isRRectCtor = (def: RRectDef): def is RRectCtor => + (def as any).rect !== undefined; +export const isRectCtor = (def: RectDef): def is RectCtor => + (def as any).rect !== undefined; +export const isRRect = (def: IRect | IRRect): def is IRRect => + (def as any).rect !== undefined; export interface RectCtor { x: number; @@ -84,7 +86,7 @@ export interface RRectCtor extends RectCtor { } export type RectDef = RectCtor | { rect: IRect }; -export type RectOrRRectDef = RRectCtor | { rect: IRect | IRRect }; +export type RRectDef = RRectCtor | { rect: IRRect }; export const processRect = (def: RectDef) => { if (isRectCtor(def)) { @@ -94,10 +96,8 @@ export const processRect = (def: RectDef) => { } }; -export const processRectOrRRect = (def: RectOrRRectDef) => { - if (isRectCtor(def) && !hasProperty(def, "rx") && !hasProperty(def, "ry")) { - return rect(def.x, def.y, def.width, def.height); - } else if (isRectCtor(def)) { +export const processRRect = (def: RRectDef) => { + if (isRRectCtor(def)) { const { rx, ry } = def; return rrect( rect(def.x, def.y, def.width, def.height), diff --git a/package/src/renderer/typeddash.ts b/package/src/renderer/typeddash.ts index 0f62658443..b648dbfc1a 100644 --- a/package/src/renderer/typeddash.ts +++ b/package/src/renderer/typeddash.ts @@ -1,8 +1,5 @@ export const mapKeys = (obj: T) => Object.keys(obj) as (keyof T)[]; -export const hasProperty = (obj: unknown, key: string) => - !!(typeof obj === "object" && obj !== null && key in obj); - export const exhaustiveCheck = (a: never): never => { throw new Error(`Unexhaustive handling for ${a}`); };