summaryrefslogtreecommitdiff
path: root/framebuffer
diff options
context:
space:
mode:
authorVincent Sanders <vince@netsurf-browser.org>2009-02-26 10:50:00 +0000
committerVincent Sanders <vince@netsurf-browser.org>2009-02-26 10:50:00 +0000
commit743f722bcb3eb639230cd7c1006199534f4ba2b3 (patch)
treee472bb0ddc7c609e3ff482cf2f160889d6259080 /framebuffer
parentcaf41b6b19b816a94ff52bfe0626e1e7dd906e24 (diff)
downloadnetsurf-743f722bcb3eb639230cd7c1006199534f4ba2b3.tar.gz
netsurf-743f722bcb3eb639230cd7c1006199534f4ba2b3.tar.bz2
cache freetype glyphs, massive reduction in cpu requirement
svn path=/trunk/netsurf/; revision=6622
Diffstat (limited to 'framebuffer')
-rw-r--r--framebuffer/fb_16bpp_plotters.c46
-rw-r--r--framebuffer/fb_32bpp_plotters.c45
-rw-r--r--framebuffer/fb_font.h3
-rw-r--r--framebuffer/fb_font_freetype.c152
4 files changed, 144 insertions, 102 deletions
diff --git a/framebuffer/fb_16bpp_plotters.c b/framebuffer/fb_16bpp_plotters.c
index 2eaaa11dc..2fa98ce7d 100644
--- a/framebuffer/fb_16bpp_plotters.c
+++ b/framebuffer/fb_16bpp_plotters.c
@@ -270,37 +270,33 @@ static bool fb_16bpp_text(int x, int y, const struct css_style *style,
{
uint32_t ucs4;
size_t nxtchr = 0;
- FT_UInt glyph_index;
- FT_Face face = fb_get_face(style);
- FT_Error error;
+ FT_Glyph glyph;
+ FT_BitmapGlyph bglyph;
while (nxtchr < length) {
ucs4 = utf8_to_ucs4(text + nxtchr, length - nxtchr);
nxtchr = utf8_next(text, length, nxtchr);
- glyph_index = FT_Get_Char_Index(face, ucs4);
-
- error = FT_Load_Glyph(face,
- glyph_index,
- FT_LOAD_RENDER |
- FT_LOAD_FORCE_AUTOHINT |
- ft_load_type);
- if (error)
- continue;
- /* now, draw to our target surface */
- if (face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) {
- fb_16bpp_draw_ft_monobitmap( &face->glyph->bitmap,
- x + face->glyph->bitmap_left,
- y - face->glyph->bitmap_top,
- c);
- } else {
- fb_16bpp_draw_ft_bitmap( &face->glyph->bitmap,
- x + face->glyph->bitmap_left,
- y - face->glyph->bitmap_top,
- c);
+ glyph = fb_getglyph(style, ucs4);
+ if (glyph == NULL)
+ continue;
+ if (glyph->format == FT_GLYPH_FORMAT_BITMAP) {
+ bglyph = (FT_BitmapGlyph)glyph;
+
+ /* now, draw to our target surface */
+ if (bglyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) {
+ fb_16bpp_draw_ft_monobitmap(&bglyph->bitmap,
+ x + bglyph->left,
+ y - bglyph->top,
+ c);
+ } else {
+ fb_16bpp_draw_ft_bitmap(&bglyph->bitmap,
+ x + bglyph->left,
+ y - bglyph->top,
+ c);
+ }
}
-
- x += face->glyph->advance.x >> 6;
+ x += glyph->advance.x >> 16;
}
return true;
diff --git a/framebuffer/fb_32bpp_plotters.c b/framebuffer/fb_32bpp_plotters.c
index 1950ff30b..1237f01a0 100644
--- a/framebuffer/fb_32bpp_plotters.c
+++ b/framebuffer/fb_32bpp_plotters.c
@@ -324,37 +324,34 @@ static bool fb_32bpp_text(int x, int y, const struct css_style *style,
{
uint32_t ucs4;
size_t nxtchr = 0;
- FT_UInt glyph_index;
- FT_Face face = fb_get_face(style);
- FT_Error error;
+ FT_Glyph glyph;
+ FT_BitmapGlyph bglyph;
while (nxtchr < length) {
ucs4 = utf8_to_ucs4(text + nxtchr, length - nxtchr);
nxtchr = utf8_next(text, length, nxtchr);
- glyph_index = FT_Get_Char_Index(face, ucs4);
-
- error = FT_Load_Glyph(face,
- glyph_index,
- FT_LOAD_RENDER |
- FT_LOAD_FORCE_AUTOHINT |
- ft_load_type);
- if (error)
+
+ glyph = fb_getglyph(style, ucs4);
+ if (glyph == NULL)
continue;
- /* now, draw to our target surface */
- if (face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) {
- fb_32bpp_draw_ft_monobitmap( &face->glyph->bitmap,
- x + face->glyph->bitmap_left,
- y - face->glyph->bitmap_top,
- c);
- } else {
- fb_32bpp_draw_ft_bitmap( &face->glyph->bitmap,
- x + face->glyph->bitmap_left,
- y - face->glyph->bitmap_top,
- c);
+ if (glyph->format == FT_GLYPH_FORMAT_BITMAP) {
+ bglyph = (FT_BitmapGlyph)glyph;
+
+ /* now, draw to our target surface */
+ if (bglyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) {
+ fb_32bpp_draw_ft_monobitmap(&bglyph->bitmap,
+ x + bglyph->left,
+ y - bglyph->top,
+ c);
+ } else {
+ fb_32bpp_draw_ft_bitmap(&bglyph->bitmap,
+ x + bglyph->left,
+ y - bglyph->top,
+ c);
+ }
}
-
- x += face->glyph->advance.x >> 6;
+ x += glyph->advance.x >> 16;
}
return true;
diff --git a/framebuffer/fb_font.h b/framebuffer/fb_font.h
index cd32e5193..df29db2c1 100644
--- a/framebuffer/fb_font.h
+++ b/framebuffer/fb_font.h
@@ -26,8 +26,9 @@ bool fb_font_finalise(void);
#include <ft2build.h>
#include FT_FREETYPE_H
+#include <freetype/ftglyph.h>
-FT_Face fb_get_face(const struct css_style *style);
+FT_Glyph fb_getglyph(const struct css_style *style, uint32_t ucs4);
extern int ft_load_type;
diff --git a/framebuffer/fb_font_freetype.c b/framebuffer/fb_font_freetype.c
index fbc3dc339..b4d320126 100644
--- a/framebuffer/fb_font_freetype.c
+++ b/framebuffer/fb_font_freetype.c
@@ -20,6 +20,8 @@
#include <inttypes.h>
#include <assert.h>
+#include <freetype/ftcache.h>
+
#include "css/css.h"
#include "render/font.h"
#include "desktop/options.h"
@@ -30,10 +32,22 @@
#include "framebuffer/fb_font.h"
static FT_Library library;
-static FT_Face face_sans_serif;
+static FTC_Manager ft_cmanager;
+static FTC_CMapCache ft_cmap_cache ;
+static FTC_ImageCache ft_image_cache;
int ft_load_type;
+/* cache manager faceID data to create freetype faceid on demand */
+typedef struct fb_faceid_s {
+ char *fontfile; /* path to font */
+ int index; /* index of font */
+} fb_faceid_t;
+
+
+static fb_faceid_t *fb_face_sans_serif; /* global default face */
+
+
utf8_convert_ret utf8_to_local_encoding(const char *string,
size_t len,
char **result)
@@ -41,33 +55,66 @@ utf8_convert_ret utf8_to_local_encoding(const char *string,
return utf8_to_enc(string, "UTF-8", len, result);
}
+/* map cache manager handle to face id */
+static FT_Error ft_face_requester(FTC_FaceID face_id, FT_Library library, FT_Pointer request_data, FT_Face *face )
+{
+ FT_Error error;
+ fb_faceid_t *fb_face = (fb_faceid_t *)face_id;
+
+ error = FT_New_Face(library, fb_face->fontfile, fb_face->index, face);
+ if (error) {
+ LOG(("Could not find font (code %d)\n", error));
+ }
+
+ LOG(("Loaded face from %s\n", fb_face->fontfile));
+
+ return error;
+}
+
+static fb_faceid_t *
+fb_new_face(const char *fontfile)
+{
+ fb_faceid_t *newf;
+ newf = calloc(1, sizeof(fb_faceid_t));
+ newf->fontfile=strdup(fontfile);
+ return newf;
+}
/* initialise font handling */
bool fb_font_init(void)
{
FT_Error error;
+ FT_Face aface;
+ /* freetype library initialise */
error = FT_Init_FreeType( &library );
if (error) {
LOG(("Freetype could not initialised (code %d)\n", error));
return false;
}
- error = FT_New_Face(library,
- "/usr/share/fonts/truetype/ttf-bitstream-vera/Vera.ttf",
- 0,
- &face_sans_serif );
+ /* cache manager initialise */
+ error = FTC_Manager_New(library, 0, 0, 0, ft_face_requester, NULL, &ft_cmanager);
if (error) {
- LOG(("Could not find default font (code %d)\n", error));
+ LOG(("Freetype could not initialise cache manager (code %d)\n", error));
FT_Done_FreeType(library);
return false;
}
-
- error = FT_Set_Pixel_Sizes(face_sans_serif, 0, 14 );
+
+ error = FTC_CMapCache_New(ft_cmanager, &ft_cmap_cache);
+
+ error = FTC_ImageCache_New(ft_cmanager, &ft_image_cache);
+
+
+ fb_face_sans_serif = fb_new_face("/usr/share/fonts/truetype/ttf-bitstream-vera/Vera.ttf");
+
+ error = FTC_Manager_LookupFace(ft_cmanager, (FTC_FaceID)fb_face_sans_serif, &aface);
if (error) {
- LOG(("Could not set pixel size (code %d)\n", error));
+ LOG(("Could not find default font (code %d)\n", error));
+ FT_Done_FreeType(library);
return false;
- }
+ }
+
/* set the default render mode */
//ft_load_type = FT_LOAD_MONOCHROME; /* faster but less pretty */
@@ -82,35 +129,47 @@ bool fb_font_finalise(void)
return true;
}
+static void fb_fill_scalar(const struct css_style *style, FTC_Scaler srec)
+{
+ srec->face_id = (FTC_FaceID)fb_face_sans_serif; /* should derive from style */
+ if (style->font_size.value.length.unit == CSS_UNIT_PX) {
+ srec->width = srec->height = style->font_size.value.length.value;
+ srec->pixel = 1;
+ } else {
+ srec->width = srec->height =
+ css_len2pt(&style->font_size.value.length, style) * 64;
+ srec->pixel = 0;
+ srec->x_res = srec->y_res = 72;
+ }
-FT_Face
-fb_get_face(const struct css_style *style)
+}
+
+FT_Glyph fb_getglyph(const struct css_style *style, uint32_t ucs4)
{
- FT_Face face;
- face = face_sans_serif;
+ FT_UInt glyph_index;
+ FTC_ScalerRec srec;
+ FT_Glyph glyph;
FT_Error error;
- int size;
- if (style->font_size.value.length.unit == CSS_UNIT_PX) {
- size = style->font_size.value.length.value;
+ fb_fill_scalar(style, &srec);
- error = FT_Set_Pixel_Sizes(face_sans_serif, 0, size );
- if (error) {
- LOG(("Could not set pixel size (code %d)\n", error));
- }
- } else {
- size = css_len2pt(&style->font_size.value.length, style);
- error = FT_Set_Char_Size( face, 0, size*64, 72, 72 );
- if (error) {
- LOG(("Could not set pixel size (code %d)\n", error));
- }
- }
+ glyph_index = FTC_CMapCache_Lookup(ft_cmap_cache, srec.face_id, 0, ucs4);
+ error = FTC_ImageCache_LookupScaler(ft_image_cache,
+ &srec,
+ FT_LOAD_RENDER |
+ FT_LOAD_FORCE_AUTOHINT |
+ ft_load_type,
+ glyph_index,
+ &glyph,
+ NULL);
- return face;
+ LOG(("Returning glyph %p for index %d advance %d", glyph, glyph_index,glyph->advance.x>>16));
+ return glyph;
}
+
/**
* Measure the width of a string.
*
@@ -127,21 +186,18 @@ static bool nsfont_width(const struct css_style *style,
{
uint32_t ucs4;
size_t nxtchr = 0;
- FT_UInt glyph_index;
- FT_Face face = fb_get_face(style);
- FT_Error error;
+ FT_Glyph glyph;
*width = 0;
while (nxtchr < length) {
ucs4 = utf8_to_ucs4(string + nxtchr, length - nxtchr);
nxtchr = utf8_next(string, length, nxtchr);
- glyph_index = FT_Get_Char_Index(face, ucs4);
- error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
- if (error)
+ glyph = fb_getglyph(style, ucs4);
+ if (glyph == NULL)
continue;
- *width += face->glyph->advance.x >> 6;
+ *width += glyph->advance.x >> 16;
}
return true;
@@ -166,20 +222,17 @@ static bool nsfont_position_in_string(const struct css_style *style,
{
uint32_t ucs4;
size_t nxtchr = 0;
- FT_UInt glyph_index;
- FT_Face face = fb_get_face(style);
- FT_Error error;
+ FT_Glyph glyph;
*actual_x = 0;
while (nxtchr < length) {
ucs4 = utf8_to_ucs4(string + nxtchr, length - nxtchr);
- glyph_index = FT_Get_Char_Index(face, ucs4);
- error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
- if (error)
+ glyph = fb_getglyph(style, ucs4);
+ if (glyph == NULL)
continue;
- *actual_x += face->glyph->advance.x >> 6;
+ *actual_x += glyph->advance.x >> 16;
if (*actual_x > x)
break;
@@ -214,21 +267,16 @@ static bool nsfont_split(const struct css_style *style,
{
uint32_t ucs4;
size_t nxtchr = 0;
- FT_UInt glyph_index;
- FT_Face face = fb_get_face(style);
- FT_Error error;
int last_space_x = 0;
int last_space_idx = 0;
+ FT_Glyph glyph;
*actual_x = 0;
while (nxtchr < length) {
ucs4 = utf8_to_ucs4(string + nxtchr, length - nxtchr);
-
- glyph_index = FT_Get_Char_Index(face, ucs4);
-
- error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
- if (error)
+ glyph = fb_getglyph(style, ucs4);
+ if (glyph == NULL)
continue;
if (ucs4 == 0x20) {
@@ -236,7 +284,7 @@ static bool nsfont_split(const struct css_style *style,
last_space_idx = nxtchr;
}
- *actual_x += face->glyph->advance.x >> 6;
+ *actual_x += glyph->advance.x >> 16;
if (*actual_x > x) {
/* string has exceeded available width return previous
* space