Skip to content

Commit e9c3708

Browse files
authored
fix: ensure ICU base path on Windows, initialize pixel buffer correctly, fix segmentation fault on macOS Intel (#46)
* some fixes * maybe fix * fmt * temp * fmt * x * fix?? * pls * fmt * why dont it work * fmt * ci: remove prebuilt test
1 parent a700bd1 commit e9c3708

File tree

11 files changed

+47
-31
lines changed

11 files changed

+47
-31
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ jobs:
8888
- name: Run Tests
8989
env:
9090
DENO_SKIA_LOCAL: 1
91-
run: deno run -A --unstable ./test/test.ts
91+
run: deno run -A --unstable test/test.ts
9292

9393
- name: Release
9494
uses: softprops/action-gh-release@master

deno.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"build": "cd native/build && CC=clang CXX=clang++ cmake .. && cmake --build . --config Release",
88
"build-win": "rm -rf native/build && mkdir native/build && cd native/build && cmake .. -G \"Visual Studio 17 2022\" -T ClangCL && cmake --build . --config Release",
99
"test": "deno run -A --unstable ./test/test.ts",
10+
"test-prebuilt": "deno run -A --unstable --import-map=./test/import_map.json ./test/test.ts",
1011
"test-pdf": "deno run -A --unstable ./test/pdf.ts",
1112
"test-svg": "deno run -A --unstable ./test/svg.ts",
1213
"bench-deno": "deno bench -A --unstable bench/deno.js",
@@ -17,7 +18,7 @@
1718

1819
"fmt": {
1920
"files": {
20-
"exclude": ["skia", "bench/node_modules", "build"]
21+
"exclude": ["skia", "bench/node_modules", "build", "native/build"]
2122
}
2223
}
2324
}

native/include/canvas.hpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,16 @@
1313
#include "include/gpu/GrDirectContext.h"
1414
#include "include/gpu/gl/GrGLInterface.h"
1515

16+
typedef enum sk_canvas_backend {
17+
kBackendCPU,
18+
kBackendOpenGL,
19+
} sk_canvas_backend;
20+
1621
typedef struct sk_canvas {
1722
SkSurface* surface;
1823
GrDirectContext* context;
19-
void* pixels;
2024
void* context_2d;
25+
sk_canvas_backend backend;
2126
} sk_canvas;
2227

