*** empty log message ***
[m17n/m17n-lib.git] / src / draw.c
index 671acc8..6155d4a 100644 (file)
@@ -1,5 +1,5 @@
 /* draw.c -- drawing module.
-   Copyright (C) 2003, 2004
+   Copyright (C) 2003, 2004, 2005, 2006
      National Institute of Advanced Industrial Science and Technology (AIST)
      Registration Number H15PRO112
 
@@ -17,7 +17,7 @@
 
    You should have received a copy of the GNU Lesser General Public
    License along with the m17n library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    02111-1307, USA.  */
 
 /***en
@@ -80,7 +80,7 @@
 static MSymbol M_glyph_string;
 
 /* Special scripts */
-static MSymbol Minherited, Mcommon;
+static MSymbol Mcommon;
 /* Special categories */
 static MSymbol McatCc, McatCf;
 
@@ -97,6 +97,7 @@ static MSymbol MbidiRLE;
 static MSymbol MbidiRLO;
 static MSymbol MbidiBN;
 static MSymbol MbidiS;
+static MSymbol MbidiNSM;
 
 static void
 visual_order (MGlyphString *gstring)
@@ -116,6 +117,8 @@ visual_order (MGlyphString *gstring)
   int *logical = alloca (sizeof (int) * len);
   int *indices;
   char *levels = alloca (len);
+
+  memset (levels, 0, sizeof (int) * len);
 #endif /* not HAVE_FRIBIDI */
 
   for (g = MGLYPH (1), i = 0; g->type != GLYPH_ANCHOR; g++, i++)
@@ -136,6 +139,10 @@ visual_order (MGlyphString *gstring)
              levels[i] = 1;
 #endif /* not HAVE_FRIBIDI */
            }
+#ifndef HAVE_FRIBIDI
+         else if (bidi == MbidiNSM && i > 0 && levels[i - 1])
+           levels[i] = 1;          
+#endif /* not HAVE_FRIBIDI */
        }
       logical[i] = g->c;
     }
@@ -440,7 +447,11 @@ compose_glyph_string (MFrame *frame, MText *mt, int from, int to,
                                                   NULL, prev->c)
                        != MCHAR_INVALID_CODE));
                   start--, prev--)
-               prev->code = code;
+               if (prev->rface->rfont != this->rface->rfont)
+                 {
+                   prev->rface->rfont = this->rface->rfont;
+                   prev->code = code;
+                 }
 
              for (g++;
                   (g->type == GLYPH_CHAR
@@ -601,7 +612,10 @@ layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to,
          if (base->left_padding && base->lbearing < 0)
            {
              base->xoff = - base->lbearing;
-             base->width += base->xoff;
+             if (base->rbearing < 0)
+               base->width = base->rbearing - base->lbearing;
+             else
+               base->width += base->xoff;
              base->rbearing += base->xoff;
              base->lbearing = 0;
            }
@@ -609,9 +623,8 @@ layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to,
            {
              base->width = base->rbearing;
            }
-         lbearing = (base->xoff + base->lbearing < 0
-                     ? base->xoff + base->lbearing : 0);
-         rbearing = base->xoff + base->rbearing;
+         lbearing = base->lbearing;
+         rbearing = base->rbearing;
        }
       else
        {
@@ -713,6 +726,12 @@ layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to,
              base[i].pos = begin;
              base[i].to = end;
            }
+         if (base->left_padding && lbearing < 0)
+           {
+             base->xoff -= lbearing;
+             base->width -= lbearing;
+             lbearing = 0;
+           }
        }
 
       g_physical_ascent = MAX (g_physical_ascent, base->ascent);
@@ -1093,6 +1112,7 @@ draw_background (MFrame *frame, MDrawWindow win, int x, int y,
     }
 
   *from_idx = *to_idx = 0;
