Skip to content

Commit 2cacca1

Browse files
committed
refactor: use picture recorder backend
1 parent 8491685 commit 2cacca1

File tree

5 files changed

+236
-42
lines changed

5 files changed

+236
-42
lines changed

skia-c/skia_c.cpp

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,38 @@ extern "C"
6161
SkGraphics::PurgeAllCaches();
6262
}
6363

64+
void skiac_create_picture_recorder(uint32_t width, uint32_t height, skiac_picture_recorder_created *pr)
65+
{
66+
auto picture_recorder = new SkPictureRecorder();
67+
auto canvas = picture_recorder->beginRecording((SkScalar)width, (SkScalar)height);
68+
auto surface = canvas->getSurface();
69+
pr->recorder = reinterpret_cast<skiac_picture_recorder *>(picture_recorder);
70+
pr->canvas = reinterpret_cast<skiac_canvas *>(canvas);
71+
pr->surface = reinterpret_cast<skiac_surface *>(surface);
72+
}
73+
74+
void skiac_picture_recorder_destroy(skiac_picture_recorder *pr)
75+
{
76+
delete reinterpret_cast<SkPictureRecorder *>(pr);
77+
}
78+
79+
skiac_picture *skiac_picture_recorder_finish_as_picture(skiac_picture_recorder *pr)
80+
{
81+
auto picture_recorder = reinterpret_cast<SkPictureRecorder *>(pr);
82+
auto picture = picture_recorder->finishRecordingAsPicture().release();
83+
return reinterpret_cast<skiac_picture *>(picture);
84+
}
85+
86+
void skiac_picture_ref(skiac_picture *picture)
87+
{
88+
SkSafeRef(reinterpret_cast<SkPicture *>(picture));
89+
}
90+
91+
void skiac_picture_destroy(skiac_picture *picture)
92+
{
93+
SkSafeUnref(reinterpret_cast<SkPicture *>(picture));
94+
}
95+
6496
// Surface
6597

6698
static SkSurface *skiac_surface_create(int width, int height, SkAlphaType alphaType, uint8_t cs)
@@ -133,7 +165,7 @@ extern "C"
133165
void skiac_surface_destroy(skiac_surface *c_surface)
134166
{
135167
// SkSurface is ref counted.
136-
SURFACE_CAST->unref();
168+
SkSafeUnref(SURFACE_CAST);
137169
}
138170

139171
skiac_surface *skiac_surface_copy_rgba(
@@ -356,6 +388,16 @@ extern "C"
356388
CANVAS_CAST->drawImageRect(image, src, dst, sampling, nullptr, SkCanvas::kFast_SrcRectConstraint);
357389
}
358390

391+
void skiac_canvas_draw_picture(
392+
skiac_canvas *c_canvas,
393+
skiac_picture *c_picture,
394+
skiac_matrix *c_matrix,
395+
skiac_paint *c_paint)
396+
{
397+
auto picture = reinterpret_cast<SkPicture *>(c_picture);
398+
CANVAS_CAST->drawPicture(picture, MATRIX_CAST, PAINT_CAST);
399+
}
400+
359401
void skiac_canvas_get_line_metrics_or_draw_text(
360402
const char *text,
361403
size_t text_len,

skia-c/skia_c.hpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <include/core/SkPicture.h>
66
#include <include/core/SkSamplingOptions.h>
77
#include <include/core/SkString.h>
8+
#include <include/core/SkPictureRecorder.h>
89
#include <include/effects/SkImageFilters.h>
910
#include <include/pathops/SkPathOps.h>
1011
#include <include/utils/SkParsePath.h>
@@ -47,10 +48,12 @@
4748

4849
using namespace skia::textlayout;
4950

51+
typedef struct skiac_picture_recorder skiac_picture_recorder;
5052
typedef struct skiac_surface skiac_surface;
5153
typedef struct skiac_canvas skiac_canvas;
5254
typedef struct skiac_paint skiac_paint;
5355
typedef struct skiac_path skiac_path;
56+
typedef struct skiac_picture skiac_picture;
5457
typedef struct skiac_shader skiac_shader;
5558
typedef struct skiac_path_effect skiac_path_effect;
5659
typedef struct skiac_matrix skiac_matrix;
@@ -137,6 +140,13 @@ struct skiac_font_collection
137140
}
138141
};
139142

