[cairo-commit] cairo/src cairo_font.c, 1.18, 1.19 cairo_ft_font.c, 1.22, 1.23 cairo_gl_surface.c, 1.8, 1.9 cairo_gstate.c, 1.51, 1.52 cairo_image_surface.c, 1.11, 1.12 cairo_png_surface.c, 1.6, 1.7 cairo_ps_surface.c, 1.9, 1.10 cairo_surface.c, 1.30, 1.31 cairo_xcb_surface.c, 1.4, 1.5 cairo_xlib_surface.c, 1.20, 1.21 cairoint.h, 1.63, 1.64

David Reveman commit at pdx.freedesktop.org
Mon May 24 02:28:07 PDT 2004


Committed by: davidr

Update of /cvs/cairo/cairo/src
In directory pdx:/tmp/cvs-serv4356/src

Modified Files:
	cairo_font.c cairo_ft_font.c cairo_gl_surface.c cairo_gstate.c 
	cairo_image_surface.c cairo_png_surface.c cairo_ps_surface.c 
	cairo_surface.c cairo_xcb_surface.c cairo_xlib_surface.c 
	cairoint.h 
Log Message:
Added glyph caching

Index: cairo_font.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_font.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -C2 -d -r1.18 -r1.19
*** a/cairo_font.c	16 Dec 2003 14:50:37 -0000	1.18
--- b/cairo_font.c	24 May 2004 09:28:05 -0000	1.19
***************
*** 28,31 ****
--- 28,37 ----
  #include "cairoint.h"
  
+ static cairo_glyph_cache_t *
+ _cairo_glyph_cache_create (void);
+ 
+ static void
+ _cairo_glyph_cache_reference (cairo_glyph_cache_t *glyph_cache);
+ 
  cairo_font_t *
  _cairo_font_create (const char           *family, 
***************
*** 51,54 ****
--- 57,63 ----
      font->refcount = 1;
      font->backend = backend;
+     font->glyph_cache = _cairo_glyph_cache_create ();
+     if (font->glyph_cache == NULL)
+ 	return CAIRO_STATUS_NO_MEMORY;
      
      return CAIRO_STATUS_SUCCESS;
***************
*** 73,76 ****
--- 82,89 ----
      cairo_matrix_copy(&newfont->matrix, &font->matrix);
      newfont->backend = font->backend;
+ 
+     newfont->glyph_cache = font->glyph_cache;
+     _cairo_glyph_cache_reference (font->glyph_cache);
+     
      return newfont;
  }
***************
*** 106,109 ****
--- 119,142 ----
  }
  
+ cairo_status_t
+ _cairo_font_text_bbox (cairo_font_t             *font,
+                        cairo_surface_t          *surface,
+                        double                   x,
+                        double                   y,
+                        const unsigned char      *utf8,
+ 		       cairo_box_t		*bbox)
+ {
+     return font->backend->text_bbox (font, surface, x, y, utf8, bbox);
+ }
+ 
+ cairo_status_t
+ _cairo_font_glyph_bbox (cairo_font_t            *font,
+ 			cairo_surface_t         *surface,
+ 			cairo_glyph_t           *glyphs,
+ 			int                     num_glyphs,
+ 			cairo_box_t		*bbox)
+ {
+     return font->backend->glyph_bbox (font, surface, glyphs, num_glyphs, bbox);
+ }
  
  cairo_status_t
***************
*** 112,115 ****
--- 145,150 ----
  		       cairo_surface_t		*source,
  		       cairo_surface_t		*surface,
+ 		       int                      source_x,
+ 		       int                      source_y,
  		       double			x,
  		       double			y,
***************
*** 117,121 ****
  {
      return font->backend->show_text(font, operator, source, 
! 				    surface, x, y, utf8);
  }
  
--- 152,156 ----
  {
      return font->backend->show_text(font, operator, source, 
! 				    surface, source_x, source_y, x, y, utf8);
  }
  
***************
*** 125,133 ****
                           cairo_surface_t        *source,
                           cairo_surface_t        *surface,
                           cairo_glyph_t          *glyphs,
                           int                    num_glyphs)
  {
      return font->backend->show_glyphs(font, operator, source, 
! 				      surface, glyphs, num_glyphs);
  }
  
--- 160,171 ----
                           cairo_surface_t        *source,
                           cairo_surface_t        *surface,
+ 			 int                    source_x,
+ 			 int                    source_y,
                           cairo_glyph_t          *glyphs,
                           int                    num_glyphs)
  {
      return font->backend->show_glyphs(font, operator, source, 
! 				      surface, source_x, source_y,
! 				      glyphs, num_glyphs);
  }
  
***************
*** 158,161 ****
--- 196,374 ----
  }
  
