emacs-devel
[Top][All Lists]
Advanced

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

Re: ATSUI support on Carbon Emacs


From: YAMAMOTO Mitsuharu
Subject: Re: ATSUI support on Carbon Emacs
Date: Thu, 06 Oct 2005 17:20:59 +0900
User-agent: Wanderlust/2.14.0 (Africa) SEMI/1.14.6 (Maruoka) FLIM/1.14.6 (Marutamachi) APEL/10.6 Emacs/22.0.50 (sparc-sun-solaris2.8) MULE/5.0 (SAKAKI)

>>>>> On Sat, 01 Oct 2005 20:28:45 +0900, YAMAMOTO Mitsuharu <address@hidden> 
>>>>> said:

>   * Tall characters get thicker because they are overdrawn when
>     overlapping rows are redrawn.  This is the verical version of
>     the following problem:
>     http://lists.gnu.org/archive/html/emacs-devel/2005-01/msg00729.html

Some changes to the platform-independent part are needed to fix this,
just like the horizontal one.  In the following patch, overlapping
glyph drawing is divided into several cases: overlapping with the
preceding rows, overlapping with the succeeding rows, both of them,
and overlapping in the erased cursor area.  And clipping rectangles
are calculated according to the type of overlapping.

May I install this?  Such changes will be needed when we support other
anti-aliasing environments such as Xft.

                                     YAMAMOTO Mitsuharu
                                address@hidden

Index: src/dispextern.h
===================================================================
RCS file: /cvsroot/emacs/emacs/src/dispextern.h,v
retrieving revision 1.209
diff -c -r1.209 dispextern.h
*** src/dispextern.h    30 Sep 2005 22:38:16 -0000      1.209
--- src/dispextern.h    6 Oct 2005 07:03:05 -0000
***************
*** 1182,1191 ****
       stipple pattern.  */
    unsigned stippled_p : 1;
  
!   /* 1 means only the foreground of this glyph string must be drawn,
!      and we should use the physical height of the line this glyph
!      string appears in as clip rect.  */
!   unsigned for_overlaps_p : 1;
  
    /* The GC to use for drawing this glyph string.  */
  #if defined(HAVE_X_WINDOWS) || defined(MAC_OS)
--- 1182,1199 ----
       stipple pattern.  */
    unsigned stippled_p : 1;
  
! #define OVERLAPS_PRED         (1 << 0)
! #define OVERLAPS_SUCC         (1 << 1)
! #define OVERLAPS_BOTH         (OVERLAPS_PRED | OVERLAPS_SUCC)
! #define OVERLAPS_ERASED_CURSOR        (1 << 2)
!   /* Non-zero means only the foreground of this glyph string must be
!      drawn, and we should use the physical height of the line this
!      glyph string appears in as clip rect.  If the value is
!      OVERLAPS_ERASED_CURSOR, the clip rect is restricted to the rect
!      of the erased cursor.  OVERLAPS_PRED and OVERLAPS_SUCC mean we
!      draw overlaps with the preceding and the succeeding rows,
!      respectively.  */
!   unsigned for_overlaps_p : 3;
  
    /* The GC to use for drawing this glyph string.  */
  #if defined(HAVE_X_WINDOWS) || defined(MAC_OS)
***************
*** 2266,2272 ****
       This function is called from redraw_overlapping_rows after
       desired rows have been made current.  */
    void (*fix_overlapping_area) P_ ((struct window *w, struct glyph_row *row,
!                                   enum glyph_row_area area));
  
  #ifdef HAVE_WINDOW_SYSTEM
  
--- 2274,2280 ----
       This function is called from redraw_overlapping_rows after
       desired rows have been made current.  */
    void (*fix_overlapping_area) P_ ((struct window *w, struct glyph_row *row,
!                                   enum glyph_row_area area, int));
  
  #ifdef HAVE_WINDOW_SYSTEM
  
***************
*** 2664,2670 ****
  extern struct cursor_pos output_cursor;
  
  extern void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
