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

feat: Add basic support for RTL text direction. #1637

Merged
merged 6 commits into from
Sep 21, 2023
Merged
Show file tree
Hide file tree
Changes from 3 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
22 changes: 22 additions & 0 deletions src/Context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ var COMMA = ',',
'strokeText',
'transform',
'translate',
'trySetLetterSpacing',
xkxx marked this conversation as resolved.
Show resolved Hide resolved
];

var CONTEXT_PROPERTIES = [
Expand All @@ -82,6 +83,7 @@ var CONTEXT_PROPERTIES = [
'lineJoin',
'lineWidth',
'miterLimit',
'direction',
'font',
'textAlign',
'textBaseline',
Expand All @@ -91,6 +93,11 @@ var CONTEXT_PROPERTIES = [
] as const;

const traceArrMax = 100;

interface CanvasRenderingContext2DFeatureDetection extends CanvasRenderingContext2D {
letterSpacing: string | undefined;
}

/**
* Konva wrapper around native 2d canvas context. It has almost the same API of 2d context with some additional functions.
* With core Konva shapes you don't need to use this object. But you will use it if you want to create
Expand Down Expand Up @@ -705,6 +712,21 @@ export class Context {
translate(x: number, y: number) {
this._context.translate(x, y);
}
/**
* Set letterSpacing if supported by browser.
* @method
* @name Konva.Context#trySetLetterSpacing
* @returns true if successful, false if not supported.
*/
trySetLetterSpacing(letterSpacing: number): boolean {
xkxx marked this conversation as resolved.
Show resolved Hide resolved
var context = this._context as CanvasRenderingContext2DFeatureDetection;
var letterSpacingSupported = 'letterSpacing' in context;

if (letterSpacingSupported) {
context.letterSpacing = letterSpacing + "px";
}
return letterSpacingSupported;
}
_enableTrace() {
var that = this,
len = CONTEXT_METHODS.length,
Expand Down
33 changes: 32 additions & 1 deletion src/shapes/Text.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export function stringToArray(string: string) {
}

export interface TextConfig extends ShapeConfig {
direction?: string;
text?: string;
fontFamily?: string;
fontSize?: number;
Expand All @@ -46,6 +47,7 @@ var AUTO = 'auto',
CONTEXT_2D = '2d',
DASH = '-',
LEFT = 'left',
LTR = 'ltr',
TEXT = 'text',
TEXT_UPPER = 'Text',
TOP = 'top',
Expand All @@ -55,11 +57,13 @@ var AUTO = 'auto',
PX_SPACE = 'px ',
SPACE = ' ',
RIGHT = 'right',
RTL = 'rtl',
WORD = 'word',
CHAR = 'char',
NONE = 'none',
ELLIPSIS = '…',
ATTR_CHANGE_LIST = [
'direction',
'fontFamily',
'fontSize',
'fontStyle',
Expand Down Expand Up @@ -132,6 +136,7 @@ function checkDefaultFill(config?: TextConfig) {
* @memberof Konva
* @augments Konva.Shape
* @param {Object} config
* @param {String} [config.direction] default is ltr
* @param {String} [config.fontFamily] default is Arial
* @param {Number} [config.fontSize] in pixels. Default is 12
* @param {String} [config.fontStyle] can be 'normal', 'italic', or 'bold', '500' or even 'italic bold'. 'normal' is the default.
Expand Down Expand Up @@ -185,6 +190,7 @@ export class Text extends Shape<TextConfig> {
fontSize = this.fontSize(),
lineHeightPx = this.lineHeight() * fontSize,
verticalAlign = this.verticalAlign(),
direction = this.direction(),
alignY = 0,
align = this.align(),
totalWidth = this.getWidth(),
Expand All @@ -201,12 +207,15 @@ export class Text extends Shape<TextConfig> {
var lineTranslateX = 0;
var lineTranslateY = 0;

context.setAttr('direction', direction);
xkxx marked this conversation as resolved.
Show resolved Hide resolved

context.setAttr('font', this._getContextFont());

context.setAttr('textBaseline', MIDDLE);

context.setAttr('textAlign', LEFT);


// handle vertical alignment
if (verticalAlign === MIDDLE) {
alignY = (this.getHeight() - textArrLen * lineHeightPx - padding * 2) / 2;
Expand Down Expand Up @@ -282,7 +291,10 @@ export class Text extends Shape<TextConfig> {
context.stroke();
context.restore();
}
if (letterSpacing !== 0 || align === JUSTIFY) {
// As `letterSpacing` isn't supported on Safari, we use this polyfill.
// The exception is for RTL text, which we rely on native as it cannot
// be supported otherwise.
if (direction !== RTL && (letterSpacing !== 0 || align === JUSTIFY)) {
// var words = text.split(' ');
spacesNumber = text.split(' ').length - 1;
var array = stringToArray(text);
Expand All @@ -303,11 +315,13 @@ export class Text extends Shape<TextConfig> {
lineTranslateX += this.measureSize(letter).width + letterSpacing;
}
} else {
context.trySetLetterSpacing(letterSpacing);
xkxx marked this conversation as resolved.
Show resolved Hide resolved
this._partialTextX = lineTranslateX;
this._partialTextY = translateY + lineTranslateY;
this._partialText = text;

context.fillStrokeShape(this);
context.trySetLetterSpacing(0);
xkxx marked this conversation as resolved.
Show resolved Hide resolved
}
context.restore();
if (textArrLen > 1) {
Expand Down Expand Up @@ -615,6 +629,7 @@ export class Text extends Shape<TextConfig> {
return super._useBufferCanvas();
}

direction: GetSet<string, this>;
fontFamily: GetSet<string, this>;
fontSize: GetSet<number, this>;
fontStyle: GetSet<string, this>;
Expand Down Expand Up @@ -682,6 +697,22 @@ Factory.overWriteSetter(Text, 'width', getNumberOrAutoValidator());

Factory.overWriteSetter(Text, 'height', getNumberOrAutoValidator());


/**
* get/set direction
* @name Konva.Text#direction
* @method
* @param {String} direction
* @returns {String}
* @example
* // get direction
* var direction = text.direction();
*
* // set direction
* text.direction('rtl');
*/
Factory.addGetterSetter(Text, 'direction', 'ltr');
xkxx marked this conversation as resolved.
Show resolved Hide resolved

/**
* get/set font family
* @name Konva.Text#fontFamily
Expand Down
Loading