+ static void
+ _cairo_glyph_cache_pop_last (cairo_glyph_cache_t *glyph_cache)
+ {
+     if (glyph_cache->last) {
+ 	cairo_glyph_surface_node_t *remove = glyph_cache->last;
+ 	
+ 	cairo_surface_destroy (remove->s.surface);
+ 	glyph_cache->last = remove->prev;
+ 	if (glyph_cache->last)
+ 	    glyph_cache->last->next = NULL;
+ 
+ 	free (remove);
+ 	glyph_cache->n_nodes--;
+     }
+ }
+ 
+ static cairo_glyph_cache_t *
+ _cairo_glyph_cache_create (void)
+ {
+     cairo_glyph_cache_t *glyph_cache;
+ 	
+     glyph_cache = malloc (sizeof (cairo_glyph_cache_t));
+     if (glyph_cache == NULL)
+ 	return NULL;
+     
+     glyph_cache->n_nodes = 0;
+     glyph_cache->first = NULL;
+     glyph_cache->last = NULL;
+     glyph_cache->cache_size = CAIRO_FONT_CACHE_SIZE_DEFAULT;
+     glyph_cache->ref_count = 1;
+ 
+     return glyph_cache;
+ }
+ 
+ static void
+ _cairo_glyph_cache_reference (cairo_glyph_cache_t *glyph_cache)
+ {
+     if (glyph_cache == NULL)
+ 	return;
+ 
+     glyph_cache->ref_count++;
+ }
+ 
+ static void
+ _cairo_glyph_cache_destroy (cairo_glyph_cache_t *glyph_cache)
+ {
+     if (glyph_cache == NULL)
+ 	return;
+ 
+     glyph_cache->ref_count--;
+     if (glyph_cache->ref_count)
+ 	return;
+ 
+     while (glyph_cache->last)
+ 	_cairo_glyph_cache_pop_last (glyph_cache);
+ 
+     free (glyph_cache);
+ }
+ 
+ static void
+ _cairo_glyph_surface_init (cairo_font_t *font,
+ 			   cairo_surface_t *surface,
+ 			   const cairo_glyph_t *glyph,
+ 			   cairo_glyph_surface_t *glyph_surface)
+ {
+     cairo_surface_t *image;
+     
+     glyph_surface->surface = NULL;
+     glyph_surface->index = glyph->index;
+     glyph_surface->matrix[0][0] = font->matrix.m[0][0];
+     glyph_surface->matrix[0][1] = font->matrix.m[0][1];
+     glyph_surface->matrix[1][0] = font->matrix.m[1][0];
+     glyph_surface->matrix[1][1] = font->matrix.m[1][1];
+ 
+     image = font->backend->create_glyph (font, glyph, &glyph_surface->size);
+     if (image == NULL)
+ 	return;
+     
+     if (surface->backend != image->backend) {
+ 	cairo_status_t status;
+ 	
+ 	glyph_surface->surface =
+ 	    _cairo_surface_create_similar_scratch (surface,
+ 						   CAIRO_FORMAT_A8, 0,
+ 						   glyph_surface->size.width,
+ 						   glyph_surface->size.height);
+ 	if (glyph_surface->surface == NULL)
+ 	    return;
+ 	
+ 	status = _cairo_surface_set_image (glyph_surface->surface,
+ 					   (cairo_image_surface_t *) image);
+ 	if (status) {
+ 	    cairo_surface_destroy (glyph_surface->surface);
+ 	    glyph_surface->surface = NULL;
+ 	}
+ 	cairo_surface_destroy (image);
+     } else
+ 	glyph_surface->surface = image;
+ }
+ 
+ cairo_surface_t *
+ _cairo_font_lookup_glyph (cairo_font_t *font,
+ 			  cairo_surface_t *surface,
+ 			  const cairo_glyph_t *glyph,
+ 			  cairo_glyph_size_t *return_size)
+ {
+     cairo_glyph_surface_t glyph_surface;
+     cairo_glyph_cache_t *cache = font->glyph_cache;
+     cairo_glyph_surface_node_t *node;
+ 	
+     for (node = cache->first; node != NULL; node = node->next) {
+ 	cairo_glyph_surface_t *s = &node->s;
+ 
+ 	if ((s->surface == NULL || s->surface->backend == surface->backend) &&
+ 	    s->index == glyph->index &&
+ 	    s->matrix[0][0] == font->matrix.m[0][0] &&
+ 	    s->matrix[0][1] == font->matrix.m[0][1] &&
+ 	    s->matrix[1][0] == font->matrix.m[1][0] &&
+ 	    s->matrix[1][1] == font->matrix.m[1][1]) {
+ 
+ 	    /* move node first in cache */
+ 	    if (node->prev) {
+ 		if (node->next == NULL) {    
+ 		    cache->last = node->prev;
+ 		    node->prev->next = NULL;
+ 		} else {
+ 		    node->prev->next = node->next;
+ 		    node->next->prev = node->prev;
+ 		}
+ 
+ 		node->prev = NULL;
+ 		node->next = cache->first;
+ 		cache->first = node;
+ 		if (node->next)
+ 		    node->next->prev = node;
+ 		else
+ 		    cache->last = node;
+ 	    }
+ 	    
+ 	    cairo_surface_reference (s->surface);
+ 	    *return_size = s->size;
+ 	    
+ 	    return s->surface;
+ 	}
+     }
+     
+     _cairo_glyph_surface_init (font, surface, glyph, &glyph_surface);
+ 
+     *return_size = glyph_surface.size;
+     
+     if (cache->cache_size > 0) {
+ 	if (cache->n_nodes == cache->cache_size)
+ 	    _cairo_glyph_cache_pop_last (cache);
+ 
+ 	node = malloc (sizeof (cairo_glyph_surface_node_t));
+ 	if (node) {
+ 	    cairo_surface_reference (glyph_surface.surface);
+ 	    
+ 	    /* insert node first in cache */
+ 	    node->s = glyph_surface;
+ 	    node->prev = NULL;
+ 	    node->next = cache->first;
+ 	    cache->first = node;
+ 	    if (node->next)
+ 		node->next->prev = node;
+ 	    else
+ 		cache->last = node;
+ 
+ 	    cache->n_nodes++;
+ 	}
+     }
+     
+     return glyph_surface.surface;
+ }
+ 
  /* public font interface follows */
  
