Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 52330b8

Browse files
committed
support ctx.direction and textAlign start/end
1 parent 0b2edc1 commit 52330b8

File tree

6 files changed

+47
-10
lines changed

6 files changed

+47
-10
lines changed

‎CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ project adheres to [Semantic Versioning](http://semver.org/).
1313

1414
### Added
1515
* Support for accessibility and links in PDFs
16+
* `ctx.direction` is implemented: `'rtl'` or `'ltr'` set the base direction of text
17+
* `ctx.textAlign` `'start'` and `'end'` are now `'right'` and `'left'` when `ctx.direction === 'rtl'`
1618

1719
### Fixed
1820
* Fix a crash in `getImageData` when the rectangle is entirely outside the canvas. ([#2024](https://github.com/Automattic/node-canvas/issues/2024))

‎index.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ export class CanvasRenderingContext2D {
290290
textBaseline: CanvasTextBaseline;
291291
textAlign: CanvasTextAlign;
292292
canvas: Canvas;
293+
direction: 'ltr' | 'rtl';
293294
}
294295

295296
export class CanvasGradient {

‎src/Canvas.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ enum text_align_t : int8_t {
3737
TEXT_ALIGNMENT_LEFT = -1,
3838
TEXT_ALIGNMENT_CENTER = 0,
3939
TEXT_ALIGNMENT_RIGHT = 1,
40-
// Currently same as LEFT and RIGHT without RTL support:
4140
TEXT_ALIGNMENT_START = -2,
4241
TEXT_ALIGNMENT_END = 2
4342
};

‎src/CanvasRenderingContext2d.cc

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,8 @@ Context2d::Initialize(Napi::Env& env, Napi::Object& exports) {
161161
InstanceAccessor<&Context2d::GetStrokeStyle, &Context2d::SetStrokeStyle>("strokeStyle", napi_default_jsproperty),
162162
InstanceAccessor<&Context2d::GetFont, &Context2d::SetFont>("font", napi_default_jsproperty),
163163
InstanceAccessor<&Context2d::GetTextBaseline, &Context2d::SetTextBaseline>("textBaseline", napi_default_jsproperty),
164-
InstanceAccessor<&Context2d::GetTextAlign, &Context2d::SetTextAlign>("textAlign", napi_default_jsproperty)
164+
InstanceAccessor<&Context2d::GetTextAlign, &Context2d::SetTextAlign>("textAlign", napi_default_jsproperty),
165+
InstanceAccessor<&Context2d::GetDirection, &Context2d::SetDirection>("direction", napi_default_jsproperty)
165166
});
166167

167168
exports.Set("CanvasRenderingContext2d", ctor);
@@ -230,6 +231,8 @@ Context2d::Context2d(const Napi::CallbackInfo& info) : Napi::ObjectWrap<Context2
230231
pango_context_set_round_glyph_positions(pango_layout_get_context(_layout), FALSE);
231232
#endif
232233

234+
pango_layout_set_auto_dir(_layout, FALSE);
235+
233236
states.emplace();
234237
state = &states.top();
235238
pango_layout_set_font_description(_layout, state->fontDescription);
@@ -762,6 +765,27 @@ Context2d::AddPage(const Napi::CallbackInfo& info) {
762765
cairo_pdf_surface_set_size(canvas()->surface(), width, height);
763766
}
764767

768+
/*
769+
* Get text direction.
770+
*/
771+
Napi::Value
772+
Context2d::GetDirection(const Napi::CallbackInfo& info) {
773+
return Napi::String::New(env, state->direction);
774+
}
775+
776+
/*
777+
* Set text direction.
778+
*/
779+
void
780+
Context2d::SetDirection(const Napi::CallbackInfo& info, const Napi::Value& value) {
781+
if (!value.IsString()) return;
782+
783+
std::string dir = value.As<Napi::String>();
784+
if (dir != "ltr" && dir != "rtl") return;
785+
786+
state->direction = dir;
787+
}
788+
765789
/*
766790
* Put image data.
767791
*
@@ -2451,6 +2475,9 @@ Context2d::paintText(const Napi::CallbackInfo&info, bool stroke) {
24512475
pango_layout_set_text(layout, str.c_str(), -1);
24522476
pango_cairo_update_layout(context(), layout);
24532477

2478+
PangoDirection pango_dir = state->direction == "ltr" ? PANGO_DIRECTION_LTR : PANGO_DIRECTION_RTL;
2479+
pango_context_set_base_dir(pango_layout_get_context(_layout), pango_dir);
2480+
24542481
if (argsNum == 3) {
24552482
scaled_by = get_text_scale(layout, args[2]);
24562483
cairo_save(context());
@@ -2522,18 +2549,26 @@ inline double getBaselineAdjustment(PangoLayout* layout, short baseline) {
25222549
void
25232550
Context2d::setTextPath(double x, double y) {
25242551
PangoRectangle logical_rect;
2552+
text_align_t alignment = state->textAlignment;
25252553

2526-
switch (state->textAlignment) {
2554+
// Convert start/end to left/right based on direction
2555+
if (alignment == TEXT_ALIGNMENT_START) {
2556+
alignment = (state->direction == "rtl") ? TEXT_ALIGNMENT_RIGHT : TEXT_ALIGNMENT_LEFT;
2557+
} else if (alignment == TEXT_ALIGNMENT_END) {
2558+
alignment = (state->direction == "rtl") ? TEXT_ALIGNMENT_LEFT : TEXT_ALIGNMENT_RIGHT;
2559+
}
2560+
2561+
switch (alignment) {
25272562
case TEXT_ALIGNMENT_CENTER:
25282563
pango_layout_get_pixel_extents(_layout, NULL, &logical_rect);
25292564
x -= logical_rect.width / 2;
25302565
break;
2531-
case TEXT_ALIGNMENT_END:
25322566
case TEXT_ALIGNMENT_RIGHT:
25332567
pango_layout_get_pixel_extents(_layout, NULL, &logical_rect);
25342568
x -= logical_rect.width;
25352569
break;
2536-
default: ;
2570+
default: // TEXT_ALIGNMENT_LEFT
2571+
break;
25372572
}
25382573

25392574
y -= getBaselineAdjustment(_layout, state->textBaseline);
@@ -2687,13 +2722,12 @@ Napi::Value
26872722
Context2d::GetTextAlign(const Napi::CallbackInfo& info) {
26882723
const char* align;
26892724
switch (state->textAlignment) {
2690-
default:
2691-
// TODO the default is supposed to be "start"
26922725
case TEXT_ALIGNMENT_LEFT: align = "left"; break;
26932726
case TEXT_ALIGNMENT_START: align = "start"; break;
26942727
case TEXT_ALIGNMENT_CENTER: align = "center"; break;
26952728
case TEXT_ALIGNMENT_RIGHT: align = "right"; break;
26962729
case TEXT_ALIGNMENT_END: align = "end"; break;
2730+
default: align = "start";
26972731
}
26982732
return Napi::String::New(env, align);
26992733
}

‎src/CanvasRenderingContext2d.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,11 @@ struct canvas_state_t {
3131
cairo_filter_t patternQuality = CAIRO_FILTER_GOOD;
3232
float globalAlpha = 1.f;
3333
int shadowBlur = 0;
34-
text_align_t textAlignment = TEXT_ALIGNMENT_LEFT; // TODO default is supposed to be START
34+
text_align_t textAlignment = TEXT_ALIGNMENT_START;
3535
text_baseline_t textBaseline = TEXT_BASELINE_ALPHABETIC;
3636
canvas_draw_mode_t textDrawingMode = TEXT_DRAW_PATHS;
3737
bool imageSmoothingEnabled = true;
38+
std::string direction = "ltr";
3839

3940
canvas_state_t() {
4041
fontDescription = pango_font_description_from_string("sans");
@@ -182,6 +183,8 @@ class Context2d : public Napi::ObjectWrap<Context2d> {
182183
void BeginTag(const Napi::CallbackInfo& info);
183184
void EndTag(const Napi::CallbackInfo& info);
184185
#endif
186+
Napi::Value GetDirection(const Napi::CallbackInfo& info);
187+
void SetDirection(const Napi::CallbackInfo& info, const Napi::Value& value);
185188
inline void setContext(cairo_t *ctx) { _context = ctx; }
186189
inline cairo_t *context(){ return _context; }
187190
inline Canvas *canvas(){ return _canvas; }

‎test/canvas.test.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -569,8 +569,6 @@ describe('Canvas', function () {
569569
const canvas = createCanvas(200, 200)
570570
const ctx = canvas.getContext('2d')
571571

572-
assert.equal('left', ctx.textAlign) // default TODO wrong default
573-
ctx.textAlign = 'start'
574572
assert.equal('start', ctx.textAlign)
575573
ctx.textAlign = 'center'
576574
assert.equal('center', ctx.textAlign)

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /