diff --git a/__test__/regression.spec.ts b/__test__/regression.spec.ts index c181e47d..3b8edb0a 100644 --- a/__test__/regression.spec.ts +++ b/__test__/regression.spec.ts @@ -305,3 +305,21 @@ test('draw-avif-image', async (t) => { ctx.drawImage(image, 0, 0) await snapshotImage(t, { ctx, canvas }) }) + +// https://github.com/Brooooooklyn/canvas/issues/1010 +test('canvas-pattern-1010', async (t) => { + const canvas = createCanvas(512, 512) + const tmpCanvas = createCanvas(512, 512) + const ctx = canvas.getContext('2d') + const tmpCtx = tmpCanvas.getContext('2d') + const image = await loadImage(join(__dirname, 'javascript.png')) + tmpCtx.drawImage(image, 0, 0) + const pattern = ctx.createPattern(image, 'repeat') + const pattern2 = ctx.createPattern(tmpCanvas, 'repeat') + ctx.fillStyle = pattern + ctx.fillRect(0, 0, 512 / 2, 512) + + ctx.fillStyle = pattern2 + ctx.fillRect(512 / 2, 0, 512 / 2, 512) + await snapshotImage(t, { ctx, canvas }) +}) diff --git a/__test__/snapshots/canvas-pattern-1010.png b/__test__/snapshots/canvas-pattern-1010.png new file mode 100644 index 00000000..e3aedc57 Binary files /dev/null and b/__test__/snapshots/canvas-pattern-1010.png differ diff --git a/index.d.ts b/index.d.ts index 5a690bba..40338625 100644 --- a/index.d.ts +++ b/index.d.ts @@ -107,9 +107,7 @@ export interface DOMMatrix extends DOMMatrixReadOnly { toJSON(): { [K in OmitNeverOfMatrix]: DOMMatrix[K] } } -type OmitMatrixMethod = { - [K in keyof DOMMatrix]: DOMMatrix[K] extends (...args: any[]) => any ? never : K -} +type OmitMatrixMethod = { [K in keyof DOMMatrix]: DOMMatrix[K] extends (...args: any[]) => any ? never : K } type OmitNeverOfMatrix = OmitMatrixMethod[keyof OmitMatrixMethod] @@ -278,7 +276,7 @@ export interface SKRSContext2D dh: number, ): void createPattern( - image: Image | ImageData, + image: Image | ImageData | Canvas | SvgCanvas, repeat: 'repeat' | 'repeat-x' | 'repeat-y' | 'no-repeat' | null, ): CanvasPattern getContextAttributes(): { alpha: boolean; desynchronized: boolean } @@ -393,14 +391,7 @@ export function createCanvas(width: number, height: number): Canvas export function createCanvas(width: number, height: number, svgExportFlag: SvgExportFlag): SvgCanvas interface IGlobalFonts { - readonly families: { - family: string - styles: { - weight: number - width: string - style: string - }[] - }[] + readonly families: { family: string; styles: { weight: number; width: string; style: string }[] }[] // return true if succeeded register(font: Buffer, nameAlias?: string): boolean // absolute path diff --git a/skia-c/skia_c.cpp b/skia-c/skia_c.cpp index f720e7d6..70ca0c40 100644 --- a/skia-c/skia_c.cpp +++ b/skia-c/skia_c.cpp @@ -1644,6 +1644,7 @@ extern "C" } skiac_shader *skiac_bitmap_get_shader( + bool is_canvas, skiac_bitmap *c_bitmap, int repeat_x, int repeat_y, @@ -1652,7 +1653,19 @@ extern "C" skiac_transform c_ts) { const auto ts = conv_from_transform(c_ts); - auto bitmap = reinterpret_cast(c_bitmap); + SkBitmap *bitmap; + if (is_canvas) { + auto surface = reinterpret_cast(c_bitmap); + auto bm = new SkBitmap(); + bm->allocPixels(surface->imageInfo()); + if (surface->readPixels(*bm, 0, 0)) { + bitmap = bm; + } else { + return nullptr; + } + } else { + bitmap = reinterpret_cast(c_bitmap); + } auto shader = bitmap->makeShader((SkTileMode)repeat_x, (SkTileMode)repeat_y, SkSamplingOptions({B, C}), &ts).release(); if (shader) { diff --git a/skia-c/skia_c.hpp b/skia-c/skia_c.hpp index bf876951..bd9f0ac2 100644 --- a/skia-c/skia_c.hpp +++ b/skia-c/skia_c.hpp @@ -515,6 +515,7 @@ extern "C" size_t skiac_bitmap_get_width(skiac_bitmap *c_bitmap); size_t skiac_bitmap_get_height(skiac_bitmap *c_bitmap); skiac_shader *skiac_bitmap_get_shader( + bool is_canvas, skiac_bitmap *c_bitmap, int repeat_x, int repeat_y, diff --git a/src/pattern.rs b/src/pattern.rs index 168effeb..30921394 100644 --- a/src/pattern.rs +++ b/src/pattern.rs @@ -55,6 +55,7 @@ impl CanvasPattern { repetition: Option, ) -> Result { let mut inner_bitmap = None; + let mut is_canvas = false; let bitmap = match input { Either4::A(image) => image .bitmap @@ -80,12 +81,14 @@ impl CanvasPattern { let canvas_bitmap = canvas.ctx.context.surface.get_bitmap(); let ptr = canvas_bitmap.0.bitmap; inner_bitmap = Some(canvas_bitmap); + is_canvas = true; ptr } Either4::D(svg_canvas) => { let canvas_bitmap = svg_canvas.ctx.context.surface.get_bitmap(); let ptr = canvas_bitmap.0.bitmap; inner_bitmap = Some(canvas_bitmap); + is_canvas = true; ptr } }; @@ -110,6 +113,7 @@ impl CanvasPattern { bitmap, repeat_x, repeat_y, + is_canvas, }), bitmap: inner_bitmap, }) diff --git a/src/sk.rs b/src/sk.rs index 180a4991..c8f84ccc 100644 --- a/src/sk.rs +++ b/src/sk.rs @@ -849,6 +849,7 @@ pub mod ffi { pub fn skiac_bitmap_get_height(c_bitmap: *mut skiac_bitmap) -> usize; pub fn skiac_bitmap_get_shader( + is_canvas: bool, c_bitmap: *mut skiac_bitmap, repeat_x: i32, repeat_y: i32, @@ -2973,6 +2974,7 @@ impl Shader { } pub fn from_bitmap( + is_canvas: bool, bitmap: *mut ffi::skiac_bitmap, repeat_x: TileMode, repeat_y: TileMode, @@ -2981,8 +2983,15 @@ impl Shader { ts: Transform, ) -> Option { unsafe { - let shader_ptr = - ffi::skiac_bitmap_get_shader(bitmap, repeat_x as i32, repeat_y as i32, b, c, ts.into()); + let shader_ptr = ffi::skiac_bitmap_get_shader( + is_canvas, + bitmap, + repeat_x as i32, + repeat_y as i32, + b, + c, + ts.into(), + ); Shader::from_ptr(shader_ptr) } } @@ -3581,11 +3590,13 @@ pub struct ImagePattern { pub(crate) repeat_x: TileMode, pub(crate) repeat_y: TileMode, pub(crate) transform: Transform, + pub(crate) is_canvas: bool, } impl ImagePattern { pub(crate) fn get_shader(&self) -> Option { Shader::from_bitmap( + self.is_canvas, self.bitmap, self.repeat_x, self.repeat_y,