From fb0304e2a9c99fa00e68bf4b37074a6885f19cff Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Tue, 23 Nov 2010 21:44:31 +1030 Subject: [PATCH] Document load_truetype_table function and ensure ft-font and Win32-font are compliant There were some difference between how the FT and Win32 load_truetype_table font backend functions worked due to the difference between FT_Load_Sfnt_Table() and GetFontData(). eg FT returns an error if less than the requested number of bytes could be read while Win32 returns success and sets the length to the number of bytes read. --- src/cairo-ft-font.c | 15 ++++++++++++--- src/cairo-win32-font.c | 7 +++++-- src/cairoint.h | 18 ++++++++++++++++++ 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c index 054da2523..acb712174 100644 --- a/src/cairo-ft-font.c +++ b/src/cairo-ft-font.c @@ -2370,6 +2370,11 @@ _cairo_ft_load_truetype_table (void *abstract_font, FT_Face face; cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED; + /* We don't support the FreeType feature of loading a table + * without specifying the size since this may overflow our + * buffer. */ + assert (length != NULL); + if (_cairo_ft_scaled_font_is_vertical (&scaled_font->base)) return CAIRO_INT_STATUS_UNSUPPORTED; @@ -2378,9 +2383,13 @@ _cairo_ft_load_truetype_table (void *abstract_font, if (!face) return _cairo_error (CAIRO_STATUS_NO_MEMORY); - if (FT_IS_SFNT (face) && - FT_Load_Sfnt_Table (face, tag, offset, buffer, length) == 0) - status = CAIRO_STATUS_SUCCESS; + if (FT_IS_SFNT (face)) { + if (buffer == NULL) + *length = 0; + + if (FT_Load_Sfnt_Table (face, tag, offset, buffer, length) == 0) + status = CAIRO_STATUS_SUCCESS; + } _cairo_ft_unscaled_font_unlock_face (unscaled); #endif diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c index fcd7b5601..d0c29bbda 100644 --- a/src/cairo-win32-font.c +++ b/src/cairo-win32-font.c @@ -1514,6 +1514,7 @@ _cairo_win32_scaled_font_load_truetype_table (void *abstract_font, cairo_win32_scaled_font_t *scaled_font = abstract_font; HDC hdc; cairo_status_t status; + DWORD ret; hdc = _get_global_font_dc (); assert (hdc != NULL); @@ -1523,9 +1524,11 @@ _cairo_win32_scaled_font_load_truetype_table (void *abstract_font, if (status) return status; - *length = GetFontData (hdc, tag, offset, buffer, *length); - if (*length == GDI_ERROR) + ret = GetFontData (hdc, tag, offset, buffer, *length); + if (ret == GDI_ERROR || (buffer && ret != *length)) status = CAIRO_INT_STATUS_UNSUPPORTED; + else + *length = ret; cairo_win32_scaled_font_done_font (&scaled_font->base); diff --git a/src/cairoint.h b/src/cairoint.h index 5a435618f..1510f8ec4 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -502,6 +502,24 @@ struct _cairo_scaled_font_backend { cairo_region_t *clip_region, int *remaining_glyphs); + /* Read data from a sfnt font table. + * @scaled_font: font + * @tag: 4 byte table name specifying the table to read. + * @offset: offset into the table + * @buffer: buffer to write data into. Caller must ensure there is sufficient space. + * If NULL, return the size of the table in @length. + * @length: If @buffer is NULL, the size of the table will be returned in @length. + * If @buffer is not null, @length specifies the number of bytes to read. + * + * If less than @length bytes are available to read this function + * returns CAIRO_INT_STATUS_UNSUPPORTED. Note that requesting more + * bytes than are available in the table may continue reading data + * from the following table and return success. If this is + * undesirable the caller should first query the table size. If an + * error occurs the output value of @length is undefined. + * + * Returns CAIRO_INT_STATUS_UNSUPPORTED if not a sfnt style font or table not found. + */ cairo_warn cairo_int_status_t (*load_truetype_table)(void *scaled_font, unsigned long tag,