+  *to_x = x;
   while (g->type != GLYPH_ANCHOR)
     {
       if (g->pos >= from && g->pos < to)
@@ -1373,23 +1393,30 @@ find_overlapping_glyphs (MGlyphString *gstring, int *left, int *right,
 
 
 static int
-gstring_width (MGlyphString *gstring, int from, int to, int *rbearing)
+gstring_width (MGlyphString *gstring, int from, int to,
+              int *lbearing, int *rbearing)
 {
   MGlyph *g;
   int width;
 
   if (from <= gstring->from && to >= gstring->to)
     {
+      if (lbearing)
+       *lbearing = gstring->lbearing;
       if (rbearing)
        *rbearing = gstring->rbearing;
       return gstring->width;
     }
 
+  if (lbearing)
+    *lbearing = 0;
   if (rbearing)
     *rbearing = 0;
   for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++)
     if (g->pos >= from && g->pos < to)
       {
+       if (lbearing && width + g->lbearing < *lbearing)
+         *lbearing = width + g->lbearing;
        if (rbearing && width + g->rbearing > *rbearing)
          *rbearing = width + g->rbearing;
        width += g->width;
@@ -1408,8 +1435,10 @@ render_glyph_string (MFrame *frame, MDrawWindow win, int x, int y,
   int from_idx, to_idx;
   int to_x;
 
+  if (from == to)
+    return;
   if (control->orientation_reversed)
-    x -= gstring->indent + gstring_width (gstring, from, to, NULL);
+    x -= gstring->indent + gstring_width (gstring, from, to, NULL, NULL);
   else
     x += gstring->indent;
 
@@ -1572,9 +1601,15 @@ truncate_gstring (MFrame *frame, MText *mt, MGlyphString *gstring)
        pos = gstring->to;
     }
   else if (i == 0)
-    pos++;
-  compose_glyph_string (frame, mt, gstring->from, pos, gstring);
-  layout_glyph_string (frame, gstring);
+    {
+      g = find_glyph_in_gstring (gstring, gstring->from, 1);
+      pos = g->to;
+    }
+  if (pos < gstring->to)
+    {
+      compose_glyph_string (frame, mt, gstring->from, pos, gstring);
+      layout_glyph_string (frame, gstring);
+    }
 }
 
 
@@ -1845,7 +1880,6 @@ mdraw__init ()
   memset (&scratch_gstring, 0, sizeof (scratch_gstring));
   MLIST_INIT1 (&scratch_gstring, glyphs, 3);
 
-  Minherited = msymbol ("inherited");
   Mcommon = msymbol ("common");
 
   McatCc = msymbol ("Cc");
@@ -1857,6 +1891,7 @@ mdraw__init ()
   MbidiRLO = msymbol ("RLO");
   MbidiBN = msymbol ("BN");
   MbidiS = msymbol ("S");
+  MbidiNSM = msymbol ("NSM");
 #ifdef HAVE_FRIBIDI
   fribidi_set_mirroring (TRUE);
 #endif
@@ -2219,7 +2254,7 @@ mdraw_text_extents (MFrame *frame,
 {
   MGlyphString *gstring;
   int y = 0;
-  int width, rbearing;
+  int width, lbearing, rbearing;
 
   ASSURE_CONTROL (control);
   M_CHECK_POS_X (mt, from, -1);
@@ -2231,52 +2266,49 @@ mdraw_text_extents (MFrame *frame,
   gstring = get_gstring (frame, mt, from, to, control);
   if (! gstring)
     MERROR (MERROR_DRAW, -1);
-  width = gstring_width (gstring, from, to, &rbearing);
+  width = gstring_width (gstring, from, to, &lbearing, &rbearing);
   if (overall_ink_return)
-    {
-      overall_ink_return->y = - gstring->physical_ascent;
-      overall_ink_return->x = gstring->lbearing;
-    }
+    overall_ink_return->y = - gstring->physical_ascent;
   if (overall_logical_return)
-    {
-      overall_logical_return->y = - gstring->ascent;
-      overall_logical_return->x = 0;
-    }
+    overall_logical_return->y = - gstring->ascent;
   if (overall_line_return)
-    {
-      overall_line_return->y = - gstring->line_ascent;
-      overall_line_return->x = gstring->lbearing;
-    }
+    overall_line_return->y = - gstring->line_ascent;
 
   for (from = gstring->to; from < to; from = gstring->to)
     {
-      int this_width, this_rbearing;
+      int this_width, this_lbearing, this_rbearing;
 
       y += gstring->line_descent;
       M17N_OBJECT_UNREF (gstring->top);
       gstring = get_gstring (frame, mt, from, to, control);
-      this_width = gstring_width (gstring, from, to, &this_rbearing);
+      this_width = gstring_width (gstring, from, to,
+                                 &this_lbearing, &this_rbearing);
       y += gstring->line_ascent;
       if (width < this_width)
        width = this_width;
       if (rbearing < this_rbearing)
        rbearing = this_rbearing;
+      if (lbearing > this_lbearing)
+       lbearing = this_lbearing;
     }
   if (overall_ink_return)
     {
-      overall_ink_return->width = rbearing;
+      overall_ink_return->x = lbearing;
+      overall_ink_return->width = rbearing - lbearing;
       overall_ink_return->height
        = y + gstring->physical_descent - overall_ink_return->y;
     }
   if (overall_logical_return)
     {
+      overall_logical_return->x = 0;
       overall_logical_return->width = width;
       overall_logical_return->height
        = y + gstring->descent - overall_logical_return->y;
     }
   if (overall_line_return)
     {
-      overall_line_return->width = MAX (width, rbearing);
+      overall_line_return->x = lbearing;
+      overall_line_return->width = MAX (width, rbearing - lbearing);
       overall_line_return->height
        = y + gstring->line_descent - overall_line_return->y;
     }