Skip to content

Commit

Permalink
fix: text align position
Browse files Browse the repository at this point in the history
  • Loading branch information
Brooooooklyn committed Oct 20, 2021
1 parent 085d74e commit 435e102
Show file tree
Hide file tree
Showing 11 changed files with 108 additions and 16 deletions.
Binary file added __test__/snapshots/text-align-center.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added __test__/snapshots/text-align-end.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added __test__/snapshots/text-align-left.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added __test__/snapshots/text-align-right.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added __test__/snapshots/text-align-start.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
37 changes: 37 additions & 0 deletions __test__/text.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { readFileSync } from 'fs'
import { join } from 'path'

import ava, { TestInterface } from 'ava'

import { GlobalFonts, createCanvas, Canvas, SKRSContext2D } from '../index'
import { snapshotImage } from './image-snapshot'

const test = ava as TestInterface<{
canvas: Canvas
ctx: SKRSContext2D
}>

const fontIosevka = readFileSync(join(__dirname, 'fonts', 'iosevka-slab-regular.ttf'))

console.assert(GlobalFonts.register(fontIosevka), 'Register Iosevka font failed')

test.beforeEach((t) => {
const canvas = createCanvas(512, 512)
t.context.canvas = canvas
t.context.ctx = canvas.getContext('2d')!
})

for (const align of ['center', 'end', 'left', 'right', 'start'] as CanvasTextAlign[]) {
test(`text-align-${align}`, async (t) => {
const { ctx, canvas } = t.context
const x = canvas.width / 2
ctx.strokeStyle = 'black'
ctx.moveTo(x, 0)
ctx.lineTo(x, canvas.height)
ctx.stroke()
ctx.textAlign = align
ctx.font = '16px Iosevka Slab'
ctx.fillText('Hello Canvas', 0, 200)
await snapshotImage(t)
})
}
45 changes: 41 additions & 4 deletions skia-c/skia_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@ extern "C"
float max_width,
float x,
float y,
float canvas_width,
skiac_font_collection *c_collection,
float font_size,
int weight,
Expand All @@ -358,6 +359,7 @@ extern "C"
{
auto font_collection = c_collection->collection;
auto font_style = SkFontStyle(weight, stretch, (SkFontStyle::Slant)slant);
auto text_direction = (TextDirection)direction;
SkTArray<SkString> families;
SkStrSplit(font_family, ",", &families);
TextStyle text_style;
Expand All @@ -380,8 +382,7 @@ extern "C"
ParagraphStyle paragraph_style;
paragraph_style.turnHintingOff();
paragraph_style.setTextStyle(text_style);
paragraph_style.setTextAlign((TextAlign)align);
paragraph_style.setTextDirection((TextDirection)direction);
paragraph_style.setTextDirection(text_direction);
ParagraphBuilderImpl builder(paragraph_style, font_collection);
builder.addText(text, text_len);
auto paragraph = static_cast<ParagraphImpl *>(builder.Build().release());
Expand Down Expand Up @@ -444,8 +445,44 @@ extern "C"

if (c_canvas)
{
auto align_factor = 0;
auto paint_x = x + line_width * align_factor;
auto canvas_center = canvas_width / 2.0f;
float paint_x;
switch ((TextAlign)align)
{
case TextAlign::kLeft:
paint_x = x + canvas_center;
break;
case TextAlign::kCenter:
paint_x = x + canvas_center - (line_width / 2);
break;
case TextAlign::kRight:
paint_x = x + canvas_center - line_width;
break;
// Unreachable
case TextAlign::kJustify:
paint_x = x;
break;
case TextAlign::kStart:
if (text_direction == TextDirection::kLtr)
{
paint_x = x;
}
else
{
paint_x = x + canvas_width - line_width;
}
break;
case TextAlign::kEnd:
if (text_direction == TextDirection::kRtl)
{
paint_x = x;
}
else
{
paint_x = x + canvas_width - line_width;
}
break;
};
auto need_scale = line_width > max_width;
if (need_scale)
{
Expand Down
1 change: 1 addition & 0 deletions skia-c/skia_c.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ extern "C"
float max_width,
float x,
float y,
float canvas_width,
skiac_font_collection *c_collection,
float font_size,
int weight,
Expand Down
8 changes: 5 additions & 3 deletions src/ctx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,7 @@ impl Context {
x,
y,
max_width,
self.width as f32,
weight,
stretch as i32,
slant,
Expand All @@ -672,7 +673,7 @@ impl Context {
state.text_align,
state.text_direction,
&shadow_paint,
);
)?;
surface.restore();
}

Expand All @@ -681,6 +682,7 @@ impl Context {
x,
y,
max_width,
self.width as f32,
weight,
stretch as i32,
slant,
Expand All @@ -691,7 +693,7 @@ impl Context {
state.text_align,
state.text_direction,
paint,
);
)?;
Ok(())
}

Expand All @@ -713,7 +715,7 @@ impl Context {
state.text_align,
state.text_direction,
&fill_paint,
));
)?);
Ok(line_metrics)
}