143+
struct skiac_picture_recorder_created
144+
{
145+
skiac_picture_recorder *recorder;
146+
skiac_canvas *canvas;
147+
skiac_surface *surface;
148+
};
149+
140150
struct skiac_line_metrics
141151
{
142152
float ascent;
@@ -212,6 +222,13 @@ struct skiac_mapped_point
212222
extern "C"
213223
{
214224
void skiac_clear_all_cache();
225+
// PictureRecorder
226+
void skiac_create_picture_recorder(uint32_t width, uint32_t height, skiac_picture_recorder_created *pr);
227+
void skiac_picture_recorder_destroy(skiac_picture_recorder *pr);
228+
// Picture
229+
skiac_picture *skiac_picture_recorder_finish_as_picture(skiac_picture_recorder *pr);
230+
void skiac_picture_ref(skiac_picture *picture);
231+
void skiac_picture_destroy(skiac_picture *picture);
215232
// Surface
216233
skiac_surface *skiac_surface_create_rgba_premultiplied(int width, int height, uint8_t cs);
217234
void skiac_surface_create_svg(skiac_svg_surface *c_surface, int width, int height, int alphaType, uint32_t flag, uint8_t cs);
@@ -284,6 +301,11 @@ extern "C"
284301
float dw,
285302
float dh,
286303
int filter_quality);
304+
void skiac_canvas_draw_picture(
305+
skiac_canvas *c_canvas,
306+
skiac_picture *c_picture,
307+
skiac_matrix *c_matrix,
308+
skiac_paint *c_paint);
287309
void skiac_canvas_get_line_metrics_or_draw_text(
288310
const char *text,
289311
size_t text_len,

src/ctx.rs

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,26 @@ pub struct Context {
4343
pub alpha: bool,
4444
pub(crate) states: Vec<Context2dRenderingState>,
4545
state: Context2dRenderingState,
46-
pub width: u32,
47-
pub height: u32,
4846
pub color_space: ColorSpace,
4947
pub stream: Option<SkWMemoryStream>,
5048
}
5149

5250
impl Context {
51+
pub fn new_recorder(width: u32, height: u32, color_space: ColorSpace) -> Result<Self> {
52+
let surface = Surface::new_picture_recorder(width, height).ok_or_else(|| {
53+
Error::from_reason("Create skia picture recorder surface failed".to_owned())
54+
})?;
55+
Ok(Self {
56+
surface,
57+
alpha: true,
58+
path: SkPath::new(),
59+
states: vec![],
60+
state: Context2dRenderingState::default(),
61+
color_space,
62+
stream: None,
63+
})
64+
}
65+
5366
pub fn new_svg(
5467
width: u32,
5568
height: u32,
@@ -70,8 +83,6 @@ impl Context {
7083
path: SkPath::new(),
7184
states: vec![],
7285
state: Context2dRenderingState::default(),
73-
width,
74-
height,
7586
color_space,
7687
stream: Some(stream),
7788
})
@@ -86,8 +97,6 @@ impl Context {
8697
path: SkPath::new(),
8798
states: vec![],
8899
state: Context2dRenderingState::default(),
89-
width,
90-
height,
91100
color_space,
92101
stream: None,
93102
})
@@ -659,6 +668,7 @@ impl Context {
659668
paint: &Paint,
660669
) -> result::Result<(), SkError> {
661670
let state = &self.state;
671+
let width = self.surface.width;
662672
let weight = state.font_style.weight;
663673
let stretch = state.font_style.stretch;
664674
let slant = state.font_style.style;
@@ -671,7 +681,7 @@ impl Context {
671681
x,
672682
y,
673683
max_width,
674-
self.width as f32,
684+
width as f32,
675685
weight,
676686
stretch as i32,
677687
slant,
@@ -691,7 +701,7 @@ impl Context {
691701
x,
692702
y,
693703
max_width,
694-
self.width as f32,
704+
self.surface.width as f32,
695705
weight,
696706
stretch as i32,
697707
slant,
@@ -785,7 +795,9 @@ pub struct CanvasRenderingContext2D {
785795

786796
impl ObjectFinalize for CanvasRenderingContext2D {
787797
fn finalize(self, mut env: Env) -> Result<()> {
788-
env.adjust_external_memory(-((self.context.width * self.context.height * 4) as i64))?;
798+
env.adjust_external_memory(
799+
-((self.context.surface.width * self.context.surface.height * 4) as i64),
800+
)?;
789801
Ok(())
790802
}
791803
}
@@ -803,7 +815,7 @@ impl CanvasRenderingContext2D {
803815
let context = if let Some(flag) = flag {
804816
Context::new_svg(width, height, flag.into(), color_space)?
805817
} else {
806-
Context::new(width, height, color_space)?
818+
Context::new_recorder(width, height, color_space)?
807819
};
808820
Ok(Self { context })
809821
}

src/lib.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,12 @@ impl CanvasElement {
251251
"png" => ContextData::Png(surface_ref),
252252
"avif" => {
253253
let cfg = AvifConfig::from(&quality_or_config);
254-
ContextData::Avif(surface_ref, cfg.into(), ctx2d.width, ctx2d.height)
254+
ContextData::Avif(
255+
surface_ref,
256+
cfg.into(),
257+
ctx2d.surface.width,
258+
ctx2d.surface.height,
259+
)
255260
}
256261
_ => {
257262
return Err(Error::new(
@@ -313,8 +318,8 @@ fn get_data_ref(
313318
let config = AvifConfig::from(quality_or_config).into();
314319
let output = avif::encode(
315320
unsafe { slice::from_raw_parts(data, size) },
316-
ctx2d.width,
317-
ctx2d.height,
321+
ctx2d.surface.width,
322+
ctx2d.surface.height,
318323
&config,
319324
)
320325
.map_err(|e| Error::new(Status::GenericFailure, format!("{}", e)))?;
@@ -462,7 +467,10 @@ impl SVGCanvas {
462467
#[napi]
463468
pub fn get_content(&self, env: Env) -> Result<JsBuffer> {
464469
let svg_data_stream = self.ctx.context.stream.as_ref().unwrap();
465-
let svg_data = svg_data_stream.data(self.ctx.context.width, self.ctx.context.height);
470+
let svg_data = svg_data_stream.data(
471+
self.ctx.context.surface.width,
472+
self.ctx.context.surface.height,
473+
);
466474
unsafe {
467475
env
468476
.create_buffer_with_borrowed_data(svg_data.0.ptr, svg_data.0.size, svg_data, |d, _| {

0 commit comments

Comments
 (0)