Skip to content

Commit

Permalink
feat: add font collection singleton scaffold
Browse files Browse the repository at this point in the history
  • Loading branch information
doodlewind committed May 4, 2021
1 parent caf41d8 commit 9b7a00a
Show file tree
Hide file tree
Showing 7 changed files with 159 additions and 13 deletions.
7 changes: 5 additions & 2 deletions index.js
Expand Up @@ -8,7 +8,7 @@ const { loadBinding } = require('@node-rs/helper')
* loadBinding helper will load `skia.[PLATFORM].node` from `__dirname` first
* If failed to load addon, it will fallback to load from `@napi-rs/skia-[PLATFORM]`
*/
const { CanvasRenderingContext2D, CanvasElement, Path2D, ImageData, Image, CanvasPattern } = loadBinding(
const { CanvasRenderingContext2D, CanvasElement, Path2D, ImageData, Image, CanvasPattern, GlobalFonts } = loadBinding(
__dirname,
'skia',
'@napi-rs/canvas',
Expand Down Expand Up @@ -43,6 +43,8 @@ const FillType = {
InverseEvenOdd: 3,
}

const GlobalFontsSingleton = new GlobalFonts()

CanvasRenderingContext2D.prototype.createPattern = function createPattern(image, repetition) {
if (image instanceof ImageData) {
const pattern = new CanvasPattern(image, repetition, 0)
Expand Down Expand Up @@ -87,7 +89,7 @@ Path2D.prototype.getFillTypeString = function getFillTypeString() {

function createCanvas(width, height) {
const canvasElement = new CanvasElement(width, height)
const ctx = new CanvasRenderingContext2D(width, height)
const ctx = new CanvasRenderingContext2D(width, height, GlobalFontsSingleton)

// napi can not define writable: true but enumerable: false property
Object.defineProperty(ctx, '_fillStyle', {
Expand Down Expand Up @@ -137,4 +139,5 @@ module.exports = {
StrokeCap,
StrokeJoin,
...Geometry,
GlobalFonts: GlobalFontsSingleton,
}
25 changes: 17 additions & 8 deletions skia-c/skia_c.cpp
Expand Up @@ -3,8 +3,6 @@

#include "skia_c.hpp"

using namespace skia::textlayout;

#define SURFACE_CAST reinterpret_cast<SkSurface *>(c_surface)
#define CANVAS_CAST reinterpret_cast<SkCanvas *>(c_canvas)
#define PAINT_CAST reinterpret_cast<SkPaint *>(c_paint)
Expand Down Expand Up @@ -274,17 +272,15 @@ extern "C"
skiac_canvas *c_canvas,
const char *text,
float x, float y,
skiac_font_collection *c_collection,
float font_size,
const char *font_family,
float baseline_offset,
uint8_t align,
float align_factor,
skiac_paint *c_paint)
{
auto font_collection = sk_make_sp<FontCollection>();
auto font_mgr = SkFontMgr::RefDefault();
font_collection->setDefaultFontManager(font_mgr);
font_collection->enableFontFallback();
auto font_collection = c_collection->collection;

TextStyle text_style;
text_style.setFontFamilies({ SkString(font_family) });
Expand Down Expand Up @@ -995,8 +991,6 @@ extern "C"
delete reinterpret_cast<SkString *>(c_sk_string);
}

// FontMetrics

skiac_font_metrics *skiac_font_metrics_create(const char *font_family, float font_size)
{
TextStyle text_style;
Expand All @@ -1013,4 +1007,19 @@ extern "C"
{
delete FONT_METRICS_CAST;
}

skiac_font_collection *skiac_font_collection_create()
{
return new skiac_font_collection();
}

skiac_font_collection *skiac_font_collection_clone(skiac_font_collection *c_font_collection)
{
return new skiac_font_collection(c_font_collection->collection);
}

void skiac_font_collection_destroy(skiac_font_collection *c_font_collection)
{
delete c_font_collection;
}
}
24 changes: 24 additions & 0 deletions skia-c/skia_c.hpp
Expand Up @@ -27,6 +27,8 @@

#include <stdint.h>

using namespace skia::textlayout;

typedef struct skiac_surface skiac_surface;
typedef struct skiac_canvas skiac_canvas;
typedef struct skiac_paint skiac_paint;
Expand All @@ -41,6 +43,22 @@ typedef struct skiac_image skiac_image;
typedef struct skiac_bitmap skiac_bitmap;
typedef struct skiac_sk_string skiac_sk_string;
typedef struct skiac_font_metrics skiac_font_metrics;
struct skiac_font_collection
{
sk_sp<FontCollection> collection;
skiac_font_collection() {
auto font_mgr = SkFontMgr::RefDefault();
collection = sk_make_sp<FontCollection>();
collection->setDefaultFontManager(font_mgr);
collection->enableFontFallback();
}
skiac_font_collection(sk_sp<FontCollection> collection) {
auto font_mgr = SkFontMgr::RefDefault();
collection->setDefaultFontManager(font_mgr);
collection->enableFontFallback();
this->collection = collection;
}
};
struct skiac_rect
{
float left;
Expand Down Expand Up @@ -140,6 +158,7 @@ extern "C"
skiac_canvas *c_canvas,
const char *text,
float x, float y,
skiac_font_collection *c_collection,
float font_size,
const char *font_family,
float baseline_offset,
Expand Down Expand Up @@ -284,6 +303,11 @@ extern "C"
// FontMetrics
skiac_font_metrics *skiac_font_metrics_create(const char *font_family, float font_size);
void skiac_font_metrics_destroy(skiac_font_metrics *c_font_metrics);

// FontCollection
skiac_font_collection *skiac_font_collection_create();
skiac_font_collection *skiac_font_collection_clone(skiac_font_collection *c_font_collection);
void skiac_font_collection_destroy(skiac_font_collection *c_font_collection);
}

#endif // SKIA_CAPI_H
13 changes: 10 additions & 3 deletions src/ctx.rs
Expand Up @@ -26,6 +26,7 @@ pub struct Context {
path: Path,
pub alpha: bool,
pub(crate) states: Vec<Context2dRenderingState>,
pub collection: FontCollection,
}

impl Context {
Expand Down Expand Up @@ -135,7 +136,7 @@ impl Context {
}

#[inline(always)]
pub fn new(width: u32, height: u32) -> Result<Self> {
pub fn new(width: u32, height: u32, collection: &mut FontCollection) -> Result<Self> {
let surface = Surface::new_rgba(width, height)
.ok_or_else(|| Error::from_reason("Create skia surface failed".to_owned()))?;
let mut states = Vec::new();
Expand All @@ -145,6 +146,7 @@ impl Context {
alpha: true,
path: Path::new(),
states,
collection: collection.clone(),
})
}

Expand Down Expand Up @@ -472,6 +474,7 @@ impl Context {
text,
x,
y,
&self.collection,
state.font_style.size,
&state.font_style.family,
state.text_baseline,
Expand All @@ -485,6 +488,7 @@ impl Context {
text,
x,
y,
&self.collection,
state.font_style.size,
&state.font_style.family,
state.text_baseline,
Expand Down Expand Up @@ -513,12 +517,15 @@ impl Context {
}
}

#[js_function(2)]
#[js_function(3)]
fn context_2d_constructor(ctx: CallContext) -> Result<JsUndefined> {
let width: u32 = ctx.get::<JsNumber>(0)?.try_into()?;
let height: u32 = ctx.get::<JsNumber>(1)?.try_into()?;
let collection_js = ctx.get::<JsObject>(2)?;
let collection = ctx.env.unwrap::<FontCollection>(&collection_js)?;

let mut this = ctx.this_unchecked::<JsObject>();
let context_2d = Context::new(width, height)?;
let context_2d = Context::new(width, height, collection)?;
ctx.env.wrap(&mut this, context_2d)?;
ctx.env.get_undefined()
}
Expand Down
45 changes: 45 additions & 0 deletions src/global_fonts.rs
@@ -0,0 +1,45 @@
use crate::sk::*;
use napi::*;

#[js_function]
fn register(ctx: CallContext) -> Result<JsUndefined> {
ctx.env.get_undefined()
}

#[js_function]
fn get_families(ctx: CallContext) -> Result<JsObject> {
let this = ctx.this_unchecked::<JsObject>();
let font_collection = ctx.env.unwrap::<FontCollection>(&this)?;

let mut families = ctx.env.create_object()?;
let family_names = font_collection.get_families();
for name in &family_names {
families.set_named_property(name.as_str(), ctx.env.get_boolean(true)?)?;
}

Ok(families)
}

impl FontCollection {
pub fn create_js_class(env: &Env) -> Result<JsFunction> {
env.define_class(
"GlobalFonts",
global_fonts_constructor,
&vec![
Property::new(&env, "register")?.with_method(register),
Property::new(&env, "families")?
.with_getter(get_families)
.with_property_attributes(PropertyAttributes::Enumerable),
],
)
}
}

#[js_function]
fn global_fonts_constructor(ctx: CallContext) -> Result<JsUndefined> {
let font_collection = FontCollection::new();
let mut this = ctx.this_unchecked::<JsObject>();
ctx.env.wrap(&mut this, font_collection)?;
this.define_properties(&[])?;
ctx.env.get_undefined()
}
5 changes: 5 additions & 0 deletions src/lib.rs
Expand Up @@ -30,6 +30,7 @@ mod image;
mod image_pattern;
mod path;
mod pattern;
mod global_fonts;
#[allow(dead_code)]
mod sk;
mod state;
Expand Down Expand Up @@ -61,6 +62,8 @@ fn init(mut exports: JsObject, env: Env) -> Result<()> {
&[Property::new(&env, "setTransform")?.with_method(image_pattern::set_transform)],
)?;

let global_fonts = sk::FontCollection::create_js_class(&env)?;

exports.set_named_property("CanvasRenderingContext2D", canvas_rendering_context2d)?;

exports.set_named_property("CanvasElement", canvas_element)?;
Expand All @@ -73,6 +76,8 @@ fn init(mut exports: JsObject, env: Env) -> Result<()> {

exports.set_named_property("CanvasPattern", canvas_pattern)?;

exports.set_named_property("GlobalFonts", global_fonts)?;

// pre init font regexp
FONT_REGEXP.get_or_init(init_font_regexp);
Ok(())
Expand Down
53 changes: 53 additions & 0 deletions src/sk.rs
Expand Up @@ -153,6 +153,12 @@ mod ffi {
strikeout_position: f32,
}

#[repr(C)]
#[derive(Copy, Clone, Debug)]
pub struct skiac_font_collection {
_unused: [u8; 0],
}

extern "C" {

pub fn skiac_surface_create_rgba_premultiplied(width: i32, height: i32) -> *mut skiac_surface;
Expand Down Expand Up @@ -267,6 +273,7 @@ mod ffi {
text: *const ::std::os::raw::c_char,
x: f32,
y: f32,
font_collection: *mut skiac_font_collection,
font_size: f32,
font_family: *const ::std::os::raw::c_char,
baseline_offset: f32,
Expand Down Expand Up @@ -571,6 +578,14 @@ mod ffi {
) -> *mut skiac_font_metrics;

pub fn skiac_font_metrics_destroy(c_font_metrics: *mut skiac_font_metrics);

pub fn skiac_font_collection_create() -> *mut skiac_font_collection;

pub fn skiac_font_collection_clone(
c_font_collection: *mut skiac_font_collection,
) -> *mut skiac_font_collection;

pub fn skiac_font_collection_destroy(c_font_collection: *mut skiac_font_collection);
}
}

Expand Down Expand Up @@ -1468,6 +1483,7 @@ impl Canvas {
text: &str,
x: f32,
y: f32,
font_collection: &FontCollection,
font_size: f32,
font_family: &str,
baseline: TextBaseline,
Expand All @@ -1492,6 +1508,7 @@ impl Canvas {
c_text.as_ptr(),
x,
y,
font_collection.0,
font_size,
c_font_family.as_ptr(),
baseline_offset,
Expand Down Expand Up @@ -2623,6 +2640,42 @@ impl Drop for FontMetrics {
}
}

#[derive(Debug)]
pub struct FontCollection(pub *mut ffi::skiac_font_collection);

impl FontCollection {
#[inline]
pub fn new() -> FontCollection {
unsafe {
let c_font_collection = ffi::skiac_font_collection_create();
let collection = FontCollection(c_font_collection);
collection
}
}

#[inline]
pub fn get_families(&self) -> Vec<String> {
vec![]
}
}

impl Clone for FontCollection {
fn clone(&self) -> FontCollection {
unsafe {
let c_font_collection = ffi::skiac_font_collection_clone(self.0);
let collection = FontCollection(c_font_collection);
collection
}
}
}

impl Drop for FontCollection {
#[inline]
fn drop(&mut self) {
unsafe { ffi::skiac_font_collection_destroy(self.0) }
}
}

#[inline(always)]
fn radians_to_degrees(rad: f32) -> f32 {
(rad / PI) * 180.0
Expand Down

0 comments on commit 9b7a00a

Please sign in to comment.