From d9b8809908be8d25b4a301529725e1df65bb610b Mon Sep 17 00:00:00 2001 From: Chris Young Date: Sun, 14 Apr 2013 16:03:46 +0100 Subject: Fix memory leak and make a point of ignoring UTF-16 surrogates --- amiga/font.c | 48 ++++++++++++++++++++++++++++++++++++++++-------- amiga/font_scan.c | 25 +++++++++++++++++++++---- amiga/font_scan.h | 2 +- 3 files changed, 62 insertions(+), 13 deletions(-) diff --git a/amiga/font.c b/amiga/font.c index 21f8b31bf..df41301d1 100755 --- a/amiga/font.c +++ b/amiga/font.c @@ -151,7 +151,7 @@ int32 ami_font_plot_glyph(struct OutlineFont *ofont, struct RastPort *rp, int32 ami_font_width_glyph(struct OutlineFont *ofont, uint16 *char1, uint16 *char2, uint32 emwidth); struct OutlineFont *ami_open_outline_font(const plot_font_style_t *fstyle, - uint16 codepoint); + uint16 *codepoint); static void ami_font_cleanup(struct MinList *ami_font_list); static bool nsfont_width(const plot_font_style_t *fstyle, @@ -220,7 +220,7 @@ bool nsfont_position_in_string(const plot_font_style_t *fstyle, *actual_x = 0; while (utf8_pos < length) { - if ((*utf16 < 0xD800) || (0xDFFF < *utf16)) + if ((*utf16 < 0xD800) || (0xDBFF < *utf16)) utf16charlen = 1; else utf16charlen = 2; @@ -231,7 +231,7 @@ bool nsfont_position_in_string(const plot_font_style_t *fstyle, if (tempx == 0) { if (ufont == NULL) - ufont = ami_open_outline_font(fstyle, *utf16); + ufont = ami_open_outline_font(fstyle, utf16); if (ufont) tempx = ami_font_width_glyph(ufont, utf16, @@ -309,7 +309,7 @@ bool nsfont_split(const plot_font_style_t *fstyle, *actual_x = 0; while (utf8_pos < length) { - if ((*utf16 < 0xD800) || (0xDFFF < *utf16)) + if ((*utf16 < 0xD800) || (0xDBFF < *utf16)) utf16charlen = 1; else utf16charlen = 2; @@ -320,7 +320,7 @@ bool nsfont_split(const plot_font_style_t *fstyle, if (tempx == 0) { if (ufont == NULL) - ufont = ami_open_outline_font(fstyle, *utf16); + ufont = ami_open_outline_font(fstyle, utf16); if (ufont) tempx = ami_font_width_glyph(ufont, utf16, @@ -432,7 +432,7 @@ struct ami_font_node *ami_font_open(const char *font) * \return outline font or NULL on error */ struct OutlineFont *ami_open_outline_font(const plot_font_style_t *fstyle, - uint16 codepoint) + uint16 *codepoint) { struct ami_font_node *node; struct OutlineFont *ofont; @@ -576,6 +576,16 @@ int32 ami_font_plot_glyph(struct OutlineFont *ofont, struct RastPort *rp, FIXED kern = 0; ULONG glyphmaptag = OT_GlyphMap8Bit; ULONG template_type = BLITT_ALPHATEMPLATE; + + if ((*char1 >= 0xD800) && (*char1 <= 0xDBFF)) { + /* We don't support UTF-16 surrogates yet, so just return. */ + return 0; + } + + if ((*char2 >= 0xD800) && (*char2 <= 0xDBFF)) { + /* Don't attempt to kern a UTF-16 surrogate */ + char2 = 0; + } if(aa == false) { glyphmaptag = OT_GlyphMap; @@ -621,6 +631,10 @@ int32 ami_font_plot_glyph(struct OutlineFont *ofont, struct RastPort *rp, EReleaseInfo(&ofont->olf_EEngine, glyphmaptag, glyph, TAG_END); + + if(char2) EReleaseInfo(&ofont->olf_EEngine, + OT_TextKernPair, kern, + TAG_END); } } @@ -636,6 +650,16 @@ int32 ami_font_width_glyph(struct OutlineFont *ofont, FIXED char1w; struct GlyphWidthEntry *gwnode; + if ((*char1 >= 0xD800) && (*char1 <= 0xDBFF)) { + /* We don't support UTF-16 surrogates yet, so just return. */ + return 0; + } + + if ((*char2 >= 0xD800) && (*char2 <= 0xDBFF)) { + /* Don't attempt to kern a UTF-16 surrogate */ + char2 = 0; + } + if(ESetInfo(&ofont->olf_EEngine, OT_GlyphCode, *char1, OT_GlyphCode2, *char1, @@ -662,6 +686,14 @@ int32 ami_font_width_glyph(struct OutlineFont *ofont, } } char_advance = (ULONG)(((char1w - kern) * emwidth) / 65536); + + if(char2) EReleaseInfo(&ofont->olf_EEngine, + OT_TextKernPair, kern, + TAG_END); + + EReleaseInfo(&ofont->olf_EEngine, + OT_WidthList, gwlist, + TAG_END); } } @@ -706,7 +738,7 @@ ULONG ami_unicode_text(struct RastPort *rp, const char *string, ULONG length, while(*utf16 != 0) { - if ((*utf16 < 0xD800) || (0xDFFF < *utf16)) + if ((*utf16 < 0xD800) || (0xDBFF < *utf16)) utf16charlen = 1; else utf16charlen = 2; @@ -740,7 +772,7 @@ ULONG ami_unicode_text(struct RastPort *rp, const char *string, ULONG length, { if(ufont == NULL) { - ufont = ami_open_outline_font(fstyle, *utf16); + ufont = ami_open_outline_font(fstyle, utf16); } if(ufont) diff --git a/amiga/font_scan.c b/amiga/font_scan.c index 83025b643..768fceef9 100644 --- a/amiga/font_scan.c +++ b/amiga/font_scan.c @@ -71,10 +71,15 @@ struct ami_font_scan_window { * \param glypharray an array of 0xffff lwc_string pointers * \return font name or NULL */ -const char *ami_font_scan_lookup(uint16 code, lwc_string **glypharray) +const char *ami_font_scan_lookup(uint16 *code, lwc_string **glypharray) { - if(glypharray[code] == NULL) return NULL; - else return lwc_string_data(glypharray[code]); + if(*code >= 0xd800 && *code <= 0xdbff) { + /* This is a multi-byte character, we don't support falback for these yet. */ + return NULL; + } + + if(glypharray[*code] == NULL) return NULL; + else return lwc_string_data(glypharray[*code]); } /** @@ -207,6 +212,7 @@ ULONG ami_font_scan_font(const char *fontname, lwc_string **glypharray) ULONG foundglyphs = 0; ULONG serif = 0; lwc_error lerror; + ULONG unicoderanges = 0; ofont = OpenOutlineFont(fontname, NULL, OFF_OPEN); @@ -219,7 +225,8 @@ ULONG ami_font_scan_font(const char *fontname, lwc_string **glypharray) TAG_END) == OTERR_Success) { if(EObtainInfo(&ofont->olf_EEngine, - OT_WidthList, &widthlist, TAG_END) == 0) + OT_WidthList, &widthlist, + TAG_END) == 0) { gwnode = (struct GlyphWidthEntry *)GetHead((struct List *)widthlist); do { @@ -229,9 +236,19 @@ ULONG ami_font_scan_font(const char *fontname, lwc_string **glypharray) foundglyphs++; } } while(gwnode = (struct GlyphWidthEntry *)GetSucc((struct Node *)gwnode)); + EReleaseInfo(&ofont->olf_EEngine, + OT_WidthList, widthlist, + TAG_END); } } + if(EObtainInfo(&ofont->olf_EEngine, OT_UnicodeRanges, &unicoderanges, TAG_END) == 0) { + if(unicoderanges & UCR_SURROGATES) LOG(("%s supports UTF-16 surrogates", fontname)); + EReleaseInfo(&ofont->olf_EEngine, + OT_UnicodeRanges, unicoderanges, + TAG_END); + } + CloseOutlineFont(ofont, NULL); return foundglyphs; diff --git a/amiga/font_scan.h b/amiga/font_scan.h index 24649854c..840f200e1 100755 --- a/amiga/font_scan.h +++ b/amiga/font_scan.h @@ -25,6 +25,6 @@ void ami_font_scan_init(const char *filename, bool force_scan, bool save, lwc_string **glypharray); void ami_font_scan_fini(lwc_string **glypharray); void ami_font_scan_save(const char *filename, lwc_string **glypharray); -const char *ami_font_scan_lookup(uint16 code, lwc_string **glypharray); +const char *ami_font_scan_lookup(uint16 *code, lwc_string **glypharray); #endif -- cgit v1.2.3