Open raichu opened 11 years ago
A related feature request would be text along an arc.
It also seems impossible to achieve this using SVG (#512)
Wouldn't rotating glyphs (separately) by 90 degrees (counter-clockwise) suffice to have basic vertical text support? Justification, underline and strike-through wouldn't work of course, but it beats having no CJK/vertical text support.
I believe this would be a very simple change, but I'm not sure where to start.
Well, since we're talking about text rendering, it's in text.class.js. All "classes" use "render" (public, often inherited from fabric.Object) and "_render" (private, custom rendering logic) methods. Then there's 2 types of rendering for text — via Cufon (old, deprecated, using cufon.js) and native (using canvas native text rendering capabilties). So you'd probably need to look into _renderViaNative
(https://github.com/kangax/fabric.js/blob/master/src/text.class.js#L272-L305). Since we support multiline rendering (unlike native canvas text rendering), we have that logic on top. 2 relevant methods are _renderTextFill
and _renderTextStroke
— they render actual text (the rest take care of background, decoration, etc.). From there, you'll probably find _drawTextLine
which has some logic to determine character positioning depending on alignment of text, etc. but essentially boils down to calling ctx[method]
(where method is "fillText" or "strokeText"). That's the part you would need to break down into per-character rendering, together with custom transformation.
I see; native eventually calls canvas' strokeText and fillText, and as far as I found, it's not possible to apply transformation per-glyph (as the HTML5 canvas standard stands today). This means I either need to implement something like strokeText and fillText myself, or modify Cufon, which is deprecated :(
I think it is important.
Here's a crazy idea :) Since canvas doesn't support it, how about calling fillText() for each CJK glyph, with a fixed space in between? I don't think one needs to worry about kerning etc in vertical text. This requires different renderer (and toSVG function) for vertical text mode though, so maybe it's better to consider a whole new VerticalText object instead of modifying Text?
@raichu did you make it?
😅 what's the result?
any solution? :sweat:
I think this feature is necessary. Actually, I'm trying to implement vertical text, it's very common with CJK text.
Please before actually implementing it with the idea that the feature is outside the of your personal project, open an issue on the api-discussion repository and let s discuss there: what languages use vertical text and what it looks like. how vertical text static should work. how interaction should work. what code is necessary.
i ll be very happy to be available in prototyping and help, so that we can actually do something that can be merged and mantained.
Is there any progress on this?
In Japanese, vertical writing starts at the top right and goes down, and when there is a line break, it moves one line to the left. I found someone's program as follows.
var vertical_text = function(context, text, x, y) {
var textList = text.split('\n');
var lineHeight = context.measureText("あ").width;
textList.forEach(function(elm, i) {
Array.prototype.forEach.call(elm, function(ch, j) {
context.fillText(ch, x-lineHeight*i, y+lineHeight*j);
});
});
};
I hope that fabric.js will support vertical text, too.
i would very much support it.
How the cursor is supposed to work? is it vertical near the last character or is horizontal between chars?
Also do lineheight make sense, and any kind of alignment does?
我会非常支持。
游标应该如何工作?是在最后一个字符附近垂直还是在字符之间水平?
lineheight是否也有意义,并且任何对齐方式都可以吗?
It should be at the inter-character level at least in Chinese and Japanese. I think it's really time to add this feature because you can't just rely on /n And happy Christmas Eve!
So the character should be HORIZONTAL between chars. Do you have a screenshot of any vertical text writing app to see it in action?
How does MS word or google docs behave with vertical text?
What do people use for writing vertically that can we look at?
MS word (Japanese)
MS word textbox version
Why some character are smaller? Is there some rule or because are used as grapheme clusters? I would not add specific language information that requires knowledge of that specific language.
Some Japanese characters are smaller. For example, UnicodeU+3041, 3043, 3045, etc. are smaller than others. It is Japanese language rule.
OK, if you would support the cursor orientation and movement for vertical writing, maybe I can customize it by myself.
does actual standard canvas text make those character smaller? or is an ignored rule so far? I m talking by canvas in general not fabric in particular.
I would love to start this. I have some info now.
Yes, those characters are made smaller in an actual standard canvas.
For example below, a character [ゆ] is smaller than others. https://jsfiddle.net/uemon/wpL3m4au/
In English, lowercase letters are smaller than uppercase letters. In the same way, some Japanese letters are smaller than other.
Those letters are set in an upper right position in vertical text, as I mentioned yesterday.
ok an in vertical alignment it goes top right. That make sense.
We could say that vertical text is like if we rotate a normal textbox clockwise of 90 degree but then we rotate each character counter clockwise 90 degree
Some Japanese symbol characters (such as '[', '<','-') rotate clockwise of 90 degree, and it is not rotated counter clockwise 90 degree in vertical text.
When you rotate each character coutner clockwise 90 degree, could you add exception as below ?
fabric.Object.prototype.exceptionVerticalRoratin = ['[, ']', '<','>']; <-★each user can define it accroding to their own language.
if ( each character of vertical text is in the exceptionVerticalRoratin array ) { don't rotate counter clockwise 90 degree } else { rotate counter clockwise 90 degree }
so the brackets are laid down horizontally, following the text flow, and so taking less space? do they break the caracteristic block sizing of japanese writing? or do they get extra space?
I think they take the same space and don't break the character block size of Japanese writing.
It may depend on the kind of the font. In a case of fixed-width font, those symbol characters take the same space. And in a case of proportional font, those symbol characters take less space.
Hi everyone. Thanks for raising the feature vertical writing. I would like to contribute to implement this feature. This is very popular in CJK text. Is there any progress on this feature?
I'm exploring text.class.js in fabricjs's source code to see how to add vertical writing. I'm thinking of implementing inputting vertical text in textbox. In canvas's Web API, I don't find any API that supports typing text in a textbox. But fabricjs can support that. How can fabricjs support typing text in a textbox inside canvas?
Hi @canhnht fabricJS can type on a canvas because it use an hidden textarea which content then gets processed by the code and painted on the canvas.
It would be good to have vertical text and also vertical text knowledge, because the main factor is that i have no idea how vertical text work and what users would expect from it ( is it RTL or LTR, how do line break works and so on ).
You could start looking at how text rendering works and how you would reposition text each grapheme cluster one under the other. The real writing would still happen on a classic horizontal textarea, that is invisible.
Oh, I got it. Thanks for your clarification. So I think the mechanism is quite similar to examples in this gist https://gist.github.com/aya-eiya/1721182 I will try implementing vertical writing based on that. Is the main code for text rendering and repositioning grapheme in the file itext.class.js? Would you mind to explain a little bit about working flow of rendering text? Could you point me to the code that renders cursor and text? Thanks in advance.
yes i can explain everything and support you in delivering the feature if you have the will and time to do so. You find most of the code in text.class.js, on the base of my experience my suggestion for possible steps are:
1) forgetting the interactive part and the cursor, just take a normal text object, write something on it, and work to have it measured and displayed vertically. ... once that work and is merged ( because we will test and merge code in small portions )
2) look at iText class, look at cursor rendering and position work ( how it gets moved with keyboard and so on, text selection for text ranges ) and adapt the cursor and selection to vertical text. ... once that work and is merged ....
3) we can look at Textbox and see if the flow adjustment make sense with vertical text too.
Does this make sense to you?
Small incremental code changes is the key to get things done, because fabricjs is large and is hard to understand and keep everything under control with large changes.
Thanks a lot for your suggestion. 👍 Fabricjs is really huge. 😅 I will try to add incremental code changes and merge small code changes as soon as possible.
I have explored fabric's source code and understood more about components in Text, IText and Textbox classes. I made some changes in fabric's code and built a demo https://github.com/canhnht/FabricJS-Demo. In this demo, it can show that these things are feasible:
From my understanding, to implement vertical writing, I think I will need to change these things in fabric's code:
From your suggestion, I will start from step 1. It seems that this step is related to calculation of width and height of character, boundary box and many other things. Currently I'm also stuck in this part. Could you help to point out the code for calculating these things when a text object is initialized? Thanks in advance.
As soon as i am back to a computer i ll link relevant pieces of code.
Fabricjs does nor measure height, it assumes is in relation with fontSize, while this can be wrong for vertical text, i m fine starting keeping that assumption.
A minimal piece of work could totally be also just add a 'vertical' true/false property to text and just let the code that calculate text width/height return the correct size.
Following with a proper rendering PR.
For the special characters i would not do anything, who uses vertical text knows how to handle them i presume, and how to input them too.
i ll write asap.
You have to give a look at initDimensions and go deep to the calls up to:
https://github.com/fabricjs/fabric.js/blob/master/src/shapes/text.class.js#L712
_measureLine
is the building block of measureLine
that is of getLineWidth
up to getTextWidth
.
It run over the characters one by one and with getGraphemeBox
https://github.com/fabricjs/fabric.js/blob/master/src/shapes/text.class.js#L744 will measure every char taking in account kerning.
Now getGraphemeBox could be as good as it is., with the difference that if the text is vertical oriente:
textHeight is the lenght of the longest line measured as if each char was typed one under the other textWidth is the sum of the largest char width for each column of text.
There are some concept like lineHeigh that would become the space between each column and also charSpacing that would still be the distance between each char inside the same column.
Thanks a lot for explaining relevant code and all the concepts. <3
I also added a vertical
true/false property to IText and added another version for each function that is affected by vertical writing.
I think I should change vertical
to Text, since it's the base class of text object and will be inherited by IText and Textbox.
For _measureLine
and _getGraphemeBox
, I will add another version for vertical writing, for example _measureLineInVerticalMode
or _getGraphemeBoxInVerticalMode
. Is that fine?
About kerned width, it seems to be the space between characters in a text. In vertical writing, will its calculation need to be changed?
i think we do not have the tools for kernedwidth vertically. Unless canvas support it natively.
for now vertical text will have all the chars high the same, no kerning, and that's it.
For me is important to have vertical text ( like also right to left ) because is not about an extra feature but a feature that is culturally important. So the first draft won't be perfect but will be there, and see it working will make possible for more people to improve it.
Hi @asturur, I'm quite confused about mechanism of positioning and resizing of boundary box in text object. In normal writing (i.e. horizontal text), when text is changed:
The resizing and positioning of boundary box in vertical writing is quite different from normal writing. I don't know where to change that mechanism. Could you help to point out part of the code for calculating boundary box? Thanks in advance.
You shouldn't be worrying of those things already :) Anyway that is not a fabricJS coded behaviour related to text. That is a side effect of the default object origin being top/left based.
If you set originX = 'center' and originY = 'center' for your object you will see that for normal text, the bounding box expands on both sizes , horizontally and vertically.
I know that vertical text are generally moving from the right to the left, but please ignore that and let's look into it when a single vertical text line works.
If you want to open a PR you should be better contributing small incremental changes toward the final goal or i won't be able to review and merge them.
Thanks a lot for your explanation. I'm trying to understand how other functions and classes of text object interact with each other and the calculations of some properties in text class. I will try to get a vertical text line work first.
Ideally Text does everything, and IText handles interactivity. Still ideally Textbox will disappear and wrapping will be an option in the Text basic class, as well as rtl and vertical.
Hi any update on this?
no. I have 5-7 small fixes i want to get out and then work on rtl text and then vertical text
Hi again! I have met an advanced demand too.(〃'▽'〃) emmmmm..........
like css writing-mode: vertical-rl;
@asturur This gist might help. From a Japanese person. https://gist.github.com/aya-eiya/1721182 Japanese character displays very well.
no. I have 5-7 small fixes i want to get out and then work on rtl text and then vertical text
Hi @asturur ! Has the problem been solved? I need the ability to arrange multiple lines of text vertically 😭 So thanks
No @zhuziqingdemao no one worked on it yet.
@asturur I've wrote a sample, it's a mess but it worked for me, hope it help. it will be great if you guys help me optimize it. https://gist.github.com/thuytv-scuti/2848ebd6214a670e6d87ddfce388448b
Vertical text is very commonly used with CJK text, so please please :)
Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.