Automatic paragraph direction and BiDirection layouts in Gtk+



Background:  This was supposed to be posted on bugzilla for this
bug: http://bugzilla.gnome.org/show_bug.cgi?id=70451
But since it turned out to be too long and a bit wider than that
bug, I decided to post on gtk-i18n-list instead.  In this mail I
try to discuss my ideal model for handling bidirectional layouts
in Gtk+.  Unfortunately I have absolutely no idea how Gtk+
currently implements this so I may be totally off.



Hi Owen, Dov, and others,


I wish to thank you for the nice job on this bug.  I have
successfully compiled and tested pango with auto paragraph
direction detection and it looks fascinating.  There's a small
but annoying problem:  I'm testing with gedit.  I enter an RTL
line, it's right-aligned.  From the algorithm we now that the
next line that I'm going to just enter neutral chars, is going to
be right-aligned too, but it does not happen until I hit enter
and just then the line jumps to right.  Let me make a raw guess,
I saw you added a NEUTRAL paragraph direction to minifribidi, but
AFAIU the paragraph direction cannot be really neutral.  Because
the empty paragraph needs a direction, and it should be either
ltr or rtl...

Sorry that I was silent before.  The priority for this bug was
way low in my stack because I don't have a good knowledge of
pango and gtk+.  As it was looking inactive, I left commenting to
some time later that I can learn more.  Now that the patch is
applied and works, I just go on and write about my requirements
and ideal model.  Hopefully you can check if the current design
satisfies them all or not.  Thanks in advance.

Ok, here comes my ideal world of BiDi layout handling in Gtk+ and
Pango: The model very extends on the HTML/CSS model.  The best
property of this model I can say is that it's general to death
and can handle any complex BiDi layout.

Every Gtk+ widget has a "direction" attribute.  There is also a
"resolved direction" which is either "ltr" or "rtl" and is calculated
based on the "direction" attribute and the resolved direction of
the parent widget.  For the root widget, the resolved direction
of the parent widget is defined to be "rtl" for right-to-left
locales, and "ltr" otherwise.  The values for "direction" attribute
and their meanings are:

  * inherit:  Is the default. The widget inherits the resolved
    direction of the parent widget.

  * opposite:  The resolved direction for the widget is the
    opposite of the resolved direction of the parent widget.
    The CSS model lacks this value.

  * ltr:  The resolved direction would be ltr, no matter what the
    resolved direction of the parent widget is.

  * rtl:  The resolved direction would be rtl, no matter what the
    resolved direction of the parent widget is.


Note that, "direction" to this point is a property of any widget
and does not deal with BiDi algorithm necessarily.  Resolved
direction defines the direction of packing in horizontal boxes,
toolbars, menubars, etc.  One day pixmaps may add an attribute
to enable "mirroring" the image if resolved "direction" is
right-to-left.



Every Gtk+ widget also has an "align" attribute.  Moreover, the
resolved alignment is one of "left", "right", "center", or
"justify" and is calculated based on the resolved alignment of the
parent widget, resolved direction of this widget, and the "align"
attribute.  The values for "align" attribute and their meanings are:

  * auto:  This is the default.  The resolved alignment would be
    "left" ("right") if the resolved direction of the widget
    is "ltr" ("rtl").  The CSS model lacks this value.

  * auto-opposite:  The resolved alignment would be "right" ("left")
    if the resolved direction of the widget is "ltr" ("rtl").
    The CSS model lacks this value.

  * inherit:  The widget inherits the resolved alignment of the
    parent widget.

  * opposite:  The resolved alignment for the widget is the
    opposite of the resolved alignment of the parent widget if
    it's "left" or "right", or the same as resolved alignment of
    the parent widget otherwise.  The CSS model lacks this value.

  * left:  The resolved alignment would be "left".

  * right:  The resolved alignment would be "right".

  * center:  The resolved alignment would be "center".

  * justify:  The resolved alignment would be "justify".


The resolved alignment attribute is mostly useful in text
entry/label widgets, but other widget may adopt it too.  For
example a toolbar can use "align" attribute to determine where to
put the icons.

Note that a text widget may compute resolved alignment for each
individual paragraph too, independent of the resolved alignment
of the widget.



And finally, there is another attribute "paragraph_direction",
which is specific to those widgets rendering text.  The values
with the meanings are:

  * auto:  The heuristic algorithm should be used to determine
    paragraph directions.  If there is no strong character in the
    whole buffer, then the resolved direction of the widget
    should be used as paragraph direction.

  * weak:  For each paragraph, the paragraph direction should be
    computed as specified in BiDi spec.  If there is no strong
    character in the paragraph, the resolved direction of the
    widget should be used instead.

  * strong:  For each paragraph, the resolved direction of the
    widget should be used as paragraph direction.

After determining the paragraph directions, the alignment of each
paragraph can be computed quite like the resolved alignment of
the widget, but using paragraph direction instead of resolved
direction.  So alignment is computed per paragraph.



Justification:

The rationale behind "paragraph_direction" should be obvious.
For "direction", the values "inherit", "ltr", and "rtl" are
necessary with no doubt.  The value "opposite" may look useless
in real scenarios, but it may be added for the sake of completeness.

The eight values for "align" are the ones that need
justification.  I believe it's not the best place to put
"justify", as it does not make much sense on non-text widgets,
but I have adopted the CSS model here, so it comes.  The values
"left", "right", "center", and "justify" are essential.  For the
other four, I would give examples of usefulness.


"auto" is the default.  It means that a Persian/Arabic/Hebrew
text would by default align to right, and English text would
align to left.

"auto-opposite" is the opposite of "auto".  This is not used so
common, but it should better be there.  This can be used to
achieve the following effect portably:

               this is a sample
           text that is aligned
             to the opposite of
         the natural direction.
            the same effect can
	      be achieved using
            align to right, but
             it would break for
	   right-to-left texts.
	      this way it would
         work just as expected.



"inherit" as the name suggests, inherits the alignment of the
parent widget.  This simply means it ignores the resolved
direction of the widget.  So no matter what kind of text is
inside, the resolved alignment is the same.

"opposite" is the opposite of the resolved alignment of the
parent widget.  This is the single most wanted feature in CSS
model for BiDi web applications.  Consider the following form:

               +----------------------------------+
	       |                                  |
               |            user: behdad          |
               |        password: ********        |
	       |                                  |
	       |             enter >              |
               +----------------------------------+

This form, in a right-to-left context should become:

               +----------------------------------+
	       |                                  |
               |           DADHEB :RESU           |
               |         ******** :DROWSSAP       |
	       |                                  |
	       |               < RETNE            |
               +----------------------------------+

To achieve this, the "user:" and "password:" cells are aligned
"opposite", while "behdad" and "********" (user and password text
boxes) are aligned "inherit".  So no matter you type a
Persian or English user name, the username is always aligned
toward the center, and does not jump to right/left.


Note how in this form the ">" should become "<".  This is done
automatically by the BiDi algorithm, but if you are using an
image for the arrow, you need to either select the arrow
direction based on the resolved direction of the widget, or use
my proposed pixmap mirroring feature.




Ok, that's all my rant for now.
Hope it helps at least a bit :)
behdad



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]