!                                       enum glyph_row_area));
  extern void draw_phys_cursor_glyph P_ ((struct window *,
                                          struct glyph_row *,
                                          enum draw_glyphs_face));
--- 2672,2678 ----
  extern struct cursor_pos output_cursor;
  
  extern void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
!                                       enum glyph_row_area, int));
  extern void draw_phys_cursor_glyph P_ ((struct window *,
                                          struct glyph_row *,
                                          enum draw_glyphs_face));
***************
*** 2682,2687 ****
--- 2690,2697 ----
  extern void x_draw_vertical_border P_ ((struct window *w));
  
  extern void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
+ extern int get_glyph_string_clip_rects P_ ((struct glyph_string *,
+                                           NativeRectangle *, int));
  extern void get_glyph_string_clip_rect P_ ((struct glyph_string *,
                                            NativeRectangle *nr));
  extern Lisp_Object find_hot_spot P_ ((Lisp_Object, int, int));
Index: src/dispnew.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/dispnew.c,v
retrieving revision 1.356
diff -c -r1.356 dispnew.c
*** src/dispnew.c       1 Sep 2005 14:16:19 -0000       1.356
--- src/dispnew.c       6 Oct 2005 07:03:06 -0000
***************
*** 4035,4057 ****
  
        if (row->overlapping_p && i > 0 && bottom_y < yb)
        {
!         if (row->used[LEFT_MARGIN_AREA])
!           rif->fix_overlapping_area (w, row, LEFT_MARGIN_AREA);
  
!         if (row->used[TEXT_AREA])
!           rif->fix_overlapping_area (w, row, TEXT_AREA);
  
!         if (row->used[RIGHT_MARGIN_AREA])
!           rif->fix_overlapping_area (w, row, RIGHT_MARGIN_AREA);
  
!         /* Record in neighbour rows that ROW overwrites part of their
!            display.  */
!         if (row->phys_ascent > row->ascent && i > 0)
!           MATRIX_ROW (w->current_matrix, i - 1)->overlapped_p = 1;
!         if ((row->phys_height - row->phys_ascent
!              > row->height - row->ascent)
!             && bottom_y < yb)
!           MATRIX_ROW (w->current_matrix, i + 1)->overlapped_p = 1;
        }
  
        if (bottom_y >= yb)
--- 4035,4067 ----
  
        if (row->overlapping_p && i > 0 && bottom_y < yb)
        {
!         int overlaps = 0;
  
!         if (MATRIX_ROW_OVERLAPS_PRED_P (row)
!             && !MATRIX_ROW (w->current_matrix, i - 1)->overlapped_p)
!           overlaps |= OVERLAPS_PRED;
!         if (MATRIX_ROW_OVERLAPS_SUCC_P (row)
!             && !MATRIX_ROW (w->current_matrix, i + 1)->overlapped_p)
!           overlaps |= OVERLAPS_SUCC;
  
!         if (overlaps)
!           {
!             if (row->used[LEFT_MARGIN_AREA])
!               rif->fix_overlapping_area (w, row, LEFT_MARGIN_AREA, overlaps);
  
!             if (row->used[TEXT_AREA])
!               rif->fix_overlapping_area (w, row, TEXT_AREA, overlaps);
! 
!             if (row->used[RIGHT_MARGIN_AREA])
!               rif->fix_overlapping_area (w, row, RIGHT_MARGIN_AREA, overlaps);
! 
!             /* Record in neighbour rows that ROW overwrites part of
!                their display.  */
!             if (overlaps & OVERLAPS_PRED)
!               MATRIX_ROW (w->current_matrix, i - 1)->overlapped_p = 1;
!             if (overlaps & OVERLAPS_SUCC)
!               MATRIX_ROW (w->current_matrix, i + 1)->overlapped_p = 1;
!           }
        }
  
        if (bottom_y >= yb)