2328
typedef struct sk_context_state {

native/src/canvas.cpp

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,16 @@ extern "C" {
88

99
sk_canvas* sk_canvas_create(int width, int height) {
1010
sk_canvas* canvas = new sk_canvas();
11-
SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
12-
size_t rowBytes = info.minRowBytes();
13-
size_t size = info.computeByteSize(rowBytes);
14-
canvas->pixels = malloc(size);
15-
canvas->surface = SkSurface::MakeRasterDirect(info, canvas->pixels, rowBytes).release();
11+
canvas->backend = kBackendCPU;
12+
canvas->surface = SkSurface::MakeRasterN32Premul(width, height).release();
1613
canvas->context_2d = sk_canvas_create_context(canvas);
1714
return canvas;
1815
}
1916

2017
sk_canvas* sk_canvas_create_gl(int width, int height) {
2118
sk_canvas* canvas = new sk_canvas();
19+
canvas->backend = kBackendOpenGL;
20+
2221
auto interface = GrGLMakeNativeInterface();
2322

2423
if (interface == nullptr) {
@@ -63,9 +62,6 @@ extern "C" {
6362
void sk_canvas_destroy(sk_canvas* canvas) {
6463
canvas->surface->unref();
6564
sk_context_destroy((sk_context*) canvas->context_2d);
66-
if (canvas->pixels != nullptr) {
67-
free(canvas->pixels);
68-
}
6965
delete canvas;
7066
}
7167

@@ -121,18 +117,13 @@ extern "C" {
121117
}
122118

123119
void sk_canvas_set_size(sk_canvas* canvas, int width, int height) {
124-
if (canvas->pixels != nullptr) {
120+
if (canvas->backend == kBackendCPU) {
125121
// Raster canvas
126122
canvas->surface->unref();
127123
sk_context_destroy((sk_context*) canvas->context_2d);
128-
free(canvas->pixels);
129-
SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
130-
size_t rowBytes = info.minRowBytes();
131-
size_t size = info.computeByteSize(rowBytes);
132-
canvas->pixels = malloc(size);
133-
canvas->surface = SkSurface::MakeRasterDirect(info, canvas->pixels, rowBytes).release();
124+
canvas->surface = SkSurface::MakeRasterN32Premul(width, height).release();
134125
canvas->context_2d = sk_canvas_create_context(canvas);
135-
} else {
126+
} else if (canvas->backend == kBackendOpenGL) {
136127
// OpenGL canvas
137128
canvas->surface->unref();
138129
sk_context_destroy((sk_context*) canvas->context_2d);

native/src/context2d.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ extern sk_sp<skia::textlayout::FontCollection> fontCollection;
99

1010
void free_style(Style* style) {
1111
if (style->shader != nullptr) {
12-
style->shader.~sk_sp();
12+
style->shader->unref();
1313
}
1414
}
1515

@@ -100,7 +100,7 @@ sk_context_state* clone_context_state(sk_context_state* state) {
100100
void free_context_state(sk_context_state* state) {
101101
free_style(&state->fillStyle);
102102
free_style(&state->strokeStyle);
103-
if (state->filter.get() != nullptr) state->filter.~sk_sp();
103+
if (state->filter.get() != nullptr) state->filter->unref();
104104
delete state->paint;
105105
delete state->transform;
106106
free_font(state->font);
@@ -1213,6 +1213,7 @@ extern "C" {
12131213
/// Filters
12141214

12151215
void sk_context_filter_reset(sk_context* context) {
1216+
if (context->state->filter.get() != nullptr) context->state->filter->unref();
12161217
context->state->filter = sk_sp((SkImageFilter*) nullptr);
12171218
}
12181219

native/src/pattern.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ extern "C" {
4545
}
4646

4747
sk_sp<SkShader> sk_pattern_to_shader(sk_pattern* pattern) {
48-
return pattern->bitmap->makeShader(pattern->tmx, pattern->tmy, SkSamplingOptions({1.0f / 3.0f, 1.0f / 3.0f}), &pattern->ts);
48+
auto shader = pattern->bitmap->makeShader(pattern->tmx, pattern->tmy, SkSamplingOptions({1.0f / 3.0f, 1.0f / 3.0f}), &pattern->ts);
49+
shader->ref();
50+
return shader;
4951
}
5052
}

src/canvas.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { CanvasRenderingContext2D } from "./context2d.ts";
2-
import ffi, { cstr, getBuffer } from "./ffi.ts";
2+
import ffi, { cstr, encodeBase64, getBuffer } from "./ffi.ts";
33
import { ColorSpace } from "./image.ts";
44

55
const {
@@ -139,9 +139,7 @@ export class Canvas {
139139

140140
toDataURL(format: ImageFormat = "png", quality = 100) {
141141
const buffer = this.encode(format, quality);
142-
return `data:image/${format};base64,${
143-
(Deno as any).core.ops.op_base64_encode(buffer)
144-
}`;
142+
return `data:image/${format};base64,${encodeBase64(buffer)}`;
145143
}
146144

147145
/**

src/ffi.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -944,7 +944,11 @@ if (LOCAL_BUILD) {
944944
}
945945

946946
await ensureDir(dirname(cacheIcuBasePath));
947-
947+
try {
948+
await Deno.mkdir(cacheIcuBasePath, { recursive: true });
949+
} catch (_) {
950+
// ignore if already exists
951+
}
948952
await Deno.writeFile(
949953
cacheIcuPath,
950954
new Uint8Array(await response.arrayBuffer()),
@@ -964,17 +968,26 @@ export default lib;
964968
const {
965969
op_ffi_cstr_read,
966970
op_ffi_get_buf,
971+
op_base64_encode,
972+
op_base64_decode,
967973
}: {
968974
op_ffi_cstr_read: (ptr: Deno.PointerValue) => string;
969975
op_ffi_get_buf: (
970976
ptr: Deno.PointerValue,
971977
offset: number,
972978
size: number,
973979
) => ArrayBuffer;
974-
} = (Deno as any).core.ops;
980+
op_base64_encode: (buf: Uint8Array) => string;
981+
op_base64_decode: (base64: string) => Uint8Array;
982+
} = (Deno as any)[(Deno as any).internal].core.ops;
975983

976984
export function cstr(str: string) {
977985
return new TextEncoder().encode(str + "\0");
978986
}
979987

980-
export { op_ffi_cstr_read as readCstr, op_ffi_get_buf as getBuffer };
988+
export {
989+
op_base64_decode as decodeBase64,
990+
op_base64_encode as encodeBase64,
991+
op_ffi_cstr_read as readCstr,
992+
op_ffi_get_buf as getBuffer,
993+
};

src/image.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import ffi, { cstr } from "./ffi.ts";
1+
import ffi, { cstr, decodeBase64 } from "./ffi.ts";
22

33
const {
44
sk_image_destroy,
@@ -68,7 +68,7 @@ export class Image extends EventTarget {
6868
const isBase64 = data.lastIndexOf("base64", comma) !== -1;
6969
const content = data.slice(comma + 1);
7070
const buffer = isBase64
71-
? (Deno as any).core.ops.op_base64_decode(content)
71+
? decodeBase64(content)
7272
: new TextEncoder().encode(content);
7373
this.src = buffer;
7474
return;

test/import_map.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"imports": {
3+
"../": "../"
4+
}
5+
}

0 commit comments

Comments
 (0)