Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/pango/ChangeLog,v
retrieving revision 1.850
diff -u -p -r1.850 ChangeLog
--- ChangeLog	27 Feb 2004 16:27:22 -0000	1.850
+++ ChangeLog	27 Feb 2004 19:09:37 -0000
@@ -1,3 +1,18 @@
+Fri Feb 27 11:23:21 2004  Owen Taylor  <otaylor@redhat.com>
+
+	Patch from Dov Grobgeld to add auto-direction to PangoLayout
+	(more of #70451)
+
+	* examples/pangofttopgm.c: Add --no-auto-dir argument.
+
+	* pango-layout.[ch]: Add pango_layout_set_auto_dir()
+	defaulting to TRUE; resolve paragraph direction within
+	a layout by propagating base direction downwards
+	from paragraph to paragraph.
+
+	* pango-context.[ch]: Add pango_itemize_with_base_dir()
+	which overrides the base direction from the PangoContext.
+
 Fri Feb 27 11:24:50 2004  Owen Taylor  <otaylor@redhat.com>
 
 	* pango/mini-fribidi/fribidi.c (pango_log2vis_get_embedding_levels):
Index: examples/pangoft2topgm.c
===================================================================
RCS file: /cvs/gnome/pango/examples/pangoft2topgm.c,v
retrieving revision 1.10
diff -u -p -r1.10 pangoft2topgm.c
--- examples/pangoft2topgm.c	25 Nov 2003 21:28:12 -0000	1.10
+++ examples/pangoft2topgm.c	27 Feb 2004 19:09:37 -0000
@@ -54,6 +54,7 @@ static char *opt_output = NULL;
 static int opt_margin = 10;
 static int opt_markup = FALSE;
 static gboolean opt_rtl = FALSE;
+static gboolean opt_auto_dir = TRUE;
 static char *opt_text = NULL;
 static  gboolean opt_waterfall = FALSE;
 static  int opt_width = -1;
@@ -106,6 +107,8 @@ make_layout(PangoContext *context,
   else
     pango_layout_set_text (layout, text, -1);
 
+  pango_layout_set_auto_dir(layout, opt_auto_dir);
+  
   font_description = get_font_description ();
   if (size > 0)
     pango_font_description_set_size (font_description, size * PANGO_SCALE);
@@ -240,6 +243,8 @@ int main(int argc, char *argv[])
   gboolean do_convert = FALSE;
   
   static const ArgDesc args[] = {
+    { "no-auto-dir","Don't set layout direction according to contents",
+      ARG_NOBOOL,   &opt_auto_dir },
     { "display",    "Show output using ImageMagick",
       ARG_BOOL,     &opt_display },
     { "dpi",        "Set the dpi'",
Index: pango/pango-context.c
===================================================================
RCS file: /cvs/gnome/pango/pango/pango-context.c,v
retrieving revision 1.63
diff -u -p -r1.63 pango-context.c
--- pango/pango-context.c	27 Feb 2004 14:48:53 -0000	1.63
+++ pango/pango-context.c	27 Feb 2004 19:09:37 -0000
@@ -573,12 +573,12 @@ static void
 itemize_state_init (ItemizeState      *state,
 		    PangoContext      *context, 
 		    const char        *text,
+		    PangoDirection     base_dir,
 		    int                start_index,
 		    int                length,
 		    PangoAttrList     *attrs,
 		    PangoAttrIterator *cached_iter)
 {
-  PangoDirection base_dir;
   gunichar *text_ucs4;
   long n_chars;
 
@@ -594,8 +594,6 @@ itemize_state_init (ItemizeState      *s
   /* First, apply the bidirectional algorithm to break
    * the text into directional runs.
    */
-  base_dir = context->base_dir;
-
   text_ucs4 = g_utf8_to_ucs4_fast (text + start_index, length, &n_chars);
   state->embedding_levels = g_new (guint8, n_chars);
   pango_log2vis_get_embedding_levels (text_ucs4, n_chars, &base_dir,
@@ -1020,10 +1018,61 @@ itemize_state_finish (ItemizeState *stat
 }
 
 /**
+ * pango_itemize_with_base_dir:
+ * @context:   a structure holding information that affects
+               the itemization process.
+ * @text:      the text to itemize.
+ * @start_index: first byte in @text to process
+ * @length:    the number of bytes (not characters) to process
+ *             after @start_index.
+ *             This must be >= 0.
+ * @base_dir:  base direction to use for bidirectional processing
+ * @attrs:     the set of attributes that apply to @text.
+ * @cached_iter:      Cached attribute iterator, or NULL
+ *
+ * Like pango_itemize(), but the base direction to use when
+ * computing bidirectional levels (see pango_context_set_base_dir ()),
+ * is specified explicitely rather than gotten from the #PangoContext.
+ *
+ * Return value: a GList of PangoItem structures.
+ */
+GList *
+pango_itemize_with_base_dir (PangoContext      *context, 
+			     PangoDirection     base_dir,
+			     const char        *text,
+			     int                start_index,
+			     int                length,
+			     PangoAttrList     *attrs,
+			     PangoAttrIterator *cached_iter)
+{
+  ItemizeState state;
+
+  g_return_val_if_fail (context != NULL, NULL);
+  g_return_val_if_fail (start_index >= 0, NULL);
+  g_return_val_if_fail (length >= 0, NULL);
+  g_return_val_if_fail (length == 0 || text != NULL, NULL);
+
+  if (length == 0)
+    return NULL;
+
+  itemize_state_init (&state, context, text, base_dir, start_index, length,
+		      attrs, cached_iter);
+
+  do 
+    itemize_state_process_run (&state);
+  while (itemize_state_next (&state));
+
+  itemize_state_finish (&state);
+  
+  return g_list_reverse (state.result);
+}
+
+/**
  * pango_itemize:
  * @context:   a structure holding information that affects
                the itemization process.
  * @text:      the text to itemize.
+ * @base_dir:  base direction to use for BiDi algorithm.
  * @start_index: first byte in @text to process
  * @length:    the number of bytes (not characters) to process
  *             after @start_index.
@@ -1052,26 +1101,13 @@ pango_itemize (PangoContext      *contex
 	       PangoAttrList     *attrs,
                PangoAttrIterator *cached_iter)
 {
-  ItemizeState state;
-
   g_return_val_if_fail (context != NULL, NULL);
   g_return_val_if_fail (start_index >= 0, NULL);
   g_return_val_if_fail (length >= 0, NULL);
   g_return_val_if_fail (length == 0 || text != NULL, NULL);
 
-  if (length == 0)
-    return NULL;
-
-  itemize_state_init (&state, context, text, start_index, length,
-		      attrs, cached_iter);
-
-  do 
-    itemize_state_process_run (&state);
-  while (itemize_state_next (&state));
-
-  itemize_state_finish (&state);
-  
-  return g_list_reverse (state.result);
+  return pango_itemize_with_base_dir (context, context->base_dir,
+				      text, start_index, length, attrs, cached_iter);
 }
 
 /**
Index: pango/pango-context.h
===================================================================
RCS file: /cvs/gnome/pango/pango/pango-context.h,v
retrieving revision 1.16
diff -u -p -r1.16 pango-context.h
--- pango/pango-context.h	18 Nov 2001 23:23:14 -0000	1.16
+++ pango/pango-context.h	27 Feb 2004 19:09:37 -0000
@@ -82,13 +82,19 @@ PangoDirection            pango_context_
  * consistent shaping/language engine and bidrectional level.
  * Returns a GList of PangoItem's
  */
-GList *pango_itemize (PangoContext      *context,
-                      const char        *text,
-                      int                start_index,
-                      int                length,
-                      PangoAttrList     *attrs,
-                      PangoAttrIterator *cached_iter);
-
+GList *pango_itemize                (PangoContext      *context,
+				     const char        *text,
+				     int                start_index,
+				     int                length,
+				     PangoAttrList     *attrs,
+				     PangoAttrIterator *cached_iter);
+GList *pango_itemize_with_base_dir  (PangoContext      *context,
+				     PangoDirection     base_dir,
+				     const char        *text,
+				     int                start_index,
+				     int                length,
+				     PangoAttrList     *attrs,
+				     PangoAttrIterator *cached_iter);
 
 G_END_DECLS
 
Index: pango/pango-layout.c
===================================================================
RCS file: /cvs/gnome/pango/pango/pango-layout.c,v
retrieving revision 1.112
diff -u -p -r1.112 pango-layout.c
--- pango/pango-layout.c	21 Feb 2004 16:33:50 -0000	1.112
+++ pango/pango-layout.c	27 Feb 2004 19:09:37 -0000
@@ -117,6 +117,7 @@ struct _PangoLayout
   guint alignment : 2;
 
   guint single_paragraph : 1;
+  guint auto_dir : 1;
   
   gint n_chars;		        /* Total number of characters in layout */
   PangoLogAttr *log_attrs;	/* Logical attributes for layout's text */
@@ -203,6 +204,7 @@ pango_layout_init (PangoLayout *layout)
 
   layout->alignment = PANGO_ALIGN_LEFT;
   layout->justify = FALSE;
+  layout->auto_dir = TRUE;
 
   layout->log_attrs = NULL;
   layout->lines = NULL;
@@ -591,6 +593,46 @@ pango_layout_get_justify (PangoLayout *l
 }
 
 /**
+ * pango_layout_set_auto_dir:
+ * @layout: a #PangoLayout
+ * @auto_dir: whether to do auto bidi dir according to the contents.
+ * 
+ * Sets whether or not to calculate the bidi direction according to
+ * the contents of the layout.
+ **/
+void
+pango_layout_set_auto_dir (PangoLayout *layout,
+			   gboolean     auto_dir)
+{
+  g_return_if_fail (PANGO_IS_LAYOUT (layout));
+
+  auto_dir = auto_dir != FALSE;
+
+  if (auto_dir != layout->auto_dir)
+    {
+      layout->auto_dir = auto_dir;
+      pango_layout_clear_lines (layout);
+    }
+}
+
+/**
+ * pango_layout_get_auto_dir:
+ * @layout: a #PangoLayout
+ * 
+ * Gets whether or not the bidi direction of the layout are calculated
+ * according to the layout contents.
+ * 
+ * Return value: the auto_dir
+ **/
+gboolean
+pango_layout_get_auto_dir (PangoLayout *layout)
+{
+  g_return_val_if_fail (PANGO_IS_LAYOUT (layout), FALSE);
+  
+  return layout->auto_dir;
+}
+
+/**
  * pango_layout_set_alignment:
  * @layout: a #PangoLayout
  * @alignment: the new alignment
@@ -1222,7 +1264,6 @@ pango_layout_move_cursor_visually (Pango
 				   int         *new_index,
 				   int         *new_trailing)
 {
-  PangoDirection base_dir;
   PangoLayoutLine *line = NULL;
   PangoLayoutLine *prev_line;
   PangoLayoutLine *next_line;
@@ -1243,12 +1284,10 @@ pango_layout_move_cursor_visually (Pango
 
   pango_layout_check_lines (layout);
 
-  base_dir = pango_context_get_base_dir (layout->context);
-
   /* Find the line the old cursor is on */
   line = pango_layout_index_to_line (layout, old_index,
 				     NULL, &prev_line, &next_line);
-  
+
   start_offset = g_utf8_pointer_to_offset (layout->text, layout->text + line->start_index);
 
   while (old_trailing--)
@@ -1267,14 +1306,14 @@ pango_layout_move_cursor_visually (Pango
   /* Handling movement between lines */
   if (vis_pos == 0 && direction < 0)
     {
-      if (base_dir == PANGO_DIRECTION_LTR)
+      if (line->resolved_dir == PANGO_DIRECTION_LTR)
 	off_start = TRUE;
       else
 	off_end = TRUE;
     }
   else if (vis_pos == n_vis && direction > 0)
     {
-      if (base_dir == PANGO_DIRECTION_LTR)
+      if (line->resolved_dir == PANGO_DIRECTION_LTR)
 	off_end = TRUE;
       else
 	off_start = TRUE;
@@ -1550,7 +1589,6 @@ pango_layout_line_get_vis2log_map (Pango
 				   gboolean         strong)
 {
   PangoLayout *layout = line->layout;
-  PangoDirection base_dir = pango_context_get_base_dir (layout->context);
   PangoDirection prev_dir;
   PangoDirection cursor_dir;
   GSList *tmp_list;
@@ -1565,16 +1603,16 @@ pango_layout_line_get_vis2log_map (Pango
   result = g_new (int, n_chars + 1);
 
   if (strong)
-    cursor_dir = base_dir;
+    cursor_dir = line->resolved_dir;
   else
-    cursor_dir = (base_dir == PANGO_DIRECTION_LTR) ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR;
+    cursor_dir = (line->resolved_dir == PANGO_DIRECTION_LTR) ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR;
 
   /* Handle the first visual position
    */
-  if (base_dir == cursor_dir)
-    result[0] = base_dir == PANGO_DIRECTION_LTR ? 0 : end - start;
+  if (line->resolved_dir == cursor_dir)
+    result[0] = line->resolved_dir == PANGO_DIRECTION_LTR ? 0 : end - start;
 
-  prev_dir = base_dir;
+  prev_dir = line->resolved_dir;
   pos = 0;
   tmp_list = line->runs;
   while (tmp_list)
@@ -1630,8 +1668,8 @@ pango_layout_line_get_vis2log_map (Pango
 
   /* And the last visual position
    */
-  if ((cursor_dir == base_dir) || (prev_dir == base_dir))
-    result[pos] = base_dir == PANGO_DIRECTION_LTR ? end - start : 0;
+  if ((cursor_dir == line->resolved_dir) || (prev_dir == line->resolved_dir))
+    result[pos] = line->resolved_dir == PANGO_DIRECTION_LTR ? end - start : 0;
       
   return result;
 }
@@ -1704,7 +1742,6 @@ pango_layout_get_cursor_pos (PangoLayout
 			     PangoRectangle *strong_pos,
 			     PangoRectangle *weak_pos)
 {
-  PangoDirection base_dir;
   PangoDirection dir1, dir2;
   PangoRectangle line_rect;
   PangoLayoutLine *layout_line = NULL; /* Quiet GCC */
@@ -1714,8 +1751,6 @@ pango_layout_get_cursor_pos (PangoLayout
   g_return_if_fail (layout != NULL);
   g_return_if_fail (index >= 0 && index <= layout->length);
   
-  base_dir = pango_context_get_base_dir (layout->context);
-
   layout_line = pango_layout_index_to_line_and_extents (layout, index,
 							&line_rect);
 
@@ -1724,8 +1759,8 @@ pango_layout_get_cursor_pos (PangoLayout
   /* Examine the trailing edge of the character before the cursor */
   if (index == layout_line->start_index)
     {
-      dir1 = base_dir;
-      if (base_dir == PANGO_DIRECTION_LTR)
+      dir1 = layout_line->resolved_dir;
+      if (layout_line->resolved_dir == PANGO_DIRECTION_LTR)
         x1_trailing = 0;
       else
         x1_trailing = line_rect.width;
@@ -1740,8 +1775,8 @@ pango_layout_get_cursor_pos (PangoLayout
   /* Examine the leading edge of the character after the cursor */
   if (index >= layout_line->start_index + layout_line->length)
     {
-      dir2 = base_dir;
-      if (base_dir == PANGO_DIRECTION_LTR)
+      dir2 = layout_line->resolved_dir;
+      if (layout_line->resolved_dir == PANGO_DIRECTION_LTR)
         x2 = line_rect.width;
       else
         x2 = 0;
@@ -1756,7 +1791,7 @@ pango_layout_get_cursor_pos (PangoLayout
     {
       strong_pos->x = line_rect.x;
       
-      if (dir1 == base_dir)
+      if (dir1 == layout_line->resolved_dir)
 	strong_pos->x += x1_trailing;
       else
 	strong_pos->x += x2;
@@ -1770,7 +1805,7 @@ pango_layout_get_cursor_pos (PangoLayout
     {
       weak_pos->x = line_rect.x;
       
-      if (dir1 == base_dir)
+      if (dir1 == layout_line->resolved_dir)
 	weak_pos->x += x2;
       else
 	weak_pos->x += x1_trailing;
@@ -1788,10 +1823,20 @@ get_x_offset (PangoLayout     *layout,
               int              line_width,
               int             *x_offset)
 {
+  PangoAlignment alignment = layout->alignment;
+
+  if (line->layout->auto_dir && line->resolved_dir == PANGO_DIRECTION_RTL)
+    {
+      if (alignment == PANGO_ALIGN_LEFT)
+	alignment = PANGO_ALIGN_RIGHT;
+      else if (alignment == PANGO_ALIGN_RIGHT)
+	alignment = PANGO_ALIGN_LEFT;
+    }
+	
   /* Alignment */
-  if (layout->alignment == PANGO_ALIGN_RIGHT)
+  if (alignment == PANGO_ALIGN_RIGHT)
     *x_offset = layout_width - line_width;
-  else if (layout->alignment == PANGO_ALIGN_CENTER)
+  else if (alignment == PANGO_ALIGN_CENTER)
     *x_offset = (layout_width - line_width) / 2;
   else
     *x_offset = 0;
@@ -1805,14 +1850,14 @@ get_x_offset (PangoLayout     *layout,
    * knowing whether left/right is the "normal" thing for this text
    */
    
-  if (layout->alignment == PANGO_ALIGN_CENTER)
+  if (alignment == PANGO_ALIGN_CENTER)
     return;
   
   if (line->is_paragraph_start)
     {
       if (layout->indent > 0)
         {
-          if (layout->alignment == PANGO_ALIGN_LEFT)
+          if (alignment == PANGO_ALIGN_LEFT)
             *x_offset += layout->indent;
           else
             *x_offset -= layout->indent;
@@ -1822,7 +1867,7 @@ get_x_offset (PangoLayout     *layout,
     {
       if (layout->indent < 0)
         {
-          if (layout->alignment == PANGO_ALIGN_LEFT)
+          if (alignment == PANGO_ALIGN_LEFT)
             *x_offset -= layout->indent;
           else
             *x_offset += layout->indent;
@@ -1880,7 +1925,8 @@ pango_layout_get_extents_internal (Pango
   GSList *line_list;
   int y_offset = 0;
   int width;
-  
+  gboolean one_line_is_not_ltr = FALSE;
+
   g_return_if_fail (layout != NULL);
 
   pango_layout_check_lines (layout);
@@ -1890,7 +1936,30 @@ pango_layout_get_extents_internal (Pango
    * x_offsets if we are computing the ink_rect or individual line extents.
    */
   width = layout->width;
-  if (width == -1 && layout->alignment != PANGO_ALIGN_LEFT && (ink_rect || line_extents))
+
+  /* Calculate if one of the lines is not LTR. Either because the alignment
+   * is not LTR or one of the lines has been resolved dir RTL.
+  */
+  one_line_is_not_ltr = FALSE;
+  if (layout->alignment != PANGO_ALIGN_LEFT)
+    one_line_is_not_ltr = TRUE;
+  else
+    {
+      line_list = layout->lines;
+      while (line_list)
+	{
+	  PangoLayoutLine *line = line_list->data;
+	  
+	  if (line->resolved_dir == PANGO_DIRECTION_RTL)
+	    {
+	      one_line_is_not_ltr = TRUE;
+	      break;
+	    }
+	  line_list = line_list->next;
+	}
+    }
+  
+  if (width == -1 && one_line_is_not_ltr && (ink_rect || line_extents))
     {
       PangoRectangle overall_logical;
       
@@ -2482,6 +2551,7 @@ typedef struct _ParaBreakState ParaBreak
 struct _ParaBreakState
 {
   GList *items;			/* This paragraph turned into items */
+  PangoDirection base_dir;	/* Current resolved base direction */
   gboolean first_line;		/* TRUE if this is the first line of the paragraph */
   int line_start_index;		/* Start index of line in layout->text */
 
@@ -2731,6 +2801,7 @@ process_line (PangoLayout    *layout,
   line = pango_layout_line_new (layout);
   line->start_index = state->line_start_index;
   line->is_paragraph_start = state->first_line;
+  line->resolved_dir = state->base_dir;
 
   if (state->first_line)
     state->remaining_width = (layout->indent >= 0) ? layout->width - layout->indent : layout->width;
@@ -2945,6 +3016,7 @@ pango_layout_check_lines (PangoLayout *l
   PangoAttrList *attrs;
   PangoAttrList *no_shape_attrs;
   PangoAttrIterator *iter;
+  PangoDirection prev_base_dir = PANGO_DIRECTION_NEUTRAL, base_dir = PANGO_DIRECTION_NEUTRAL;
   
   if (layout->lines)
     return;
@@ -2965,6 +3037,16 @@ pango_layout_check_lines (PangoLayout *l
   
   start_offset = 0;
   start = layout->text;
+  
+  /* Find the first strong direction of the text */
+  if (layout->auto_dir)
+    {
+      prev_base_dir = pango_find_base_dir (layout->text, layout->length);
+      if (prev_base_dir == PANGO_DIRECTION_NEUTRAL)
+	prev_base_dir = pango_context_get_base_dir (layout->context);
+    }
+  else
+    base_dir = pango_context_get_base_dir (layout->context);
 
   do
     {
@@ -2987,7 +3069,18 @@ pango_layout_check_lines (PangoLayout *l
         }
 
       g_assert (next_para_index >= delimiter_index);
-      
+
+      if (layout->auto_dir)
+	{
+	  base_dir = pango_find_base_dir (start, delimiter_index);
+	  
+	  /* Propagate the base direction for neutral paragraphs */
+	  if (base_dir == PANGO_DIRECTION_NEUTRAL)
+	    base_dir = prev_base_dir;
+	  else
+	    prev_base_dir = base_dir;
+	}
+
       end = start + delimiter_index;
       
       delim_len = next_para_index - delimiter_index;
@@ -3000,12 +3093,13 @@ pango_layout_check_lines (PangoLayout *l
       g_assert (delim_len < 4);	/* PS is 3 bytes */
       g_assert (delim_len >= 0);
 
-      state.items = pango_itemize (layout->context,
-				   layout->text,
-				   start - layout->text,
-				   end - start,
-				   attrs,
-				   iter);
+      state.items = pango_itemize_with_base_dir (layout->context,
+						 base_dir,
+						 layout->text,
+						 start - layout->text,
+						 end - start,
+						 attrs,
+						 iter);
 
       get_items_log_attrs (start, state.items,
                            layout->log_attrs + start_offset,
@@ -3014,6 +3108,7 @@ pango_layout_check_lines (PangoLayout *l
       if (state.items)
 	{
 	  state.first_line = TRUE;
+	  state.base_dir = base_dir;
 	  state.start_offset = start_offset;
           state.line_start_index = start - layout->text;
 
@@ -3029,7 +3124,8 @@ pango_layout_check_lines (PangoLayout *l
 
           empty_line = pango_layout_line_new (layout);
           empty_line->start_index = start - layout->text;
-	  empty_line->is_paragraph_start = TRUE;
+	  empty_line->is_paragraph_start = TRUE;	  
+	  empty_line->resolved_dir = base_dir;
 
           layout->lines = g_slist_prepend (layout->lines,
                                            empty_line);
@@ -3133,7 +3229,6 @@ pango_layout_line_x_to_index (PangoLayou
   gint last_offset;
   gint end_index;       /* end iterator for line */
   gint end_offset;      /* end iterator for line */
-  PangoDirection base_dir;
   PangoLayout *layout;
   gint last_trailing;
   gboolean suppress_last_trailing;
@@ -3146,8 +3241,6 @@ pango_layout_line_x_to_index (PangoLayou
 
   layout = line->layout;
 
-  base_dir = pango_context_get_base_dir (layout->context);
-
   /* Find the last index in the line
    */
   first_index = line->start_index;
@@ -3218,10 +3311,10 @@ pango_layout_line_x_to_index (PangoLayou
     {
       /* pick the leftmost char */
       if (index)
-	*index = (base_dir == PANGO_DIRECTION_LTR) ? first_index : last_index;
+	*index = (line->resolved_dir == PANGO_DIRECTION_LTR) ? first_index : last_index;
       /* and its leftmost edge */
       if (trailing)
-	*trailing = (base_dir == PANGO_DIRECTION_LTR || suppress_last_trailing) ? 0 : last_trailing;
+	*trailing = (line->resolved_dir == PANGO_DIRECTION_LTR || suppress_last_trailing) ? 0 : last_trailing;
       
       return FALSE;
     }
@@ -3308,11 +3401,11 @@ pango_layout_line_x_to_index (PangoLayou
 
   /* pick the rightmost char */
   if (index)
-    *index = (base_dir == PANGO_DIRECTION_LTR) ? last_index : first_index;
+    *index = (line->resolved_dir == PANGO_DIRECTION_LTR) ? last_index : first_index;
 
   /* and its rightmost edge */
   if (trailing)
-    *trailing = (base_dir == PANGO_DIRECTION_LTR && !suppress_last_trailing) ? last_trailing : 0;
+    *trailing = (line->resolved_dir == PANGO_DIRECTION_LTR && !suppress_last_trailing) ? last_trailing : 0;
 
   return FALSE;
 }
@@ -3351,7 +3444,6 @@ pango_layout_line_get_x_ranges (PangoLay
 				int             **ranges,
 				int              *n_ranges)
 {
-  PangoDirection base_dir;
   PangoRectangle logical_rect;
   gint line_start_index = 0;
   GSList *tmp_list;
@@ -3359,15 +3451,22 @@ pango_layout_line_get_x_ranges (PangoLay
   int accumulated_width = 0;
   int x_offset;
   int width;
+  PangoAlignment alignment = line->layout->alignment;
+
+  if (line->layout->auto_dir && line->resolved_dir == PANGO_DIRECTION_RTL)
+    {
+      if (alignment == PANGO_ALIGN_LEFT)
+	alignment = PANGO_ALIGN_RIGHT;
+      else if (alignment == PANGO_ALIGN_RIGHT)
+	alignment = PANGO_ALIGN_LEFT;
+    }
   
   g_return_if_fail (line != NULL);
   g_return_if_fail (line->layout != NULL);
   g_return_if_fail (start_index <= end_index);
 
-  base_dir = pango_context_get_base_dir (line->layout->context);
-
   width = line->layout->width;
-  if (width == -1 && line->layout->alignment != PANGO_ALIGN_LEFT)
+  if (width == -1 && alignment != PANGO_ALIGN_LEFT)
     {
       pango_layout_get_extents (line->layout, NULL, &logical_rect);
       width = logical_rect.width;
@@ -3389,8 +3488,8 @@ pango_layout_line_get_x_ranges (PangoLay
     *ranges = g_new (int, 2 * (2 + g_slist_length (line->runs)));
     
   if (x_offset > 0 &&
-      ((base_dir == PANGO_DIRECTION_LTR && start_index < line_start_index) ||
-       (base_dir == PANGO_DIRECTION_RTL && end_index > line_start_index + line->length)))
+      ((line->resolved_dir == PANGO_DIRECTION_LTR && start_index < line_start_index) ||
+       (line->resolved_dir == PANGO_DIRECTION_RTL && end_index > line_start_index + line->length)))
     {
       if (ranges)
 	{
@@ -3454,8 +3553,8 @@ pango_layout_line_get_x_ranges (PangoLay
     }
 
   if (x_offset + logical_rect.width < line->layout->width &&
-      ((base_dir == PANGO_DIRECTION_LTR && end_index > line_start_index + line->length) ||
-       (base_dir == PANGO_DIRECTION_RTL && start_index < line_start_index)))
+      ((line->resolved_dir == PANGO_DIRECTION_LTR && end_index > line_start_index + line->length) ||
+       (line->resolved_dir == PANGO_DIRECTION_RTL && start_index < line_start_index)))
     {
       if (ranges)
 	{
@@ -3729,8 +3828,9 @@ pango_layout_line_new (PangoLayout *layo
   private->line.runs = 0;
   private->line.length = 0;
 
-  /* Note that we leave start_index and is_paragraph_start uninitialized */
-  
+  /* Note that we leave start_index, resolved_dir, and is_paragraph_start
+   *  uninitialized */
+
   return (PangoLayoutLine *) private;
 }
 
Index: pango/pango-layout.h
===================================================================
RCS file: /cvs/gnome/pango/pango/pango-layout.h,v
retrieving revision 1.31
diff -u -p -r1.31 pango-layout.h
--- pango/pango-layout.h	25 Nov 2003 21:28:13 -0000	1.31
+++ pango/pango-layout.h	27 Feb 2004 19:09:37 -0000
@@ -55,6 +55,7 @@ struct _PangoLayoutLine
   gint         length;		/* length of line in bytes */
   GSList      *runs;
   guint        is_paragraph_start : 1;  /* TRUE if this is the first line of the paragraph */ 
+  guint        resolved_dir : 3;  /* Resolved direction of line */
 };
 
 #define PANGO_TYPE_LAYOUT              (pango_layout_get_type ())
@@ -111,6 +112,9 @@ int            pango_layout_get_spacing 
 void           pango_layout_set_justify          (PangoLayout                *layout,
 						  gboolean                    justify);
 gboolean       pango_layout_get_justify          (PangoLayout                *layout);
+void           pango_layout_set_auto_dir          (PangoLayout                *layout,
+						  gboolean                    auto_dir);
+gboolean       pango_layout_get_auto_dir          (PangoLayout                *layout);
 void           pango_layout_set_alignment        (PangoLayout                *layout,
 						  PangoAlignment              alignment);
 PangoAlignment pango_layout_get_alignment        (PangoLayout                *layout);
