GNOME Bugzilla – Bug 64538
pango_layout_set_justify() doesn't work
Last modified: 2007-05-04 11:42:14 UTC
All though pango_layout_set_justify() is present, it does nothing. Doing this properly would require changing the shaper interfaces so that the shaper could decide where to add space to glyph strings, for instance, for kashida insertion for Arabic. However, it's possible a quick hack could be done by using the log attrs to insert white space: - If the line has white space in it, insert space in the white spaces; possibly adding more in intersentence whitespaces than interword white spaces. - Otherwise, insert space equally between all clusters (might look funny, in some cases, but between all glyphs doesn't make sense)
Probably best waiting for 1.2 to prevent weird dependencies on 1.0.x.
I might be time to bring this out of the "Future" category. Gnumeric would like this feature now. Clearing milestone.
Are you volunteering to do the work for 1.4?
I could probably do the hacky expand-all-spaces-equally version, but I have positively no clue about how to do Arabic right.
There is some discussion in: http://mail.gnome.org/archives/gtk-i18n-list/2003-January/msg00055.html Putting on the 1.4 API freeze milestone, in hopes that someone (very unlikely to me) will to get to the item...
The Unicode standard has some information on where to insert kashidas, in section 8.2. Microsoft also has a nice article which may help a bit: http://www.microsoft.com/middleeast/msdn/JustifyingText-CSS.aspx We could ask the people at http://arabeyes.org/ for help. CSS3 has lots of settings that affect justification, so we should probably go with them as much as possible. See the text module currently at: http://www.w3.org/TR/2003/CR-css3-text-20030514/ They have 7 settings for the text-justify property: auto | inter-word | inter-ideograph | distribute | newspaper | inter-cluster | kashida These specify how word and character spacing are to be used. They also have a "text-kashida-space" property to specify the ratio of kashida expansion to whitespace expansion.
At the very least the fact that this is currently non-functional should be documented.
Punt once more... Sat Feb 21 11:31:16 2004 Owen Taylor <otaylor@redhat.com> * pango/pango-layout.c (pango_layout_set_justify): Add a docs note about non-implementedness. (#64538)
*** Bug 145582 has been marked as a duplicate of this bug. ***
*** Bug 166353 has been marked as a duplicate of this bug. ***
I've done a bit of work on this. Here's where I've got so far: http://www.dachaplin.dsl.pipex.com/pangoxt/pango.patch (I'm using Pango 1.8.0 at the moment, though it seems to apply fairly cleanly to head.) I've tried to support the justification settings from CSS3, except for kashidas. There are also a few minor bits to fix (adjusting tabs, handling kerning changes, and fixing cursor problems). If someone can spot a major problem with it let me know. Otherwise I'll try to finish off the last few bits and then add in hyphenation support. The main functions are layout_with_specific_width() which determines the break points, and build_lines() and finish_line() that build the lines & do the justification.
I've just put a new patch up at http://www.dachaplin.dsl.pipex.com/pangoxt/ I've rewritten it to try to make the code as simple as possible (though of course it is still very complicated). It is also now quite a bit more flexible, and I've updated it to handle the newer CSS3 justification settings. I still need to fix the cursor problems, and adjust tabs a bit. But I think it is nearly ready now.
Damon, glade to see you're working on this patch again. I was working on your patch couple of months ago and I saw that you implemented CSS's design for justification. IMO it's not a good approach for pango. In HTML/CSS design, you HAVE TO tag each language/script run and set its justification as needed. But for pango, there's just one selection for paragraph (and in simple mode, one selection for text entry widget). I told behdad about this too. IMHO pango should support justification control for each script seperatly and simultaneously. Behdad, would you help here please?
CSS3 divides scripts into groups, and then specifies how each group is justified according to each justification setting: http://www.w3.org/TR/2005/WD-css3-text-20050627/#text-justify I'm not sure you really need to control each script separately. Isn't control of each script group enough?
I meant groups, not scripts one-by-one. So what if I wand inter-ideograph and kashida simultaneously?
I would hope that the CSS3 justification table represents all the useful combinations of settings, i.e. those that have been seen in the real world. (The table is pointless if it doesn't.)
As I told, CSS3 requires you to tag each script and set it's direction and justification mode. So it's justification table is useful. But why we force pango to do that? How enlongation of an Arabic text is related to inter-word space of Latin?
Where does it say "CSS3 requires you to tag each script and set it's direction and justification mode"? I don't understand why it would have the table of justification combinations if you had to tag each script anyway. As I understand it, if the main text of a document is in Arabic, then it is normal to use kashidas for all justification. Any embedded text in other scripts would not be justified (unless there are no kashida points).
I think the CSS model is enough, at least to start with. Thanks Damon for the nice job. Behnam, can you do some testing instead? One small note, in Persian we prefer to do justfication through equal elongation of all stems, not like Arabic which prefers some characters to the other.
I assume patch.3 obsoletes patch.2, right? BTW, the opening line in patch.3 reads "Unicode 6.1" were it should be "Unicode 4.1" :)
Damon: looks like you need to update pango_layout_copy too.
Behdad: yes, it obsoletes patch.2. By "6.1" I meant "section 6.1". I've clarified that. Note that it doesn't actually support kashidas yet. It needs someone familiar with them to implement that. But I'd help with it. Morten: yes, I've copied the justification setting now. Thanks.
Damon, I think putting your code in a new file makes much sense. I'm currently rewriting break.c, and having the changes isolated from each other helps a bit down the road. Thanks.
I've put a newer patch up at http://www.dachaplin.dsl.pipex.com/pangoxt/ That fixes a few bugs and renames a variable that was named incorrectly. I just need to fix cursor navigation then I think it is ready to be applied. Tabs aren't working perfectly, but they need to be rewritten to support more features at some point anyway, so I'm not too bothered about them. I'm still unsure of the API though. CSS3 changed quite a few things in the last draft and may change again, so I'm not sure we should stick too closely to it yet.
Donno about CSS 3, I've not studied it in detail recently. For the record, the Uniscribe API for justification: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/intl/uniscrib_8v02.asp We probably need something like that on the backend interface to let modules help with justification.
A new patch is up at http://www.dachaplin.dsl.pipex.com/pangoxt/ I think it is ready to be applied now, though I'll test it a bit more in the next few days. I've changed it so whitespace isn't trimmed for ragged right text if possible. I've also optimised it so it is now generally a little faster than the current code for ragged text. (And justification is only a few percent slower.)
Another new patch is up at http://www.dachaplin.dsl.pipex.com/pangoxt/ Since the CSS3 spec is still very unstable, I've made all the CSS3 settings private for now. I think the only public API for justification we should have for now is the old pango_layout_set_justify(layout, TRUE/FALSE). Once CSS3 stabilizes or we decide on a good API we can add that as well.
Another new patch is up at http://www.dachaplin.dsl.pipex.com/pangoxt/ Hopefully this fixes all the stylistic issues Owen moaned on and on about ;) Most of the new code is in a separate pango-layout-engine.c file now, and I've tidied up the code and split up a few functions.
This should *not* be implemented in pango layout, but on a lower level, so that there is a low-level api accessible to applications that do not use PangoLayout. I cannot overemphasize how essential the low level api is to Pango's deployment in applications that have complex layout needs (such as AbiWord). The Uniscribe api for this is simple and effective, and I think worth looking at. Basically, ScriptTextOut() takes an additional pointer to an array of size of the glyphs list, that contains amount to be added to the normal character advances to achieve justification; this can be NULL, in which case no justification is done. The application is responsible for calculating the justification amounts, using the visual properties of each character. If you want to see how the this works in practice, have a look at http://www.abisource.com/viewcvs/cgi/viewcvs.cgi/abi/src/af/gr/win/gr_Win32USPGraphics.cpp?rev=HEAD&content-type=text/vnd.viewcvs-markup
I've updated the patches so they apply cleanly to cvs GTK+ and pango: http://www.dachaplin.dsl.pipex.com/pangoxt/ Tomas: I'd rather we extended PangoLayout so it provided all the layout needs for complex apps like word processors and DTP apps. Then all developers would have access to high quality text layout functionality.
Created attachment 69868 [details] The GTK+ and Pango patches I'm attaching the patches here as my webspace is about to disappear.
Created attachment 69869 [details] Test code
*** Bug 432684 has been marked as a duplicate of this bug. ***
Why is this important piece of code rotting here?
Created attachment 87025 [details] [review] Updated patch for pango 1.16.2
Created attachment 87029 [details] [review] Updated patch for pango 1.16.2 Uch, was too fast with uploading.
Created attachment 87058 [details] [review] [pango-view] Add option for testing justified text.
Created attachment 87060 [details] [review] [pango-view] Adding pseudo text for testing justification on latin scripts.
Created attachment 87061 [details] [review] [pango-layout] Add very primitive justification support.
Looks generally good. I would make a few changes: - Try avoiding offset_to_pointer from the start of paragraph on each line. The pointer you want is somewhere already... - Only expand U+0020 SPACE characters. - Humm, is_end_of_paragraph() doesn't look right to me. At least it should not be called is_end_of_paragraph. Try it with U+2028 LINE SEPARATOR. No idea if we should justify at LINE SEPARATOR. Probably should. - Probably need to specially handle trailing spaces on the line.
Lets see who's faster. (hint: I'm away for the weekend)
- Only expand U+0020 SPACE characters. Why? U+00A0 is supposed to be identical, except for breaking.
Right. Good point about U+00A0. But all other spaces that come to my mind better not be expanded. The em-based ones for sure. Right?
(In reply to comment #40) > - Try avoiding offset_to_pointer from the start of paragraph on each line. The > pointer you want is somewhere already... Have not found this pointer yet. > - Only expand U+0020 SPACE characters. Ok, U+0020 and U+00A0. > - Humm, is_end_of_paragraph() doesn't look right to me. At least it should not > be called is_end_of_paragraph. Try it with U+2028 LINE SEPARATOR. No idea if > we should justify at LINE SEPARATOR. Probably should. What is U+2028? Does Pango inject them? As replacement for "\n"? Doesn't log_attrs[offset].is_line_break express exactly this situation? Could a PangoLine even contain such a character? My assumtion is you only find them between lines. So I check for either being in the last line of a PangoLayout unit (offset >= layout->n_chars) or having an explict line break right after the current line. What would be a better name for that function? "has_explicit_line_break"? Or maybe I should invert the logic and call the function "must_justify_line"? > - Probably need to specially handle trailing spaces on the line. From the space_counts I get Pango seems to strip trailing spaces already. Makes sense, as the also have to be stripped for right alignment.
Stripping trailing spaces should not be needed anymore, once bug 434212 is fixed. Would like to add that bug as dependency, but: "You tried to change the Depends on field , but only the assignee or reporter of the bug, or a sufficiently empowered user may change that field."
Created attachment 87205 [details] [review] [pango-layout] Add very primitive justification support. Updated the patch: * Expand only spaces with variable width (U+0020 and U+00A0). * Renamed "is_end_of_paragraph" to "keep_word_spacing" and make it depend on is_mandatory_break instead of is_line_break. * I am Treating trailing spaces as separate bug 434212. * After reading pango-layout.c and the associated headers again, it doesn't seem to be possible to avoid offset_to_pointer without extending current data structures. Reducing offset_to_pointer should be done in a separate step - but not without profiling Pango first (never throw memory on a performance problem, before you really know to have a performance problem).
Created attachment 87225 [details] [review] [pango-layout] Add very primitive justification support. Duh, forgot some g_debug in the patch.
Created attachment 87353 [details] [review] [pango-layout] Add very primitive justification support. The unholy alliance of git-update-index and git-commit --amend drives me crazy... Well, maybe I just should not create patches that short before my wedding.
Ok, good idea about introducing a new logical attribute. The only other thing I want to change is to use pango_glyph_item_iter instead of looping over the runs directly, so it works for rtl too. Working on it now.
2007-05-02 Mathias Hasselmann <mathias.hasselmann@gmx.de> * pango-view/viewer-render.c (make_layout), (parse_options): Add --justify.
Humm, while working on the patch I figured that you are not correctly using log_attrs. log_attrs takes character index, buy you are feeding it glyph index...
Oh, and congrats on the wedding!
Created attachment 87379 [details] [review] Yay! 2007-05-02 Behdad Esfahbod <behdad@gnome.org> Bug 64538 – pango_layout_set_justify() doesn't work * pango/pango-layout.c (zero_line_final_space), (justify_clusters), (justify_words), (pango_layout_line_postprocess): Implement justification by expanding spaces! Based on early patch from Mathias Hasselmann.
Created attachment 87422 [details] [review] Yoohoo! Now for clusters too, if no space was found. 2007-05-02 Behdad Esfahbod <behdad@gnome.org> Bug 64538 – pango_layout_set_justify() doesn't work * pango/pango-layout.c (process_item), (justify_clusters), (justify_words): If no space found, justify by inserting space between clusters.
Closing this bug! Opened bug 435362 to track Damon's patch.
Mandatory screenshot available at http://mces.blogspot.com/2007/05/justified-text-with-pango.html