Index: src/xdisp.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/xdisp.c,v
retrieving revision 1.1057
diff -c -r1.1057 xdisp.c
*** src/xdisp.c 1 Oct 2005 20:42:09 -0000       1.1057
--- src/xdisp.c 6 Oct 2005 07:03:06 -0000
***************
*** 1768,1782 ****
  }
  
  /* EXPORT:
!    Return in *R the clipping rectangle for glyph string S.  */
  
! void
! get_glyph_string_clip_rect (s, nr)
       struct glyph_string *s;
!      NativeRectangle *nr;
  {
    XRectangle r;
  
    if (s->row->full_width_p)
      {
        /* Draw full-width.  X coordinates are relative to S->w->left_col.  */
--- 1768,1787 ----
  }
  
  /* EXPORT:
!    Return in RECTS[] at most N clipping rectangles for glyph string S.
!    Return the number of stored rectangles.  */
  
! int
! get_glyph_string_clip_rects (s, rects, n)
       struct glyph_string *s;
!      NativeRectangle *rects;
!      int n;
  {
    XRectangle r;
  
+   if (n <= 0)
+     return 0;
+ 
    if (s->row->full_width_p)
      {
        /* Draw full-width.  X coordinates are relative to S->w->left_col.  */
***************
*** 1823,1828 ****
--- 1828,1850 ----
      {
        r.y = WINDOW_HEADER_LINE_HEIGHT (s->w);
        r.height = window_text_bottom_y (s->w) - r.y;
+ 
+       /* Alas, the above simple strategy does not work for the
+        environments with anti-aliased text: if the same text is
+        drawn onto the same place multiple times, it gets thicker.
+        If the overlap we are processing is for the erased cursor, we
+        take the intersection with the rectagle of the cursor.  */
+       if (s->for_overlaps_p & OVERLAPS_ERASED_CURSOR)
+       {
+         XRectangle rc, r_save = r;
+ 
+         rc.x = WINDOW_TEXT_TO_FRAME_PIXEL_X (s->w, s->w->phys_cursor.x);
+         rc.y = s->w->phys_cursor.y;
+         rc.width = s->w->phys_cursor_width;
+         rc.height = s->w->phys_cursor_height;
+ 
+         x_intersect_rectangles (&r_save, &rc, &r);
+       }
      }
    else
      {
***************
*** 1881,1891 ****
        }
      }
  
  #ifdef CONVERT_FROM_XRECT
!   CONVERT_FROM_XRECT (r, *nr);
  #else
!   *nr = r;
  #endif
  }
  
  
--- 1903,1973 ----
        }
      }
  
+   if ((s->for_overlaps_p & OVERLAPS_BOTH) == 0
+       || (s->for_overlaps_p & OVERLAPS_BOTH) == OVERLAPS_BOTH && n == 1)
+     {
  #ifdef CONVERT_FROM_XRECT
!       CONVERT_FROM_XRECT (r, *rects);
  #else
!       *rects = r;
! #endif
!       return 1;
!     }
!   else
!     {
!       /* If we are processing overlapping and allowed to return
!        multiple clipping rectangles, we exclude the row of the glyph
!        string from the clipping rectangle.  This is to avoid drawing
!        the same text on the environment with anti-aliasing.  */
! #ifdef CONVERT_FROM_XRECT
!       XRectangle rs[2];
! #else
!       XRectangle *rs = rects;
! #endif
!       int i = 0, row_y = WINDOW_TO_FRAME_PIXEL_Y (s->w, s->row->y);
! 
!       if (s->for_overlaps_p & OVERLAPS_PRED)
!       {
!         rs[i] = r;
!         if (r.y + r.height > row_y)
!           if (r.y < row_y)
!             rs[i].height = row_y - r.y;
!           else
!             rs[i].height = 0;
!         i++;
!       }
!       if (s->for_overlaps_p & OVERLAPS_SUCC)
!       {
!         rs[i] = r;
!         if (r.y < row_y + s->row->visible_height)
!           if (r.y + r.height > row_y + s->row->visible_height)
!             {
!               rs[i].y = row_y + s->row->visible_height;
!               rs[i].height = r.y + r.height - rs[i].y;
!             }
!           else
!             rs[i].height = 0;
!         i++;
!       }
! 
!       n = i;
! #ifdef CONVERT_FROM_XRECT
!       for (i = 0; i < n; i++)
!       CONVERT_FROM_XRECT (rs[i], rects[i]);
  #endif
+       return n;
+     }
+ }
+ 
+ /* EXPORT:
+    Return in *NR the clipping rectangle for glyph string S.  */
+ 
+ void
+ get_glyph_string_clip_rect (s, nr)
+      struct glyph_string *s;
+      NativeRectangle *nr;
+ {
+   get_glyph_string_clip_rects (s, nr, 1);
  }
  
  