***************
*** 172,175 ****
--- 385,390 ----
  	return;
  
+     _cairo_glyph_cache_destroy (font->glyph_cache);
+ 
      if (font->backend->destroy)
  	font->backend->destroy (font);
***************
*** 189,192 ****
      cairo_matrix_copy (matrix, &(font->matrix));
  }
- 
- 
--- 404,405 ----

Index: cairo_ft_font.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_ft_font.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -C2 -d -r1.22 -r1.23
*** a/cairo_ft_font.c	8 May 2004 01:52:02 -0000	1.22
--- b/cairo_ft_font.c	24 May 2004 09:28:05 -0000	1.23
***************
*** 30,33 ****
--- 30,34 ----
  #include FT_FREETYPE_H
  #include FT_OUTLINE_H
+ #include FT_IMAGE_H
  
  typedef struct {
***************
*** 465,472 ****
  
  static cairo_status_t 
  _cairo_ft_font_show_glyphs (void		*abstract_font,
                              cairo_operator_t    operator,
                              cairo_surface_t     *source,
!                             cairo_surface_t     *surface,
                              const cairo_glyph_t *glyphs,
                              int                 num_glyphs)
--- 466,552 ----
  
  static cairo_status_t 
+ _cairo_ft_font_glyph_bbox (void		       *abstract_font,
+ 			   cairo_surface_t     *surface,
+ 			   const cairo_glyph_t *glyphs,
+ 			   int                 num_glyphs,
+ 			   cairo_box_t         *bbox)
+ {
+     cairo_ft_font_t *font = abstract_font;
+     cairo_surface_t *mask = NULL;
+     cairo_glyph_size_t size;
+ 
+     cairo_fixed_t x1, y1, x2, y2;
+     int i;
+ 
+     bbox->p1.x = bbox->p1.y = CAIRO_MAXSHORT << 16;
+     bbox->p2.x = bbox->p2.y = CAIRO_MINSHORT << 16;
+ 
+     if (font == NULL
+ 	|| surface == NULL
+ 	|| glyphs == NULL)
+         return CAIRO_STATUS_NO_MEMORY;
+ 
+     for (i = 0; i < num_glyphs; i++)
+     {
+ 	mask = _cairo_font_lookup_glyph (&font->base, surface,
+ 					 &glyphs[i], &size);
+ 	if (mask == NULL)
+ 	    continue;
+ 
+ 	x1 = _cairo_fixed_from_double (glyphs[i].x + size.x);
+ 	y1 = _cairo_fixed_from_double (glyphs[i].y - size.y);
+ 	x2 = x1 + _cairo_fixed_from_double (size.width);
+ 	y2 = y1 + _cairo_fixed_from_double (size.height);
+ 	
+ 	if (x1 < bbox->p1.x)
+ 	    bbox->p1.x = x1;
+ 	
+ 	if (y1 < bbox->p1.y)
+ 	    bbox->p1.y = y1;
+ 	
+ 	if (x2 > bbox->p2.x)
+ 	    bbox->p2.x = x2;
+ 	
+ 	if (y2 > bbox->p2.y)
+ 	    bbox->p2.y = y2;
+ 	
+ 	if (mask)
+ 	    cairo_surface_destroy (mask);
+     }
+ 
+     return CAIRO_STATUS_SUCCESS;
+ }
+ 
+ static cairo_status_t 
+ _cairo_ft_font_text_bbox (void		      *abstract_font,
+                           cairo_surface_t     *surface,
+                           double              x0,
+                           double              y0,
+                           const unsigned char *utf8,
+ 			  cairo_box_t *bbox)
+ {
+     cairo_ft_font_t *font = abstract_font;
+     cairo_glyph_t *glyphs;
+     size_t num_glyphs;
+     
+     if (_utf8_to_glyphs (font, utf8, x0, y0, &glyphs, &num_glyphs))
+     {
+         cairo_status_t res;
+         res = _cairo_ft_font_glyph_bbox (font, surface,
+ 					 glyphs, num_glyphs, bbox);
+         free (glyphs);
+         return res;
+     }
+     else
+         return CAIRO_STATUS_NO_MEMORY;
+ }
+ 
+ static cairo_status_t 
  _cairo_ft_font_show_glyphs (void		*abstract_font,
                              cairo_operator_t    operator,
                              cairo_surface_t     *source,
! 			    cairo_surface_t     *surface,
! 			    int                 source_x,
! 			    int                 source_y,
                              const cairo_glyph_t *glyphs,
                              int                 num_glyphs)
***************
*** 474,485 ****
      cairo_ft_font_t *font = abstract_font;
      cairo_status_t status;
-     int i;
-     cairo_ft_font_t *ft = NULL;
-     FT_GlyphSlot glyphslot;
      cairo_surface_t *mask = NULL;
!     cairo_point_double_t origin;
  
      double x, y;
!     int width, height, stride;
  
      if (font == NULL 
--- 554,562 ----
      cairo_ft_font_t *font = abstract_font;
      cairo_status_t status;
      cairo_surface_t *mask = NULL;
!     cairo_glyph_size_t size;
  
      double x, y;
!     int i;
  
      if (font == NULL 
***************
*** 489,570 ****
          return CAIRO_STATUS_NO_MEMORY;
  
-     ft = (cairo_ft_font_t *)font;
-     glyphslot = ft->face->glyph;
-     _install_font_matrix (&font->base.matrix, ft->face);
- 
      for (i = 0; i < num_glyphs; i++)
      {
! 	unsigned char *bitmap;
! 
!         FT_Load_Glyph (ft->face, glyphs[i].index, FT_LOAD_DEFAULT);
!         FT_Render_Glyph (glyphslot, ft_render_mode_normal);
!       
!         width = glyphslot->bitmap.width;
!         height = glyphslot->bitmap.rows;
!         stride = glyphslot->bitmap.pitch;
! 	bitmap = glyphslot->bitmap.buffer;
     
  	x = glyphs[i].x;
  	y = glyphs[i].y;
  
! 	if (i == 0) {
! 	    origin.x = x;
! 	    origin.y = y;
! 	}
! 
!         /* X gets upset with zero-sized images (such as whitespace) */
!         if (width * height == 0)
! 	    continue;
! 	    
! 	/*
! 	 * XXX 
! 	 * reformat to match libic alignment requirements.
! 	 * This should be done before rendering the glyph,
! 	 * but that requires using FT_Outline_Get_Bitmap
! 	 * function
! 	 */
! 	if (stride & 3)
! 	{
! 	    int		nstride = (stride + 3) & ~3;
! 	    unsigned char	*g, *b;
! 	    int		h;
! 	    
! 	    bitmap = malloc (nstride * height);
! 	    if (!bitmap)
! 		return CAIRO_STATUS_NO_MEMORY;
! 	    g = glyphslot->bitmap.buffer;
! 	    b = bitmap;
! 	    h = height;
! 	    while (h--)
! 	    {
! 		memcpy (b, g, width);
! 		b += nstride;
! 		g += stride;
! 	    }
! 	    stride = nstride;
! 	}
! 	mask = cairo_surface_create_for_image (bitmap,
! 					       CAIRO_FORMAT_A8,
! 					       width, height, stride);
! 	if (mask == NULL)
! 	{
! 	    if (bitmap != glyphslot->bitmap.buffer)
! 		free (bitmap);
! 	    return CAIRO_STATUS_NO_MEMORY;
! 	}
! 	
! 	status =
! 	    _cairo_surface_composite (operator, source, mask, surface,
! 				      -origin.x + x + glyphslot->bitmap_left,
! 				      -origin.y + y - glyphslot->bitmap_top,
! 				      0, 0, 
! 				      x + glyphslot->bitmap_left, 
! 				      y - glyphslot->bitmap_top, 
! 				      (double) width, (double) height);
  	
  	cairo_surface_destroy (mask);
! 	if (bitmap != glyphslot->bitmap.buffer)
! 	    free (bitmap);
! 	
  	if (status)
  	    return status;
--- 566,590 ----
          return CAIRO_STATUS_NO_MEMORY;
  
      for (i = 0; i < num_glyphs; i++)
      {
! 	mask = _cairo_font_lookup_glyph (&font->base, surface,
! 					 &glyphs[i], &size);
! 	if (mask == NULL)
! 	    continue;
     
  	x = glyphs[i].x;
  	y = glyphs[i].y;
  
! 	status = _cairo_surface_composite (operator, source, mask, surface,
! 					   source_x + x + size.x,
! 					   source_y + y - size.y,
! 					   0, 0, 
! 					   x + size.x, 
! 					   y - size.y, 
! 					   (double) size.width,
! 					   (double) size.height);
  	
  	cairo_surface_destroy (mask);
! 
  	if (status)
  	    return status;
***************
*** 578,581 ****
--- 598,603 ----
                            cairo_surface_t     *source,
                            cairo_surface_t     *surface,
+ 			  int                 source_x,
+ 			  int                 source_y,
                            double              x0,
                            double              y0,
***************
*** 584,588 ****
      cairo_ft_font_t *font = abstract_font;
      cairo_glyph_t *glyphs;
!     int num_glyphs;
      
      if (_utf8_to_glyphs (font, utf8, x0, y0, &glyphs, &num_glyphs))
--- 606,610 ----
      cairo_ft_font_t *font = abstract_font;
      cairo_glyph_t *glyphs;
!     size_t num_glyphs;
      
      if (_utf8_to_glyphs (font, utf8, x0, y0, &glyphs, &num_glyphs))
***************
*** 591,594 ****
--- 613,617 ----
          res = _cairo_ft_font_show_glyphs (font, operator, 
                                            source, surface,
+ 					  source_x, source_y,
                                            glyphs, num_glyphs);      
          free (glyphs);
***************
*** 769,772 ****
--- 792,863 ----
  }
  
+ static cairo_surface_t *
+ _cairo_ft_font_create_glyph (void *abstract_font,
+ 			     const cairo_glyph_t *glyph,
+ 			     cairo_glyph_size_t *return_size)
+ {
+     cairo_ft_font_t *font = abstract_font;
+     cairo_image_surface_t *image;
+     FT_GlyphSlot glyphslot;
+     unsigned int width, height, stride;
+     FT_Outline *outline;
+     FT_BBox cbox;
+     FT_Bitmap bitmap;
+     
+     glyphslot = font->face->glyph;
+     _install_font_matrix (&font->base.matrix, font->face);
+ 
+     FT_Load_Glyph (font->face, glyph->index, FT_LOAD_DEFAULT);
+ 
+     outline = &glyphslot->outline;
+     
+     FT_Outline_Get_CBox (outline, &cbox);
+ 
+     cbox.xMin &= -64;
+     cbox.yMin &= -64;
+     cbox.xMax = (cbox.xMax + 63) & -64;
+     cbox.yMax = (cbox.yMax + 63) & -64;
+ 
+     width = (unsigned int) ((cbox.xMax - cbox.xMin) >> 6);
+     height = (unsigned int) ((cbox.yMax - cbox.yMin) >> 6);
+     stride = (width + 3) & -4;
+     
+     bitmap.pixel_mode = ft_pixel_mode_grays;
+     bitmap.num_grays  = 256;
+     bitmap.width = width;
+     bitmap.rows = height;
+     bitmap.pitch = stride;
+     
+     if (width * height == 0) 
+ 	return NULL;
+     
+     bitmap.buffer = malloc (stride * height);
+     if (bitmap.buffer == NULL)
+ 	return NULL;
+ 	
+     memset (bitmap.buffer, 0x0, stride * height);
+ 
+     FT_Outline_Translate (outline, -cbox.xMin, -cbox.yMin);
+     FT_Outline_Get_Bitmap (glyphslot->library, outline, &bitmap);
+     
+     image = (cairo_image_surface_t *)
+ 	cairo_image_surface_create_for_data ((char *) bitmap.buffer,
+ 					     CAIRO_FORMAT_A8,
+ 					     width, height, stride);
+     if (image == NULL) {
+ 	free (bitmap.buffer);
+ 	return NULL;
+     }
+ 
+     _cairo_image_surface_assume_ownership_of_data (image);
+ 
+     return_size->width = (unsigned short) width;
+     return_size->height = (unsigned short) height;
+     return_size->x = (short) (cbox.xMin >> 6);
+     return_size->y = (short) (cbox.yMax >> 6);
+     
+     return &image->base;
+ }
+ 
  const struct cairo_font_backend cairo_ft_font_backend = {
      _cairo_ft_font_create,
***************
*** 776,782 ****
--- 867,876 ----
      _cairo_ft_font_text_extents,
      _cairo_ft_font_glyph_extents,
+     _cairo_ft_font_text_bbox,
+     _cairo_ft_font_glyph_bbox,
      _cairo_ft_font_show_text,
      _cairo_ft_font_show_glyphs,
      _cairo_ft_font_text_path,
      _cairo_ft_font_glyph_path,
+     _cairo_ft_font_create_glyph
  };

Index: cairo_gl_surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_gl_surface.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -C2 -d -r1.8 -r1.9
*** a/cairo_gl_surface.c	11 May 2004 12:31:16 -0000	1.8
--- b/cairo_gl_surface.c	24 May 2004 09:28:05 -0000	1.9
***************
*** 322,325 ****
--- 322,326 ----
  _cairo_gl_surface_create_similar (void *abstract_src,
  				  cairo_format_t format,
+ 				  int drawable,
  				  int width,
  				  int height)
***************
*** 328,334 ****
      glitz_surface_t *surface;
      cairo_surface_t *crsurface;
  
!     surface = glitz_surface_create_similar (src->surface,
! 					    _glitz_format (format),
  					    width, height);
      if (surface == NULL)
--- 329,346 ----
      glitz_surface_t *surface;
      cairo_surface_t *crsurface;
+     glitz_format_t *glitz_format;
+     unsigned long option_mask;
+     
+     option_mask = GLITZ_FORMAT_OPTION_OFFSCREEN_MASK;
+     if (!drawable)
+ 	option_mask |= GLITZ_FORMAT_OPTION_READONLY_MASK;
+     
+     glitz_format =
+ 	glitz_surface_find_similar_standard_format (src->surface, option_mask,
+ 						    _glitz_format (format));
+     if (glitz_format == NULL)
+ 	return NULL;
  
!     surface = glitz_surface_create_similar (src->surface, glitz_format,
  					    width, height);
      if (surface == NULL)
***************
*** 353,357 ****
  
      clone = (cairo_gl_surface_t *)
!         _cairo_gl_surface_create_similar (template, format,
  					  src_image->width,
  					  src_image->height);
--- 365,369 ----
  
      clone = (cairo_gl_surface_t *)
!         _cairo_gl_surface_create_similar (template, format, 0,
  					  src_image->width,
  					  src_image->height);

Index: cairo_gstate.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_gstate.c,v
retrieving revision 1.51
retrieving revision 1.52
diff -C2 -d -r1.51 -r1.52
*** a/cairo_gstate.c	20 May 2004 23:42:56 -0000	1.51
--- b/cairo_gstate.c	24 May 2004 09:28:05 -0000	1.52
***************
*** 2090,2095 ****
      cairo_matrix_t saved_font_matrix;
      cairo_pattern_t pattern;
!     cairo_text_extents_t text_extents;
!     cairo_box_t extents;
  
      status = _cairo_path_current_point (&gstate->path, &point);
--- 2090,2094 ----
      cairo_matrix_t saved_font_matrix;
      cairo_pattern_t pattern;
!     cairo_box_t bbox;
  
      status = _cairo_path_current_point (&gstate->path, &point);
***************
*** 2108,2122 ****
      _cairo_pattern_init_copy (&pattern, gstate->pattern);
      
!     status = _cairo_gstate_text_extents (gstate, utf8, &text_extents);
      if (status)
  	return status;
      
!     extents.p1.x = _cairo_fixed_from_double (x);
!     extents.p1.y = _cairo_fixed_from_double (y);
!     extents.p2.x = _cairo_fixed_from_double (x + text_extents.width);
!     extents.p2.y = _cairo_fixed_from_double (y + text_extents.height);
!     status = _cairo_gstate_create_pattern (gstate, &pattern, &extents);
      if (status)
  	return status;
      if (gstate->clip.surface)
      {
--- 2107,2119 ----
      _cairo_pattern_init_copy (&pattern, gstate->pattern);
      
!     status = _cairo_font_text_bbox (gstate->font, gstate->surface,
!  				    x, y, utf8, &bbox);
      if (status)
  	return status;
      
!     status = _cairo_gstate_create_pattern (gstate, &pattern, &bbox);
      if (status)
  	return status;
+     
      if (gstate->clip.surface)
      {
***************
*** 2134,2138 ****
  	status = _cairo_font_show_text (gstate->font,
  					CAIRO_OPERATOR_ADD, pattern.source,
! 					intermediate, 
  					x - gstate->clip.x, 
  					y - gstate->clip.y, utf8);
--- 2131,2137 ----
  	status = _cairo_font_show_text (gstate->font,
  					CAIRO_OPERATOR_ADD, pattern.source,
! 					intermediate,
! 					gstate->clip.x - pattern.source_offset.x,
! 					gstate->clip.y - pattern.source_offset.y,
  					x - gstate->clip.x, 
  					y - gstate->clip.y, utf8);
***************
*** 2173,2177 ****
  	status = _cairo_font_show_text (gstate->font,
  					gstate->operator, pattern.source,
! 					gstate->surface, x, y, utf8);
      }
      
--- 2172,2179 ----
  	status = _cairo_font_show_text (gstate->font,
  					gstate->operator, pattern.source,
! 					gstate->surface,
! 					-pattern.source_offset.x,
! 					-pattern.source_offset.y,
! 					x, y, utf8);
      }
      
***************
*** 2193,2198 ****
      cairo_glyph_t *transformed_glyphs = NULL;
      cairo_pattern_t pattern;
!     cairo_text_extents_t text_extents;
!     cairo_box_t extents;
  
      transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t));
--- 2195,2199 ----
      cairo_glyph_t *transformed_glyphs = NULL;
      cairo_pattern_t pattern;
!     cairo_box_t bbox;
  
      transformed_glyphs = malloc (num_glyphs * sizeof(cairo_glyph_t));
***************
*** 2212,2227 ****
  
      _cairo_pattern_init_copy (&pattern, gstate->pattern);
!     status = _cairo_gstate_glyph_extents (gstate, transformed_glyphs, num_glyphs,
! 					  &text_extents);
      if (status)
  	return status;
  
!     extents.p1.x = _cairo_fixed_from_double (transformed_glyphs[0].x);
!     extents.p1.y = _cairo_fixed_from_double (transformed_glyphs[0].y);
!     extents.p2.x = _cairo_fixed_from_double (transformed_glyphs[0].x +
! 					     text_extents.width);
!     extents.p2.y = _cairo_fixed_from_double (transformed_glyphs[0].y +
! 					     text_extents.height);
!     status = _cairo_gstate_create_pattern (gstate, &pattern, &extents);
      if (status)
  	return status;
--- 2213,2222 ----
  
      _cairo_pattern_init_copy (&pattern, gstate->pattern);
!     status = _cairo_font_glyph_bbox (gstate->font, gstate->surface,
!  				     transformed_glyphs, num_glyphs, &bbox);
      if (status)
  	return status;
  
!     status = _cairo_gstate_create_pattern (gstate, &pattern, &bbox);
      if (status)
  	return status;
***************
*** 2250,2253 ****
--- 2245,2250 ----
  					  CAIRO_OPERATOR_ADD, 
  					  pattern.source, intermediate,
+ 					  gstate->clip.x - pattern.source_offset.x,
+ 					  gstate->clip.y - pattern.source_offset.y,
  					  transformed_glyphs, num_glyphs);
  
***************
*** 2288,2291 ****
--- 2285,2290 ----
  					  gstate->operator, pattern.source,
  					  gstate->surface,
+ 					  -pattern.source_offset.x,
+ 					  -pattern.source_offset.y,
  					  transformed_glyphs, num_glyphs);
      }

