GNOME Bugzilla – Bug 325547
Pango should implement the other tab alignments
Last modified: 2018-05-22 12:14:02 UTC
I took some time to read the pango code that does the line-layouting and handles the tabs. I didn't try to implement anything yet, this is just a thought of how to implement the other alignments: The static method shape_tab (pango-layout.c), if I get it right, is modifying the given glyphs string to include a tab character, that is - an empty glyph which width is the difference between the end of the current line (where the tab was inserted) to the next possible tab position. This is good for left-aligned tabs; However, in order to handle the rest of the tab alignments, the returned width must vary. In the current implementation, it is somewhat hard to know what comes next, so instead I suggest a different approach: * shape_tab will remain the same. * The tab returned by shape_tab will be stored in a last_tab_glyph variable. * When a new glyph is added, a value is subtructed from last_tab_glyph's width: * For PANGO_TAB_LEFT, the value is 0. * For PANGO_TAB_RIGHT, the value is the width of the new glyph. * For PANGO_TAB_CENTER, the value is half the width of the new glyph. * For PANGO_TAB_NUMERIC, well, that's a bit tricky... :-) * If last_tab_glyph's width is nullified or becoming negative, it is removed. That is my proposal. I don't know if I will have time to try to implement it, hope to recieve some feedback about it (and maybe some successful attempts :-) ) Itai.
Sounds generally good. Go ahead with implementation and we will see :-)
Created attachment 56722 [details] [review] A patch that implements Right and Center tab alignments.
Thanks. The patch looks good. I will test and comment soon.
Created attachment 57464 [details] [review] test case Patch to add --tab-align option to pango-*view examples.
Oops... My patch doesn't do anything useful... Can you either finish my testing patch, or attach a test case?
Created attachment 57547 [details] A test case for the new tab alignments implementation. I didn't quite understand the patch you sent, Behdad, and I actually didn't have much time to do so also... Anyway, this is the test case I made quickly when I wrote my patch. Should be fine. It includes several text widgets with tabs of all kinds and text in English and Hebrew. Please note that this patch does not redefine the tab name for RTL mode, so the left tab in RTL mode actually aligns the text to the right, and vice-versa. I didn't change it because the default was left until now, and all RTL programs that uses tabs used the left tab (so it is kind of backwards compatability). Itai.
*** Bug 110042 has been marked as a duplicate of this bug. ***
Created attachment 58298 [details] [review] Committed patch This is the patch I committed to HEAD. It's the same patch as Itai's, with support for examples/ and updated documentations. 2006-01-28 Behdad Esfahbod <behdad@gnome.org> Implement other tab alignments. Bug #325547, Itai Bar-Haim. * docs/tmpl/tab-stops.sgml: Documented new tab alignment enum vals. * pango/pango-tabs.h, pango/pango-tabs.c: Added support for tab alignments PANGO_TAB_RIGHT and PANGO_TAB_CENTER. * examples/renderdemo.h, examples/renderdemo.c: Added support for --tab-spec.
Thank you.
Created attachment 58303 [details] [review] current patch My current patch, with some minor improvements over the previous one.
I reverted the committed patch, as apparently it needs some more work: Currently with left-aligned patches, the text will snap to the next tab stop, and there infinitely many tab stops. With the current patch (that I applied and then reverted), right-align and center-align tabstops do not work like that, ie. if the text doesn't fit, it doesn't jump to the next tab stop, but it just moves right, ignoring the tab. So, for example with all left-align tabs you get something like this: a bcd efghi a bcdefghijklmn efghi where the "efghi" in the second line jumps to the third tab stop. But with right-aligned tabs, you will get: a bcd efghi abcdefghijklmnefghi which is wrong. Now this may be easy to fix, but there's also the question of how useful such a thing would be. IMO, we need to implement two modes for the tab alignment stuff, one to jump to the next tab stop if text doesn't fit, the other to just ignore the tab stop. The former is the default behavior when no tab stops are set. The latter is more useful with set tabs, like you have a table and you want to tabulate the elements in each row. Now if one element doesn't fit in the set tab, you don't want to shift the element to the next column. You just get some mis-alignment. With implementing this, we can go and and implement auto-tab-width too, where you just set tab alignment with no width, and the minimum required width will be calculated. That would be really handy to set tables... More on the design of this thing in the next comment, to keep this short. One more thing: the current patch is not correct in get_tab_pos. It doesn't return the correct (ie, the last's) tab position's tab alignment if index >= num_tabs.
Ok, I call this mode skippable. If tabs are skippable, when the text doesn't fit, we skip to the next tab stop. Otherwise, we ignore the tab stop. With skippable off, there's a unique mapping between tab characters in the line and tab stops. Now this may not be the optimal place, but I suggest we implement this flag on the PangoTabArray. We need two methods: void pango_tab_array_set_skippable (PangoTabArray *tab_array, gboolean skippable); gboolean pango_tab_array_get_skippable (PangoTabArray *tab_array); Then we need to decide on the default value. The skippable value of the default PangoLayout tab behavior will not change, so it will be non-skippable. for new tab arrays again, we need to keep the old behavior, so default to non-skippable. Skippable tab arrays are more useful though. Owen, do you see any problem with this proposal? And a final question: what the PANGO_TAB_NUMERIC is supposed to do? Guess it's supposed to align on the decimal separator, right? How are we to approach that? The text may content arbitrary characters, like a monetary symbol, so simply skipping any (internationalized) digits and justifying on the first non-digit character doesn't work. On the other hand, searching for a period doesn't work either, as there are a zillion different decimal separators for different locales. I believe we should implement NUMERIC with the other ones in this bug. Note that NUMERIC doesn't make much sense with skippable tabs.
I understand what you are saying, but when I wrote that patch I tried to immitate the behaviour in applications I hade (i.e. Word). Perhaps we could think of other ways it can work in corner cases like this, and allow the programmer to choose. Nevertheless, if the currently implemented behaviour is one of the options, than perhaps the patch should remain commited, as it adds some functionality, while the other wanted behaviours will be implemented in the future. Itai.
Oops, seems like I have had made my last comment private!
No Itai, the patch cannot go in, 1) because it's incomplete, 2) it introduces behavior that we know will be changed in the future.
About NUMERIC alignment: This indeed aligns string representing numeric values by the decimal seperator. What I've seen in other places is that the first occurance inside the string, that actually represents a numeric value (seperated by characters that are non-numeric according to the locale) is the only value treated as numeric, and the entire string is aligned according to it. Examples (^ represents the tab position): abc123.45def67ghi ^ 123abdef45.678 ^ (well, between the '3' and the 'a') One thing we should remember here is that unlike the other alignments, the numeric alignment is intended for a specific purpose, so it is okay for us to make some assumptions about the possible uses of it. Localing, however, will cause us problems in here. Suppose we want to align two different strings with the NUMERIC alignment, when one string is in western digits, and another string in arabic digits. Will both strings be aligned correctly? What about different seperators? What about string that mixes western and arabic digits? Should we try to find a correct numeric string inside a bigger string in a case of digits mixing, and match seperators while at it? Just some points to think about. Itai.
I don't quite understand the default value for skippable mode. You said it should be false (non-skippable). But in non-skippable mode, when the text doesn't fit, what we get is some mis-alignment, while current behaviour is jumping to the next tab. So shouldn't the default mode be "skippable"? Another thing I don't understand is how it will work with alignments other than "left". Suppose the following case: L R C (tabs) a bcd efgh if the third word (efgh) is longer, what will happen? L R C (tabs) a bcdefghijklm this? a bcd efghijklm or this? or perhaps something else?
Right, for some reason my mental idea of what skippable means was skewed when I wrote that comment. As for your example, the second line is what should happen. It's not that useful when you have different tab alignments like the R and C in this case, but that's the most consistent with current behavior.
As I see it, neither one of the examples I wrote immitate the current behaviour (guess I wasn't paying much attention while writing this...) In the current behaviuor, this what's will happen: L L L (tabs) a bcd efghi (original) now the SECOND word gets longer: L L L (tabs) a bcdxxxxxxx efghi (skippable) a bcdxxxxxxxefghi (nonskippable, that isn't available currently) And if we'll try to do the same with other alignments: L R C (tabs) a bcd efghi (original) a bcdxxxxxxx efghi (skippable) a bcdxxxxxxxefghi (nonskippable) however, what is the case if the long text starts on a non-left tab? R R C (tabs) a bcd efghi (original) abcdxxx efghi (nonskippable) a bcdxxx efghi (skippable - option 1 - the unfit text moves on) abcdxxx efghi (skippable - option 2 - just like nonskippable) and there's option 3 (move the tab iteself as much as possible. Then start moving the next tab to make more room and so on): R R (tabs) abcdxxx efghi
Option 1 is what I mean. How did you come up with option 2? Option 3 is very very hard to implement.
I came up with option 2 because on left-tabs, text that does not fit causes the next tabulated segment to jump to the first possible tab that comes next. The unfit text segment does not change it position, it only effects the segments that comes afterwards... (P.S. I noticed a small mistake in the example of the left-tabs only. I positioned the last word center-aligned in a Left-Tab, instead of left-aligned...)
Relevant read: elastic tabstops: http://nickgravgaard.com/elastictabstops/
-- GitLab Migration Automatic Message -- This bug has been migrated to GNOME's GitLab instance and has been closed from further activity. You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.gnome.org/GNOME/pango/issues/34.