***************
*** 20588,20600 ****
  #ifdef HAVE_WINDOW_SYSTEM
  
  /* EXPORT for RIF:
!    Fix the display of area AREA of overlapping row ROW in window W.  */
  
  void
! x_fix_overlapping_area (w, row, area)
       struct window *w;
       struct glyph_row *row;
       enum glyph_row_area area;
  {
    int i, x;
  
--- 20670,20684 ----
  #ifdef HAVE_WINDOW_SYSTEM
  
  /* EXPORT for RIF:
!    Fix the display of area AREA of overlapping row ROW in window W
!    with respect to the overlapping part OVERLAPS.  */
  
  void
! x_fix_overlapping_area (w, row, area, overlaps)
       struct window *w;
       struct glyph_row *row;
       enum glyph_row_area area;
+      int overlaps;
  {
    int i, x;
  
***************
*** 20617,20623 ****
  
          draw_glyphs (w, start_x, row, area,
                       start, i,
!                      DRAW_NORMAL_TEXT, 1);
        }
        else
        {
--- 20701,20707 ----
  
          draw_glyphs (w, start_x, row, area,
                       start, i,
!                      DRAW_NORMAL_TEXT, overlaps);
        }
        else
        {
***************
*** 20659,20671 ****
         are redrawn.  */
        else if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
        {
          if (row > w->current_matrix->rows
              && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
!           x_fix_overlapping_area (w, row - 1, TEXT_AREA);
  
          if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
              && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
!           x_fix_overlapping_area (w, row + 1, TEXT_AREA);
        }
      }
  }
--- 20743,20759 ----
         are redrawn.  */
        else if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
        {
+         w->phys_cursor_width = x1 - w->phys_cursor.x;
+ 
          if (row > w->current_matrix->rows
              && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
!           x_fix_overlapping_area (w, row - 1, TEXT_AREA,
!                                   OVERLAPS_ERASED_CURSOR);
  
          if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
              && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
!           x_fix_overlapping_area (w, row + 1, TEXT_AREA,
!                                   OVERLAPS_ERASED_CURSOR);
        }
      }
  }
***************
*** 22456,22468 ****
        xassert (row->enabled_p && !row->mode_line_p);
  
        if (row->used[LEFT_MARGIN_AREA])
!         x_fix_overlapping_area (w, row, LEFT_MARGIN_AREA);
  
        if (row->used[TEXT_AREA])
!         x_fix_overlapping_area (w, row, TEXT_AREA);
  
        if (row->used[RIGHT_MARGIN_AREA])
!         x_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA);
        }
  }
  
--- 22544,22556 ----
        xassert (row->enabled_p && !row->mode_line_p);
  
        if (row->used[LEFT_MARGIN_AREA])
!         x_fix_overlapping_area (w, row, LEFT_MARGIN_AREA, OVERLAPS_BOTH);
  
        if (row->used[TEXT_AREA])
!         x_fix_overlapping_area (w, row, TEXT_AREA, OVERLAPS_BOTH);
  
        if (row->used[RIGHT_MARGIN_AREA])
!         x_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA, OVERLAPS_BOTH);
        }
  }
  




reply via email to

[Prev in Thread] Current Thread [Next in Thread]