Index: cairo_image_surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_image_surface.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -C2 -d -r1.11 -r1.12
*** a/cairo_image_surface.c	16 Apr 2004 15:33:20 -0000	1.11
--- b/cairo_image_surface.c	24 May 2004 09:28:05 -0000	1.12
***************
*** 180,183 ****
--- 180,184 ----
  _cairo_image_surface_create_similar (void		*abstract_src,
  				     cairo_format_t	format,
+ 				     int		drawable,
  				     int		width,
  				     int		height)

Index: cairo_png_surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_png_surface.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -C2 -d -r1.6 -r1.7
*** a/cairo_png_surface.c	4 May 2004 19:00:22 -0000	1.6
--- b/cairo_png_surface.c	24 May 2004 09:28:05 -0000	1.7
***************
*** 83,86 ****
--- 83,87 ----
  _cairo_png_surface_create_similar (void		*abstract_src,
  				   cairo_format_t	format,
+ 				   int		drawable,
  				   int		width,
  				   int		height)

Index: cairo_ps_surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_ps_surface.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -C2 -d -r1.9 -r1.10
*** a/cairo_ps_surface.c	6 Apr 2004 16:36:12 -0000	1.9
--- b/cairo_ps_surface.c	24 May 2004 09:28:05 -0000	1.10
***************
*** 140,143 ****
--- 140,144 ----
  _cairo_ps_surface_create_similar (void		*abstract_src,
  				 cairo_format_t	format,
+ 				 int		drawable,
  				 int		width,
  				 int		height)

