Author: fejj
Date: 2007-10-01 16:37:32 -0400 (Mon, 01 Oct 2007)
New Revision: 86724
Modified:
trunk/moon/src/ChangeLog
trunk/moon/src/font.cpp
Log:
2007-10-01 Jeffrey Stedfast <[EMAIL PROTECTED]>
* font.cpp: Reduced Glyph table memory usage.
Modified: trunk/moon/src/ChangeLog
===================================================================
--- trunk/moon/src/ChangeLog 2007-10-01 20:14:00 UTC (rev 86723)
+++ trunk/moon/src/ChangeLog 2007-10-01 20:37:32 UTC (rev 86724)
@@ -1,3 +1,7 @@
+2007-10-01 Jeffrey Stedfast <[EMAIL PROTECTED]>
+
+ * font.cpp: Reduced Glyph table memory usage.
+
2007-10-01 Sebastien Pouliot <[EMAIL PROTECTED]>
* brush.cpp|h: Change SetupBrush and SetupGradient signatures to
Modified: trunk/moon/src/font.cpp
===================================================================
--- trunk/moon/src/font.cpp 2007-10-01 20:14:00 UTC (rev 86723)
+++ trunk/moon/src/font.cpp 2007-10-01 20:37:32 UTC (rev 86724)
@@ -133,15 +133,21 @@
double width;
};
+struct GlyphBitmap {
+ cairo_surface_t *surface;
+ unsigned char *buffer;
+ int height;
+ int width;
+ int left;
+ int top;
+};
+
struct GlyphInfo {
uint32_t unichar;
uint32_t index;
+ GlyphMetrics metrics;
+ GlyphBitmap *bitmap;
moon_path *path;
- GlyphMetrics metrics;
- cairo_surface_t *surface;
- FT_Bitmap bitmap;
- int bitmap_left;
- int bitmap_top;
};
static const FT_Matrix invert_y = {
@@ -209,8 +215,18 @@
{
int i;
- for (i = 0; i < 256; i++)
- g_free (glyphs[i].bitmap.buffer);
+ for (i = 0; i < 256; i++) {
+ if (glyphs[i].path)
+ moon_path_destroy (glyphs[i].path);
+
+ if (glyphs[i].bitmap) {
+ if (glyphs[i].bitmap->surface)
+ cairo_surface_destroy
(glyphs[i].bitmap->surface);
+
+ g_free (glyphs[i].bitmap->buffer);
+ g_free (glyphs[i].bitmap);
+ }
+ }
g_free (glyphs);
FT_Done_Face (face);
@@ -378,12 +394,62 @@
0, /* delta */
};
+#define BITSWAP8(c) ((((c) * 0x0802LU & 0x22110LU) | ((c) * 0x8020LU &
0x88440LU)) * 0x10101LU >> 16)
+
+static void
+prepare_bitmap (GlyphInfo *glyph, FT_Bitmap *bitmap)
+{
+ int width, height, stride;
+ unsigned char *buffer, *d;
+ cairo_format_t format;
+ size_t size;
+ int count;
+
+ height = bitmap->rows;
+ width = bitmap->width;
+
+ size = bitmap->rows * bitmap->pitch;
+ buffer = glyph->bitmap->buffer = (unsigned char *) g_malloc (size);
+ memcpy (buffer, bitmap->buffer, size);
+
+ switch (bitmap->pixel_mode) {
+ case FT_PIXEL_MODE_MONO:
+ //printf ("pixel_mode is FT_PIXEL_MODE_MONO\n");
+ stride = (((width + 31) & ~31) >> 3);
+ format = CAIRO_FORMAT_A1;
+
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+ count = stride * height;
+ d = buffer;
+
+ while (count--) {
+ *d = BITSWAP8 (*d);
+ d++;
+ }
+#endif
+ break;
+ case FT_PIXEL_MODE_LCD:
+ case FT_PIXEL_MODE_LCD_V:
+ case FT_PIXEL_MODE_GRAY:
+ //printf ("pixel_mode is FT_PIXEL_MODE_GRAY\n");
+ stride = bitmap->pitch;
+ format = CAIRO_FORMAT_A8;
+ break;
+ default:
+ printf ("unknown pixel format\n");
+ return;
+ }
+
+ glyph->bitmap->surface = cairo_image_surface_create_for_data (buffer,
format, width, height, stride);
+ glyph->bitmap->height = height;
+ glyph->bitmap->width = width;
+}
+
GlyphInfo *
TextFont::GetGlyphInfo (uint32_t unichar)
{
GlyphInfo *glyph;
uint32_t index;
- size_t size;
if (unichar == 0)
return NULL;
@@ -395,16 +461,25 @@
glyph->index = FcFreeTypeCharIndex (face, unichar);
glyph->unichar = unichar;
- if (glyph->surface) {
- cairo_surface_destroy (glyph->surface);
- glyph->surface = NULL;
+ if (glyph->bitmap) {
+ if (glyph->bitmap->surface) {
+ cairo_surface_destroy (glyph->bitmap->surface);
+ glyph->bitmap->surface = NULL;
+ }
+
+ g_free (glyph->bitmap->buffer);
+ glyph->bitmap->buffer = NULL;
+
+ // Don't free the bitmap as we'll just be amlloc'ing it
again anyway
+ //g_free (glyph->bitmap);
+ //glyph->bitmap = NULL;
}
- if (glyph->path)
+ if (glyph->path) {
moon_path_destroy (glyph->path);
+ glyph->path = NULL;
+ }
- g_free (glyph->bitmap.buffer);
-
if (glyph->index > 0 && FT_Load_Glyph (face, glyph->index,
LOAD_FLAGS) == 0) {
if (FT_Render_Glyph (face->glyph,
FT_RENDER_MODE_NORMAL) != 0)
goto unavail;
@@ -413,25 +488,20 @@
glyph->path = moon_path_new (8);
FT_Outline_Transform (&face->glyph->outline,
&invert_y);
FT_Outline_Decompose (&face->glyph->outline,
&outline_funcs, glyph->path);
- memset (&glyph->bitmap, 0, sizeof
(&glyph->bitmap));
- glyph->bitmap_left = 0;
- glyph->bitmap_top = 0;
} else {
- glyph->path = NULL;
- glyph->bitmap = face->glyph->bitmap;
+ if (glyph->bitmap == NULL)
+ glyph->bitmap = g_new (GlyphBitmap, 1);
- size = face->glyph->bitmap.rows *
face->glyph->bitmap.pitch;
- glyph->bitmap.buffer = (unsigned char *)
g_malloc (size);
- memcpy (glyph->bitmap.buffer,
face->glyph->bitmap.buffer, size);
- glyph->bitmap_left = face->glyph->bitmap_left;
- glyph->bitmap_top = face->glyph->bitmap_top;
+ glyph->bitmap->left = face->glyph->bitmap_left;
+ glyph->bitmap->top = face->glyph->bitmap_top;
+ prepare_bitmap (glyph, &face->glyph->bitmap);
}
glyph->metrics.horiBearingX =
face->glyph->metrics.horiBearingX / 64.0;
glyph->metrics.horiBearingY =
face->glyph->metrics.horiBearingY / 64.0;
+ glyph->metrics.horiAdvance =
face->glyph->metrics.horiAdvance / 64.0;
glyph->metrics.vertBearingX =
face->glyph->metrics.vertBearingX / 64.0;
glyph->metrics.vertBearingY =
face->glyph->metrics.vertBearingY / 64.0;
- glyph->metrics.horiAdvance =
face->glyph->metrics.horiAdvance / 64.0;
glyph->metrics.vertAdvance =
face->glyph->metrics.vertAdvance / 64.0;
glyph->metrics.height = face->glyph->metrics.height /
64.0;
glyph->metrics.width = face->glyph->metrics.width /
64.0;
@@ -441,10 +511,12 @@
glyph->metrics.vertBearingX = 0.0;
glyph->metrics.vertBearingY = 0.0;
- glyph->path = NULL;
- memset (&glyph->bitmap, 0, sizeof (&glyph->bitmap));
- glyph->bitmap_left = 0;
- glyph->bitmap_top = 0;
+ if (glyph->bitmap) {
+ glyph->bitmap->height = 0;
+ glyph->bitmap->width = 0;
+ glyph->bitmap->left = 0;
+ glyph->bitmap->top = 0;
+ }
if (unichar == 0x20) {
// Space
@@ -461,6 +533,13 @@
}
} else {
unavail:
+ if (glyph->bitmap) {
+ glyph->bitmap->height = 0;
+ glyph->bitmap->width = 0;
+ glyph->bitmap->left = 0;
+ glyph->bitmap->top = 0;
+ }
+
glyph->metrics.horiBearingX = 0.0;
glyph->metrics.horiBearingY = 0.0;
glyph->metrics.vertBearingX = 0.0;
@@ -469,14 +548,10 @@
glyph->metrics.vertAdvance = 0.0;
glyph->metrics.height = 0.0;
glyph->metrics.width = 0.0;
- memset (&glyph->bitmap, 0, sizeof (&glyph->bitmap));
- glyph->bitmap_left = 0;
- glyph->bitmap_top = 0;
- glyph->path = NULL;
}
}
- if (glyph->metrics.horiAdvance > 0)
+ if (glyph->metrics.horiAdvance > 0.0)
return glyph;
return NULL;
@@ -495,55 +570,9 @@
return (double) (face->underline_thickness / 64);
}
-#define BITSWAP8(c) ((((c) * 0x0802LU & 0x22110LU) | ((c) * 0x8020LU &
0x88440LU)) * 0x10101LU >> 16)
-
void
TextFont::RenderGlyphBitmap (cairo_t *cr, GlyphInfo *glyph, double x, double y)
{
- int width, height, stride;
- cairo_format_t format;
- FT_Bitmap *bitmap;
- unsigned char *d;
- int count;
-
- bitmap = &glyph->bitmap;
-
- height = bitmap->rows;
- width = bitmap->width;
-
- if (!glyph->surface) {
- switch (bitmap->pixel_mode) {
- case FT_PIXEL_MODE_MONO:
- //printf ("pixel_mode is FT_PIXEL_MODE_MONO\n");
- stride = (((width + 31) & ~31) >> 3);
- format = CAIRO_FORMAT_A1;
-
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
- count = stride * height;
- d = bitmap->buffer;
-
- while (count--) {
- *d = BITSWAP8 (*d);
- d++;
- }
-#endif
- break;
- case FT_PIXEL_MODE_LCD:
- case FT_PIXEL_MODE_LCD_V:
- case FT_PIXEL_MODE_GRAY:
- //printf ("pixel_mode is FT_PIXEL_MODE_GRAY\n");
- stride = bitmap->pitch;
- format = CAIRO_FORMAT_A8;
- break;
- default:
- printf ("unknown pixel format\n");
- return;
- }
-
- glyph->surface = cairo_image_surface_create_for_data
(bitmap->buffer, format,
- width,
height, stride);
- }
-
// take horiBearingX into consideration
x += glyph->metrics.horiBearingX;
@@ -552,11 +581,11 @@
cairo_save (cr);
- cairo_mask_surface (cr, glyph->surface, x, y);
+ cairo_mask_surface (cr, glyph->bitmap->surface, x, y);
cairo_set_operator (cr, CAIRO_OPERATOR_SATURATE);
cairo_new_path (cr);
- cairo_rectangle (cr, x, y, (double) width, (double) height);
+ cairo_rectangle (cr, x, y, (double) glyph->bitmap->width, (double)
glyph->bitmap->height);
cairo_close_path (cr);
cairo_fill (cr);
_______________________________________________
Mono-patches maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches