Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

0.0.7 pr.17 #22

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 25 additions & 6 deletions soft-skia-wasm/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
extern crate soft_skia;
mod utils;

use std::collections::HashMap;

use base64;
use soft_skia::provider::{Providers, Group, Provider, GroupClip};
use soft_skia::provider::{Providers, Group, GroupClip};
use wasm_bindgen::prelude::*;
use soft_skia::instance::Instance;
use soft_skia::shape::{Circle, Line, Points, RoundRect, Shapes, PaintStyle, DrawContext, Image};
use soft_skia::shape::{Circle, Line, Points, RoundRect, Shapes, PaintStyle, Image, Text};
use soft_skia::shape::Rect;
use soft_skia::shape::ColorU8;
use soft_skia::tree::Node;
Expand Down Expand Up @@ -96,6 +94,15 @@ pub struct WASMImageAttr {
height: u32,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct WASMTextAttr {
text: String,
x: i32,
y: i32,
font_size: Option<f32>,
color: Option<String>
}


#[derive(Serialize, Deserialize, Debug)]
pub enum WASMShapesAttr {
Expand All @@ -106,7 +113,8 @@ pub enum WASMShapesAttr {
P(WASMPointsAttr),
G(WASMGroupAttr),
GC(WASMGroupClipAttr),
I(WASMImageAttr)
I(WASMImageAttr),
T(WASMTextAttr),
}

#[derive(Serialize, Deserialize, Debug)]
Expand All @@ -118,6 +126,7 @@ pub struct WASMShape {
impl SoftSkiaWASM {
#[wasm_bindgen(constructor)]
pub fn new(id: usize) -> Self {
utils::set_panic_hook();
let instance = Instance::new(id);
SoftSkiaWASM(instance)
}
Expand Down Expand Up @@ -206,7 +215,6 @@ impl SoftSkiaWASM {
#[wasm_bindgen(js_name = setAttrBySerde)]
pub fn set_attr_by_serde(&mut self, id: usize, value: JsValue) {
let message: WASMShape = serde_wasm_bindgen::from_value(value).unwrap();

match message.attr {
WASMShapesAttr::R(WASMRectAttr{ width, height, x, y , color, style}) => {
let color = parse_color(color);
Expand Down Expand Up @@ -281,6 +289,17 @@ impl SoftSkiaWASM {
}) => {
self.0.set_shape_to_child(id, Shapes::I(Image { image, x, y, width, height }))
}
WASMShapesAttr::T(WASMTextAttr{
x,
y,
text,
font_size,
color
}) => {
let color = parse_color(color);
let font_size = font_size.unwrap_or(16.0);
self.0.set_shape_to_child(id, Shapes::T(Text { text, x, y, font_size, color }))
}
};
}
}
Expand Down
5 changes: 3 additions & 2 deletions soft-skia/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ license = "MIT"

[dependencies]
png = "0.17.5"
tiny-skia = "0.9.0"
base64 = "0.21.0"
tiny-skia = "0.10.0"
base64 = "0.21.0"
fontdue = "0.7.3"
Binary file added soft-skia/assets/Roboto-Regular.ttf
Binary file not shown.
94 changes: 90 additions & 4 deletions soft-skia/src/shape.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use std::collections::HashMap;

use fontdue::{layout::{Layout, LayoutSettings, CoordinateSystem, TextStyle}, Font, Metrics};
pub use tiny_skia::{ColorU8, FillRule, Mask, Paint, PathBuilder, Pixmap, Stroke, Transform};
use tiny_skia::{LineCap, LineJoin, Path, PixmapPaint};
use std::iter::zip;

#[derive(Debug)]
pub enum Shapes {
Expand All @@ -11,6 +13,7 @@ pub enum Shapes {
L(Line),
P(Points),
I(Image),
T(Text),
}

#[derive(Debug)]
Expand Down Expand Up @@ -41,7 +44,10 @@ impl DrawContext {
pub trait Shape {
fn default() -> Self;
fn draw(&self, pixmap: &mut Pixmap, context: &DrawContext) -> ();
fn get_path(&self, context: &DrawContext) -> Path;
fn get_path(&self, context: &DrawContext) -> Path {
let pb = PathBuilder::new();
pb.finish().unwrap()
}
}

#[derive(Debug, Clone, Copy)]
Expand Down Expand Up @@ -105,6 +111,15 @@ pub struct Image {
pub height: u32,
}

#[derive(Debug)]
pub struct Text {
pub text: String,
pub x: i32,
pub y: i32,
pub font_size: f32,
pub color: Option<ColorU8>,
}

impl Shapes {
pub fn draw(&self, pixmap: &mut Pixmap, context: &DrawContext) -> () {
match self {
Expand All @@ -114,6 +129,7 @@ impl Shapes {
Shapes::L(line) => line.draw(pixmap, context),
Shapes::P(points) => points.draw(pixmap, context),
Shapes::I(image) => image.draw(pixmap, context),
Shapes::T(text) => text.draw(pixmap, context),
}
}

Expand All @@ -125,6 +141,7 @@ impl Shapes {
Shapes::L(line) => line.get_path(context),
Shapes::P(points) => points.get_path(context),
Shapes::I(image) => image.get_path(context),
Shapes::T(text) => text.get_path(context),
}
}
}
Expand Down Expand Up @@ -510,10 +527,79 @@ impl Shape for Image {
None,
);
}
fn get_path(&self, context: &DrawContext) -> Path {
let pb = PathBuilder::new();
pb.finish().unwrap()

}

impl Shape for Text {
fn default() -> Self {
todo!()
}

fn draw(&self, pixmap: &mut Pixmap, context: &DrawContext) -> () {
let font = include_bytes!("../assets/Roboto-Regular.ttf") as &[u8];
let roboto_regular = Font::from_bytes(font, fontdue::FontSettings::default()).unwrap();
let fonts = &[roboto_regular];
let mut layout = Layout::new(CoordinateSystem::PositiveYDown);
layout.reset(&LayoutSettings {
..LayoutSettings::default()
});
layout.append(fonts, &TextStyle::new(&self.text, self.font_size, 0));

let mut glyphs:Vec<Vec<u8>> = vec![];
self.text.chars().for_each(|c| {
let (_, bitmap) = fonts[0].rasterize(c, self.font_size);
glyphs.push(bitmap);
});
let dim= compute_dim(&layout);

let mut bitmap:Vec<u8> = vec![0; dim.0 * dim.1];
for (pos, char_bitmap) in zip(layout.glyphs(), &glyphs) {
let x = pos.x as i32;
let y = pos.y as i32 as i32;
let width = pos.width as usize;
let height = pos.height as usize;
let mut i = 0;
for y in y..y+height as i32 {
for x in x..x+width as i32 {
let index = ((y * dim.0 as i32 + x)) as usize;
if index < bitmap.len() {
bitmap[index] = char_bitmap[i];
}
i += 1;
}
}
}
let mut rgba_bitmap:Vec<u8> = vec![];
for i in 0..bitmap.len() {
if let Some(color) = self.color {
rgba_bitmap.extend([color.red(), color.green(), color.blue(), bitmap[i]].iter());
} else {
rgba_bitmap.extend([0, 0, 0, bitmap[i]].iter());
}
}

let p = Pixmap::from_vec(rgba_bitmap, tiny_skia::IntSize::from_wh(dim.0 as u32, dim.1 as u32).unwrap()).unwrap();
pixmap.draw_pixmap(
self.x,
self.y,
p.as_ref(),
&PixmapPaint::default(),
Transform::from_row(1.0, 0.0, 0.0, 1.0, 0.0, 0.0),
None,
);

}
}

fn compute_dim(layout: &Layout) -> (usize, usize) {
let (mut x1, mut y1, mut x2, mut y2): (i32, i32, i32, i32) = (0, 0, 0, 0);
for pos in layout.glyphs() {
x1 = x1.min(pos.x as i32);
y1 = y1.min(pos.y as i32);
x2 = x2.max(pos.x as i32+pos.width as i32);
y2 = y2.max(pos.y as i32+pos.height as i32);
}
return (1+(x2-x1) as usize, (y2-y1) as usize)
}

#[cfg(test)]
Expand Down
4 changes: 4 additions & 0 deletions vue-playground/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
VLine,
VPoints,
VImage,
VText,
}"
@error="(e: any) => void 0"
@input="input"
Expand Down Expand Up @@ -98,6 +99,7 @@ import launch, {
VLine,
VPoints,
VImage,
VText,
} from "vue-skia";
import { VueLive } from "vue-live";
import GithubCorners from "@uivjs/vue-github-corners";
Expand All @@ -119,6 +121,7 @@ export default defineComponent({
VLine,
VPoints,
VImage,
VText
},
data() {
return {
Expand All @@ -133,6 +136,7 @@ export default defineComponent({
VLine,
VPoints,
VImage,
VText,
code,
LoadingCode,
debug: false,
Expand Down
1 change: 1 addition & 0 deletions vue-playground/src/code.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export default `<v-surface :width="360" :height="360">
</template>
<v-circle :cx="0" :cy="60" :r="50" :style="'fill'" />
<v-circle :cx="0" :cy="60" :r="70" />
<v-text :x="70" :y="0" :fontSize="16" color="red" text="Hello"></v-text>
</v-group>
</v-surface>
`;
33 changes: 33 additions & 0 deletions vue-skia-framework/components/VText.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<template>
<v-sk-text :text="text" :x="x" :y="y" :fontSize="fontSize" :color="color" />
</template>

<script lang="ts">
import { defineComponent, PropType } from "vue";

export default defineComponent({
name: "VText",
props: {
text: {
type: String as PropType<string>,
required: true,
},
x: {
type: Number as PropType<number>,
required: true,
},
y: {
type: Number as PropType<number>,
required: true,
},
fontSize: {
type: Number as PropType<number>,
required: false
},
color: {
type: String as PropType<string>,
required: false
}
}
});
</script>
3 changes: 2 additions & 1 deletion vue-skia-framework/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import VRoundRect from "./components/VRoundRect.vue";
import VLine from "./components/VLine.vue";
import VPoints from "./components/VPoints.vue";
import VImage from './components/VImage.vue';
import VText from './components/VText.vue';

export default launch;
export { plugin as VueSkia }
export { VSurface, VGroup, VRect, VCircle, VRoundRect, VLine, VPoints, VImage }
export { VSurface, VGroup, VRect, VCircle, VRoundRect, VLine, VPoints, VImage, VText }
16 changes: 15 additions & 1 deletion vue-skia-framework/plugin/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ const WidgetList = [
'RoundRect',
'Rect',
'Circle',
'Image'
'Image',
'Text'
];

const VSKNode = (name: string) => {
Expand Down Expand Up @@ -173,6 +174,19 @@ const VSKNode = (name: string) => {
},
});
}
if (name === "Text") {
core.setAttrBySerde(instance._ssw_id, {
attr: {
T: {
text: attrs.text,
x: attrs.x,
y: attrs.y,
font_size: attrs.fontSize,
color: attrs.color,
},
},
});
}
}

onBeforeUnmount(() => {
Expand Down
Loading