Index: cairo_surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_surface.c,v
retrieving revision 1.30
retrieving revision 1.31
diff -C2 -d -r1.30 -r1.31
*** a/cairo_surface.c	11 May 2004 18:20:06 -0000	1.30
--- b/cairo_surface.c	24 May 2004 09:28:05 -0000	1.31
***************
*** 55,58 ****
--- 55,78 ----
  
  cairo_surface_t *
+ _cairo_surface_create_similar_scratch (cairo_surface_t	*other,
+ 				       cairo_format_t	format,
+ 				       int		drawable,
+ 				       int		width,
+ 				       int		height)
+ {
+     cairo_surface_t *surface;
+     
+     if (other == NULL)
+ 	return NULL;
+ 
+     surface = other->backend->create_similar (other, format, drawable,
+ 					      width, height);
+     if (surface == NULL)
+ 	surface = cairo_image_surface_create (format, width, height);
+ 
+     return surface;
+ }
+ 
+ cairo_surface_t *
  cairo_surface_create_similar (cairo_surface_t	*other,
  			      cairo_format_t	format,
***************
*** 80,89 ****
  {
      cairo_status_t status;
!     cairo_surface_t *surface = NULL;
! 
!     surface = other->backend->create_similar (other, format, width, height);
!     if (surface == NULL)
! 	surface = cairo_image_surface_create (format, width, height);
  
      status = _cairo_surface_fill_rectangle (surface,
  					    CAIRO_OPERATOR_SRC, color,
--- 100,107 ----
  {
      cairo_status_t status;
!     cairo_surface_t *surface;
  
+     surface = _cairo_surface_create_similar_scratch (other, format, 1,
+ 						     width, height);
      status = _cairo_surface_fill_rectangle (surface,
  					    CAIRO_OPERATOR_SRC, color,

Index: cairo_xcb_surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_xcb_surface.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -C2 -d -r1.4 -r1.5
*** a/cairo_xcb_surface.c	6 Apr 2004 16:36:12 -0000	1.4
--- b/cairo_xcb_surface.c	24 May 2004 09:28:05 -0000	1.5
***************
*** 232,235 ****
--- 232,236 ----
  _cairo_xcb_surface_create_similar (void		*abstract_src,
  				    cairo_format_t	format,
+ 				    int			drawable,
  				    int			width,
  				    int			height)
***************
*** 509,513 ****
  
      clone = (cairo_xcb_surface_t *)
! 	_cairo_xcb_surface_create_similar (template, format,
  					    src_image->width,
  					    src_image->height);
--- 510,514 ----
  
      clone = (cairo_xcb_surface_t *)
! 	_cairo_xcb_surface_create_similar (template, format, 0,
  					    src_image->width,
  					    src_image->height);

Index: cairo_xlib_surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo_xlib_surface.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -C2 -d -r1.20 -r1.21
*** a/cairo_xlib_surface.c	20 May 2004 23:42:56 -0000	1.20
--- b/cairo_xlib_surface.c	24 May 2004 09:28:05 -0000	1.21
***************
*** 112,115 ****
--- 112,116 ----
  _cairo_xlib_surface_create_similar (void		*abstract_src,
  				    cairo_format_t	format,
+ 				    int			drawable,
  				    int			width,
  				    int			height)
***************
*** 383,387 ****
  
      clone = (cairo_xlib_surface_t *)
! 	_cairo_xlib_surface_create_similar (template, format,
  					    src_image->width,
  					    src_image->height);
--- 384,388 ----
  
      clone = (cairo_xlib_surface_t *)
! 	_cairo_xlib_surface_create_similar (template, format, 0,
  					    src_image->width,
  					    src_image->height);

Index: cairoint.h
===================================================================
RCS file: /cvs/cairo/cairo/src/cairoint.h,v
retrieving revision 1.63
retrieving revision 1.64
diff -C2 -d -r1.63 -r1.64
*** a/cairoint.h	20 May 2004 23:42:56 -0000	1.63
--- b/cairoint.h	24 May 2004 09:28:05 -0000	1.64
***************
*** 158,162 ****
      short x, y;
      unsigned short width, height;
! } cairo_rectangle_t;
  
  /* Sure wish C had a real enum type so that this would be distinct
--- 158,162 ----
      short x, y;
      unsigned short width, height;
! } cairo_rectangle_t, cairo_glyph_size_t;
  
  /* Sure wish C had a real enum type so that this would be distinct
***************
*** 275,278 ****
--- 275,291 ----
  				      int			num_glyphs,
  				      cairo_text_extents_t	*extents);
+ 
+     cairo_status_t (*text_bbox)      (void			*font,
+ 				      cairo_surface_t		*surface,
+ 				      double			x,
+ 				      double			y,
+ 				      const unsigned char	*utf8,
+ 				      cairo_box_t		*bbox);
+ 
+     cairo_status_t (*glyph_bbox)    (void			*font,
+ 				     cairo_surface_t     	*surface,
+ 				     const cairo_glyph_t	*glyphs,
+ 				     int			num_glyphs,
+ 				     cairo_box_t		*bbox);
    
      cairo_status_t (*show_text)      (void			*font,
***************
*** 280,283 ****
--- 293,298 ----
  				      cairo_surface_t		*source,
  				      cairo_surface_t		*surface,
+ 				      int                       source_x,
+ 				      int                       source_y,
  				      double			x,
  				      double			y,
***************
*** 288,291 ****
--- 303,308 ----
  				      cairo_surface_t		*source,
  				      cairo_surface_t     	*surface,
+ 				      int                       source_x,
+ 				      int                       source_y,
  				      const cairo_glyph_t	*glyphs,
  				      int			num_glyphs);
***************
*** 301,304 ****
--- 318,324 ----
  				      int			num_glyphs,
  				      cairo_path_t		*path);
+     cairo_surface_t *(*create_glyph) (void			*font,
+ 				      const cairo_glyph_t	*glyph,
+ 				      cairo_glyph_size_t        *return_size);
  } cairo_font_backend_t;
  
***************
*** 312,315 ****
--- 332,336 ----
      (*create_similar)		(void			*surface,
  				 cairo_format_t		format,
+ 				 int                    drawable,
  				 int			width,
  				 int			height);
***************
*** 528,534 ****
--- 549,584 ----
  #define CAIRO_FONT_BACKEND_DEFAULT &cairo_ft_font_backend
  
+ #define CAIRO_FONT_CACHE_SIZE_DEFAULT 256
+ 
+ typedef struct {
+     unsigned long index;
+     double matrix[2][2];
+     
+     unsigned int time;
+     
+     cairo_surface_t *surface;
+     cairo_glyph_size_t size;
+ } cairo_glyph_surface_t;
+ 
+ typedef struct cairo_glyph_surface_node {
+     struct cairo_glyph_surface_node *next;
+     struct cairo_glyph_surface_node *prev;
+     
+     cairo_glyph_surface_t s;
+ } cairo_glyph_surface_node_t;
+ 
+ typedef struct {
+     cairo_glyph_surface_node_t *first;
+     cairo_glyph_surface_node_t *last;
+     unsigned int n_nodes;
+     
+     unsigned int ref_count;
+     unsigned int cache_size;
+ } cairo_glyph_cache_t;
+ 
  struct cairo_font {
      int refcount;
      cairo_matrix_t matrix;
+     cairo_glyph_cache_t *glyph_cache;
      const struct cairo_font_backend *backend;
  };
***************
*** 978,985 ****
--- 1028,1052 ----
  
  extern cairo_status_t __internal_linkage
+ _cairo_font_text_bbox (cairo_font_t             *font,
+                        cairo_surface_t          *surface,
+                        double                   x,
+                        double                   y,
+                        const unsigned char      *utf8,
+ 		       cairo_box_t		*bbox);
+ 
+ extern cairo_status_t __internal_linkage
+ _cairo_font_glyph_bbox (cairo_font_t            *font,
+ 			cairo_surface_t         *surface,
+ 			cairo_glyph_t           *glyphs,
+ 			int                     num_glyphs,
+ 			cairo_box_t		*bbox);
+ 
+ extern cairo_status_t __internal_linkage
  _cairo_font_show_text (cairo_font_t             *font,
                         cairo_operator_t         operator,
                         cairo_surface_t          *source,
                         cairo_surface_t          *surface,
+ 		       int                      source_x,
+ 		       int                      source_y,
                         double                   x,
                         double                   y,
***************
*** 992,995 ****
--- 1059,1064 ----
                           cairo_surface_t        *source,
                           cairo_surface_t        *surface,
+ 			 int                    source_x,
+ 			 int                    source_y,
                           cairo_glyph_t          *glyphs,
                           int                    num_glyphs);
***************
*** 1009,1012 ****
--- 1078,1087 ----
                          cairo_path_t            *path);
  
+ extern cairo_surface_t *__internal_linkage
+ _cairo_font_lookup_glyph (cairo_font_t          *font,
+ 			  cairo_surface_t       *surface,
+ 			  const cairo_glyph_t   *glyph,
+ 			  cairo_glyph_size_t    *return_size);
+ 
  /* cairo_hull.c */
  extern cairo_status_t
***************
*** 1088,1091 ****
--- 1163,1173 ----
  /* cairo_surface.c */
  extern cairo_surface_t * __internal_linkage
+ _cairo_surface_create_similar_scratch (cairo_surface_t	*other,
+ 				       cairo_format_t	format,
+ 				       int		drawable,
+ 				       int		width,
+ 				       int		height);
+ 
+ extern cairo_surface_t * __internal_linkage
  _cairo_surface_create_similar_solid (cairo_surface_t	*other,
  				     cairo_format_t	format,





More information about the cairo-commit mailing list