Skip to content

Commit

Permalink
refactor: use picture recorder backend
Browse files Browse the repository at this point in the history
  • Loading branch information
Brooooooklyn committed Sep 9, 2022
1 parent 8491685 commit 2cacca1
Show file tree
Hide file tree
Showing 5 changed files with 236 additions and 42 deletions.
44 changes: 43 additions & 1 deletion skia-c/skia_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,38 @@ extern "C"
SkGraphics::PurgeAllCaches();
}

void skiac_create_picture_recorder(uint32_t width, uint32_t height, skiac_picture_recorder_created *pr)
{
auto picture_recorder = new SkPictureRecorder();
auto canvas = picture_recorder->beginRecording((SkScalar)width, (SkScalar)height);
auto surface = canvas->getSurface();
pr->recorder = reinterpret_cast<skiac_picture_recorder *>(picture_recorder);
pr->canvas = reinterpret_cast<skiac_canvas *>(canvas);
pr->surface = reinterpret_cast<skiac_surface *>(surface);
}

void skiac_picture_recorder_destroy(skiac_picture_recorder *pr)
{
delete reinterpret_cast<SkPictureRecorder *>(pr);
}

skiac_picture *skiac_picture_recorder_finish_as_picture(skiac_picture_recorder *pr)
{
auto picture_recorder = reinterpret_cast<SkPictureRecorder *>(pr);
auto picture = picture_recorder->finishRecordingAsPicture().release();
return reinterpret_cast<skiac_picture *>(picture);
}

void skiac_picture_ref(skiac_picture *picture)
{
SkSafeRef(reinterpret_cast<SkPicture *>(picture));
}

void skiac_picture_destroy(skiac_picture *picture)
{
SkSafeUnref(reinterpret_cast<SkPicture *>(picture));
}

// Surface

static SkSurface *skiac_surface_create(int width, int height, SkAlphaType alphaType, uint8_t cs)
Expand Down Expand Up @@ -133,7 +165,7 @@ extern "C"
void skiac_surface_destroy(skiac_surface *c_surface)
{
// SkSurface is ref counted.
SURFACE_CAST->unref();
SkSafeUnref(SURFACE_CAST);
}

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

void skiac_canvas_draw_picture(
skiac_canvas *c_canvas,
skiac_picture *c_picture,
skiac_matrix *c_matrix,
skiac_paint *c_paint)
{
auto picture = reinterpret_cast<SkPicture *>(c_picture);
CANVAS_CAST->drawPicture(picture, MATRIX_CAST, PAINT_CAST);
}

void skiac_canvas_get_line_metrics_or_draw_text(
const char *text,
size_t text_len,
Expand Down
22 changes: 22 additions & 0 deletions skia-c/skia_c.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <include/core/SkPicture.h>
#include <include/core/SkSamplingOptions.h>
#include <include/core/SkString.h>
#include <include/core/SkPictureRecorder.h>
#include <include/effects/SkImageFilters.h>
#include <include/pathops/SkPathOps.h>
#include <include/utils/SkParsePath.h>
Expand Down Expand Up @@ -47,10 +48,12 @@

using namespace skia::textlayout;

typedef struct skiac_picture_recorder skiac_picture_recorder;
typedef struct skiac_surface skiac_surface;
typedef struct skiac_canvas skiac_canvas;
typedef struct skiac_paint skiac_paint;
typedef struct skiac_path skiac_path;
typedef struct skiac_picture skiac_picture;
typedef struct skiac_shader skiac_shader;
typedef struct skiac_path_effect skiac_path_effect;
typedef struct skiac_matrix skiac_matrix;
Expand Down Expand Up @@ -137,6 +140,13 @@ struct skiac_font_collection
}
};

struct skiac_picture_recorder_created
{
skiac_picture_recorder *recorder;
skiac_canvas *canvas;
skiac_surface *surface;
};

