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 772c464

Browse files
fix(TextMetrics): rtl direction + start/end textAlign (Automattic#2510)
* fix(TextMetrics): rtl direction + start/end textAlign * changelog * update tests * expose resolveTextAlignment * jest test
1 parent 1234a86 commit 772c464

File tree

4 files changed

+53
-11
lines changed

4 files changed

+53
-11
lines changed

‎CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ project adheres to [Semantic Versioning](http://semver.org/).
1515
* Fix fetching prebuilds during installation on certain newer versions of Node (#2497)
1616
* Fixed issue with fillText that was breaking subsequent fillText calls (#2171)
1717
* Fix svg rendering when the image is resized (#2498)
18+
* Fix measureText with direction rtl textAlign start/end
1819

1920
3.1.0
2021
==================

‎src/CanvasRenderingContext2d.cc

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2557,6 +2557,20 @@ inline double getBaselineAdjustment(PangoLayout* layout, short baseline) {
25572557
}
25582558
}
25592559

2560+
text_align_t
2561+
Context2d::resolveTextAlignment() {
2562+
text_align_t alignment = state->textAlignment;
2563+
2564+
// Convert start/end to left/right based on direction
2565+
if (alignment == TEXT_ALIGNMENT_START) {
2566+
return (state->direction == "rtl") ? TEXT_ALIGNMENT_RIGHT : TEXT_ALIGNMENT_LEFT;
2567+
} else if (alignment == TEXT_ALIGNMENT_END) {
2568+
return (state->direction == "rtl") ? TEXT_ALIGNMENT_LEFT : TEXT_ALIGNMENT_RIGHT;
2569+
}
2570+
2571+
return alignment;
2572+
}
2573+
25602574
/*
25612575
* Set text path for the string in the layout at (x, y).
25622576
* This function is called by paintText and won't behave correctly
@@ -2567,14 +2581,7 @@ inline double getBaselineAdjustment(PangoLayout* layout, short baseline) {
25672581
void
25682582
Context2d::setTextPath(double x, double y) {
25692583
PangoRectangle logical_rect;
2570-
text_align_t alignment = state->textAlignment;
2571-
2572-
// Convert start/end to left/right based on direction
2573-
if (alignment == TEXT_ALIGNMENT_START) {
2574-
alignment = (state->direction == "rtl") ? TEXT_ALIGNMENT_RIGHT : TEXT_ALIGNMENT_LEFT;
2575-
} else if (alignment == TEXT_ALIGNMENT_END) {
2576-
alignment = (state->direction == "rtl") ? TEXT_ALIGNMENT_LEFT : TEXT_ALIGNMENT_RIGHT;
2577-
}
2584+
text_align_t alignment = resolveTextAlignment();
25782585

25792586
switch (alignment) {
25802587
case TEXT_ALIGNMENT_CENTER:
@@ -2816,16 +2823,16 @@ Context2d::MeasureText(const Napi::CallbackInfo& info) {
28162823

28172824
metrics = PANGO_LAYOUT_GET_METRICS(layout);
28182825

2826+
text_align_t alignment = resolveTextAlignment();
2827+
28192828
double x_offset;
2820-
switch (state->textAlignment) {
2829+
switch (alignment) {
28212830
case TEXT_ALIGNMENT_CENTER:
28222831
x_offset = logical_rect.width / 2.;
28232832
break;
2824-
case TEXT_ALIGNMENT_END:
28252833
case TEXT_ALIGNMENT_RIGHT:
28262834
x_offset = logical_rect.width;
28272835
break;
2828-
case TEXT_ALIGNMENT_START:
28292836
case TEXT_ALIGNMENT_LEFT:
28302837
default:
28312838
x_offset = 0.0;

‎src/CanvasRenderingContext2d.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ class Context2d : public Napi::ObjectWrap<Context2d> {
222222
void _setStrokePattern(Napi::Value arg);
223223
void checkFonts();
224224
void paintText(const Napi::CallbackInfo&, bool);
225+
text_align_t resolveTextAlignment();
225226
Napi::Reference<Napi::Value> _fillStyle;
226227
Napi::Reference<Napi::Value> _strokeStyle;
227228
Canvas *_canvas;

‎test/canvas.test.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1026,6 +1026,39 @@ describe('Canvas', function () {
10261026
assertApprox(rm.actualBoundingBoxLeft, 19, 6)
10271027
assertApprox(rm.actualBoundingBoxRight, 1, 6)
10281028
})
1029+
1030+
it('resolves text alignment wrt Context2d#direction #2508', function () {
1031+
const canvas = createCanvas(0, 0)
1032+
const ctx = canvas.getContext('2d')
1033+
1034+
ctx.textAlign = "left";
1035+
const leftMetrics = ctx.measureText('hello');
1036+
assert(leftMetrics.actualBoundingBoxLeft < leftMetrics.actualBoundingBoxRight, "leftMetrics.actualBoundingBoxLeft < leftMetrics.actualBoundingBoxRight");
1037+
1038+
ctx.textAlign = "right";
1039+
const rightMetrics = ctx.measureText('hello');
1040+
assert(rightMetrics.actualBoundingBoxLeft > rightMetrics.actualBoundingBoxRight, "metrics.actualBoundingBoxLeft > metrics.actualBoundingBoxRight");
1041+
1042+
ctx.textAlign = "start";
1043+
1044+
ctx.direction = "ltr";
1045+
const ltrStartMetrics = ctx.measureText('hello');
1046+
assert.deepStrictEqual(ltrStartMetrics, leftMetrics, "ltr start metrics should equal left metrics");
1047+
1048+
ctx.direction = "rtl";
1049+
const rtlStartMetrics = ctx.measureText('hello');
1050+
assert.deepStrictEqual(rtlStartMetrics, rightMetrics, "rtl start metrics should equal right metrics");
1051+
1052+
ctx.textAlign = "end";
1053+
1054+
ctx.direction = "ltr";
1055+
const ltrEndMetrics = ctx.measureText('hello');
1056+
assert.deepStrictEqual(ltrEndMetrics, rightMetrics, "ltr end metrics should equal right metrics");
1057+
1058+
ctx.direction = "rtl";
1059+
const rtlEndMetrics = ctx.measureText('hello');
1060+
assert.deepStrictEqual(rtlEndMetrics, leftMetrics, "rtl end metrics should equal left metrics");
1061+
})
10291062
})
10301063

10311064
it('Context2d#fillText()', function () {

0 commit comments

Comments
(0)

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