Expand Down
10 changes: 10 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::ffi::NulError;

use thiserror::Error;

use crate::sk::Matrix;
Expand Down Expand Up @@ -26,6 +28,14 @@ pub enum SkError {
U32ToStrokeJoinError(u32),
#[error("[`{0}`] is not valid transform")]
InvalidTransform(Matrix),
#[error("Convert String to CString failed")]
NulError,
#[error("[`{0}`]")]
Generic(String),
}

impl From<NulError> for SkError {
fn from(_: NulError) -> Self {
Self::NulError
}
}
23 changes: 14 additions & 9 deletions src/sk.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::convert::TryFrom;
use std::f32::consts::PI;
use std::ffi::{c_void, CStr, CString};
use std::ffi::{c_void, CStr, CString, NulError};
use std::fmt;
use std::ops::{Deref, DerefMut};
use std::os::raw::c_char;
Expand Down Expand Up @@ -359,6 +359,7 @@ mod ffi {
max_width: f32,
x: f32,
y: f32,
canvas_width: f32,
font_collection: *mut skiac_font_collection,
font_size: f32,
weight: i32,
Expand Down Expand Up @@ -1975,6 +1976,7 @@ impl Canvas {
x: f32,
y: f32,
max_width: f32,
canvas_width: f32,
weight: u32,
stretch: i32,
slant: FontStyle,
Expand All @@ -1985,9 +1987,9 @@ impl Canvas {
align: TextAlign,
direction: TextDirection,
paint: &Paint,
) {
let c_text = std::ffi::CString::new(text).unwrap();
let c_font_family = std::ffi::CString::new(font_family).unwrap();
) -> Result<(), NulError> {
let c_text = std::ffi::CString::new(text)?;
let c_font_family = std::ffi::CString::new(font_family)?;

unsafe {
ffi::skiac_canvas_get_line_metrics_or_draw_text(
Expand All @@ -1996,6 +1998,7 @@ impl Canvas {
max_width,
x,
y,
canvas_width,
font_collection.0,
font_size,
weight as i32,
Expand All @@ -2009,7 +2012,8 @@ impl Canvas {
self.0,
ptr::null_mut(),
);
}
};
Ok(())
}

pub fn get_line_metrics(
Expand All @@ -2025,9 +2029,9 @@ impl Canvas {
align: TextAlign,
direction: TextDirection,
paint: &Paint,
) -> ffi::skiac_line_metrics {
let c_text = std::ffi::CString::new(text).unwrap();
let c_font_family = std::ffi::CString::new(font_family).unwrap();
) -> Result<ffi::skiac_line_metrics, NulError> {
let c_text = std::ffi::CString::new(text)?;
let c_font_family = std::ffi::CString::new(font_family)?;

let mut line_metrics = ffi::skiac_line_metrics::default();

Expand All @@ -2038,6 +2042,7 @@ impl Canvas {
0.0,
0.0,
0.0,
0.0,
font_collection.0,
font_size,
weight as i32,
Expand All @@ -2052,7 +2057,7 @@ impl Canvas {
&mut line_metrics,
);
}
line_metrics
Ok(line_metrics)
}

pub fn draw_surface(
Expand Down

1 comment on commit 435e102

@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: 435e102 Previous: 085d74e Ratio
Draw house#skia-canvas 27 ops/sec (±0.11%) 26 ops/sec (±0.25%) 0.96
Draw house#node-canvas 21 ops/sec (±0.23%) 21 ops/sec (±0.32%) 1
Draw house#@napi-rs/skia 25 ops/sec (±0.17%) 25 ops/sec (±0.8%) 1
Draw gradient#skia-canvas 26 ops/sec (±0.07%) 25.5 ops/sec (±0.48%) 0.98
Draw gradient#node-canvas 20 ops/sec (±0.16%) 20.4 ops/sec (±0.19%) 1.02
Draw gradient#@napi-rs/skia 24 ops/sec (±0.11%) 24.6 ops/sec (±0.05%) 1.03

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

Please sign in to comment.