struct skiac_line_metrics
{
float ascent;
Expand Down Expand Up @@ -212,6 +222,13 @@ struct skiac_mapped_point
extern "C"
{
void skiac_clear_all_cache();
// PictureRecorder
void skiac_create_picture_recorder(uint32_t width, uint32_t height, skiac_picture_recorder_created *pr);
void skiac_picture_recorder_destroy(skiac_picture_recorder *pr);
// Picture
skiac_picture *skiac_picture_recorder_finish_as_picture(skiac_picture_recorder *pr);
void skiac_picture_ref(skiac_picture *picture);
void skiac_picture_destroy(skiac_picture *picture);
// Surface
skiac_surface *skiac_surface_create_rgba_premultiplied(int width, int height, uint8_t cs);
void skiac_surface_create_svg(skiac_svg_surface *c_surface, int width, int height, int alphaType, uint32_t flag, uint8_t cs);
Expand Down Expand Up @@ -284,6 +301,11 @@ extern "C"
float dw,
float dh,
int filter_quality);
void skiac_canvas_draw_picture(
skiac_canvas *c_canvas,
skiac_picture *c_picture,
skiac_matrix *c_matrix,
skiac_paint *c_paint);
void skiac_canvas_get_line_metrics_or_draw_text(
const char *text,
size_t text_len,
Expand Down
32 changes: 22 additions & 10 deletions src/ctx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,26 @@ pub struct Context {
pub alpha: bool,
pub(crate) states: Vec<Context2dRenderingState>,
state: Context2dRenderingState,
pub width: u32,
pub height: u32,
pub color_space: ColorSpace,
pub stream: Option<SkWMemoryStream>,
}

impl Context {
pub fn new_recorder(width: u32, height: u32, color_space: ColorSpace) -> Result<Self> {
let surface = Surface::new_picture_recorder(width, height).ok_or_else(|| {
Error::from_reason("Create skia picture recorder surface failed".to_owned())
})?;
Ok(Self {
surface,
alpha: true,
path: SkPath::new(),
states: vec![],
state: Context2dRenderingState::default(),
color_space,
stream: None,
})
}

pub fn new_svg(
width: u32,
height: u32,
Expand All @@ -70,8 +83,6 @@ impl Context {
path: SkPath::new(),
states: vec![],
state: Context2dRenderingState::default(),
width,
height,
color_space,
stream: Some(stream),
})
Expand All @@ -86,8 +97,6 @@ impl Context {
path: SkPath::new(),
states: vec![],
state: Context2dRenderingState::default(),
width,
height,
color_space,
stream: None,
})
Expand Down Expand Up @@ -659,6 +668,7 @@ impl Context {
paint: &Paint,
) -> result::Result<(), SkError> {
let state = &self.state;
let width = self.surface.width;
let weight = state.font_style.weight;
let stretch = state.font_style.stretch;
let slant = state.font_style.style;
Expand All @@ -671,7 +681,7 @@ impl Context {
x,
y,
max_width,
self.width as f32,
width as f32,
weight,
stretch as i32,
slant,
Expand All @@ -691,7 +701,7 @@ impl Context {
x,
y,
max_width,
self.width as f32,
self.surface.width as f32,
weight,
stretch as i32,
slant,
Expand Down Expand Up @@ -785,7 +795,9 @@ pub struct CanvasRenderingContext2D {

impl ObjectFinalize for CanvasRenderingContext2D {
fn finalize(self, mut env: Env) -> Result<()> {
env.adjust_external_memory(-((self.context.width * self.context.height * 4) as i64))?;
env.adjust_external_memory(
-((self.context.surface.width * self.context.surface.height * 4) as i64),
)?;
Ok(())
}
}
Expand All @@ -803,7 +815,7 @@ impl CanvasRenderingContext2D {
let context = if let Some(flag) = flag {
Context::new_svg(width, height, flag.into(), color_space)?
} else {
Context::new(width, height, color_space)?
Context::new_recorder(width, height, color_space)?
};
Ok(Self { context })
}
Expand Down
16 changes: 12 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,12 @@ impl CanvasElement {
"png" => ContextData::Png(surface_ref),
"avif" => {
let cfg = AvifConfig::from(&quality_or_config);
ContextData::Avif(surface_ref, cfg.into(), ctx2d.width, ctx2d.height)
ContextData::Avif(
surface_ref,
cfg.into(),
ctx2d.surface.width,
ctx2d.surface.height,
)
}
_ => {
return Err(Error::new(
Expand Down Expand Up @@ -313,8 +318,8 @@ fn get_data_ref(
let config = AvifConfig::from(quality_or_config).into();
let output = avif::encode(
unsafe { slice::from_raw_parts(data, size) },
ctx2d.width,
ctx2d.height,
ctx2d.surface.width,
ctx2d.surface.height,
&config,
)
.map_err(|e| Error::new(Status::GenericFailure, format!("{}", e)))?;
Expand Down Expand Up @@ -462,7 +467,10 @@ impl SVGCanvas {
#[napi]
pub fn get_content(&self, env: Env) -> Result<JsBuffer> {
let svg_data_stream = self.ctx.context.stream.as_ref().unwrap();
let svg_data = svg_data_stream.data(self.ctx.context.width, self.ctx.context.height);
let svg_data = svg_data_stream.data(
self.ctx.context.surface.width,
self.ctx.context.surface.height,
);
unsafe {
env
.create_buffer_with_borrowed_data(svg_data.0.ptr, svg_data.0.size, svg_data, |d, _| {
Expand Down
Loading

1 comment on commit 2cacca1

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark

Benchmark suite Current: 2cacca1 Previous: 8491685 Ratio
Draw house#skia-canvas 26 ops/sec (±0.24%) 24 ops/sec (±0.5%) 0.92
Draw house#node-canvas 21 ops/sec (±0.27%) 26 ops/sec (±0.9%) 1.24
Draw house#@napi-rs/skia 22 ops/sec (±0.38%) 23 ops/sec (±0.18%) 1.05
Draw gradient#skia-canvas 24 ops/sec (±0.3%) 23 ops/sec (±0.05%) 0.96
Draw gradient#node-canvas 20 ops/sec (±0.34%) 25 ops/sec (±0.23%) 1.25
Draw gradient#@napi-rs/skia 21 ops/sec (±0.39%) 22 ops/sec (±0.15%) 1.05

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.