Skip to content

Commit

Permalink
fix: draw text on svg
Browse files Browse the repository at this point in the history
  • Loading branch information
Brooooooklyn committed Feb 19, 2024
1 parent f3a699b commit 539cd87
Show file tree
Hide file tree
Showing 8 changed files with 199 additions and 12 deletions.
140 changes: 140 additions & 0 deletions __test__/image-og.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
26 changes: 23 additions & 3 deletions __test__/regression.spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { promises as fs } from 'fs'
import { join } from 'path'
import { promises as fs } from 'node:fs'
import { join } from 'node:path'

import test from 'ava'

import { createCanvas, loadImage, GlobalFonts } from '../index'
import { createCanvas, loadImage, GlobalFonts, Image } from '../index'
import { snapshotImage } from './image-snapshot'

test('transform-with-state', async (t) => {
Expand Down Expand Up @@ -170,3 +170,23 @@ test('draw-text-center-maxWidth', async (t) => {
ctx.fillText(`Very ${'long '.repeat(20)} text`, canvas.width / 2, 50, maxWidth)
await snapshotImage(t, { ctx, canvas })
})

test('draw-svg-with-text', async (t) => {
GlobalFonts.registerFromPath(join(__dirname, 'fonts', 'iosevka-slab-regular.ttf'))
const canvas = createCanvas(1200, 700)
const ctx = canvas.getContext('2d')
const ViceCityGradient = ctx.createLinearGradient(0, 0, 1200, 0)
ViceCityGradient.addColorStop(0, '#3494e6')
ViceCityGradient.addColorStop(1, '#EC6EAD')
ctx.fillStyle = ViceCityGradient
ctx.fillRect(0, 0, 1200, 700)
ctx.fillStyle = 'white'
ctx.font = '48px Iosevka Slab'
const Title = '@napi-rs/image'
ctx.fillText(Title, 80, 100)

const Arrow = new Image()
Arrow.src = await fs.readFile(join(__dirname, 'image-og.svg'))
ctx.drawImage(Arrow, 80, 60)
await snapshotImage(t, { ctx, canvas })
})
Binary file added __test__/snapshots/draw-svg-with-text.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions skia-c/skia_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1486,11 +1486,11 @@ extern "C"
bitmap_info->height = info.height();
}

void skiac_bitmap_make_from_svg(const uint8_t *data, size_t length, float width, float height, skiac_bitmap_info *bitmap_info, uint8_t cs)
void skiac_bitmap_make_from_svg(const uint8_t *data, size_t length, float width, float height, skiac_bitmap_info *bitmap_info, skiac_font_collection *c_collection, uint8_t cs)
{
auto color_space = COLOR_SPACE_CAST;
auto svg_stream = new SkMemoryStream(data, length, false);
auto svg_dom = SkSVGDOM::MakeFromStream(*svg_stream);
auto svg_dom = SkSVGDOM::Builder().setFontManager(c_collection->assets).make(*svg_stream);
auto svg_root = svg_dom->getRoot();
auto svg_container_size = svg_root->intrinsicSize(SkSVGLengthContext(SkSize::Make(0, 0)));
if (svg_container_size.isZero())
Expand Down
6 changes: 5 additions & 1 deletion skia-c/skia_c.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ class TypefaceFontProviderCustom : public TypefaceFontProvider

sk_sp<SkTypeface> onLegacyMakeTypeface(const char family_name[], SkFontStyle style) const override
{
if (!family_name)
{
return nullptr;
}
auto style_set = this->onMatchFamily(family_name);
if (!style_set)
{
Expand Down Expand Up @@ -469,7 +473,7 @@ extern "C"

// Bitmap
void skiac_bitmap_make_from_buffer(const uint8_t *ptr, size_t size, skiac_bitmap_info *bitmap_info);
void skiac_bitmap_make_from_svg(const uint8_t *data, size_t length, float width, float height, skiac_bitmap_info *bitmap_info, uint8_t cs);
void skiac_bitmap_make_from_svg(const uint8_t *data, size_t length, float width, float height, skiac_bitmap_info *bitmap_info, skiac_font_collection *c_collection, uint8_t cs);
skiac_bitmap *skiac_bitmap_make_from_image_data(uint8_t *ptr, size_t width, size_t height, size_t row_bytes, size_t size, int ct, int at);
size_t skiac_bitmap_get_width(skiac_bitmap *c_bitmap);
size_t skiac_bitmap_get_height(skiac_bitmap *c_bitmap);
Expand Down
2 changes: 1 addition & 1 deletion src/ctx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1497,7 +1497,7 @@ impl CanvasRenderingContext2D {
if !image.complete {
return Ok(());
}
image.regenerate_bitmap_if_need();
image.regenerate_bitmap_if_need()?;
if let Some(bitmap) = &mut image.bitmap {
BitmapRef::Borrowed(bitmap)
} else {
Expand Down
13 changes: 10 additions & 3 deletions src/image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ use std::str::FromStr;
use base64::{engine::general_purpose::STANDARD, Engine};
use napi::{bindgen_prelude::*, NapiValue};

use crate::error::SkError;
use crate::global_fonts::get_font;
use crate::sk::Bitmap;
use crate::sk::ColorSpace;

Expand Down Expand Up @@ -252,16 +254,18 @@ impl Image {
Some(Bitmap::from_buffer(data.as_ptr() as *mut u8, length))
} else if self.is_svg_image(data_ref, length) {
self.is_svg = true;
let font = get_font().map_err(SkError::from)?;
if (self.width - -1.0).abs() > f64::EPSILON && (self.height - -1.0).abs() > f64::EPSILON {
Bitmap::from_svg_data_with_custom_size(
data.as_ptr(),
length,
self.width as f32,
self.height as f32,
self.color_space,
&font,
)
} else {
Bitmap::from_svg_data(data.as_ptr(), length, self.color_space)
Bitmap::from_svg_data(data.as_ptr(), length, self.color_space, &font)
}
} else {
self.on_error(env, &this)?;
Expand All @@ -281,19 +285,22 @@ impl Image {
Ok(())
}

pub(crate) fn regenerate_bitmap_if_need(&mut self) {
pub(crate) fn regenerate_bitmap_if_need(&mut self) -> Result<()> {
if !self.need_regenerate_bitmap || !self.is_svg || self.src.is_none() {
return;
return Ok(());
}
if let Some(data) = self.src.as_mut() {
let font = get_font().map_err(SkError::from)?;
self.bitmap = Bitmap::from_svg_data_with_custom_size(
data.as_ref().as_ptr(),
data.as_ref().len(),
self.width as f32,
self.height as f32,
self.color_space,
&font,
);
}
Ok(())
}

fn on_load(&self, this: &This) -> Result<()> {
Expand Down
20 changes: 18 additions & 2 deletions src/sk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -809,6 +809,7 @@ pub mod ffi {
width: f32,
height: f32,
info: *mut skiac_bitmap_info,
font_collection: *mut skiac_font_collection,
cs: u8,
);

Expand Down Expand Up @@ -3420,14 +3421,27 @@ impl Bitmap {
}
}

pub fn from_svg_data(data: *const u8, size: usize, color_space: ColorSpace) -> Option<Self> {
pub fn from_svg_data(
data: *const u8,
size: usize,
color_space: ColorSpace,
fc: &FontCollection,
) -> Option<Self> {
let mut bitmap_info = ffi::skiac_bitmap_info {
bitmap: ptr::null_mut(),
width: 0,
height: 0,
};
unsafe {
ffi::skiac_bitmap_make_from_svg(data, size, -1.0, -1.0, &mut bitmap_info, color_space as u8);
ffi::skiac_bitmap_make_from_svg(
data,
size,
-1.0,
-1.0,
&mut bitmap_info,
fc.0,
color_space as u8,
);

if bitmap_info.bitmap.is_null() {
return None;
Expand All @@ -3442,6 +3456,7 @@ impl Bitmap {
width: f32,
height: f32,
color_space: ColorSpace,
fc: &FontCollection,
) -> Option<Self> {
let mut bitmap_info = ffi::skiac_bitmap_info {
bitmap: ptr::null_mut(),
Expand All @@ -3455,6 +3470,7 @@ impl Bitmap {
width,
height,
&mut bitmap_info,
fc.0,
color_space as u8,
);

Expand Down

0 comments on commit 539cd87

Please sign in to comment.