diff --git a/ChangeLog b/ChangeLog index d431187..d1de18d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2008-04-04 Fred Kiefer + + * Source/winlib/WIN32FontInfo.m + (-appendBezierPathWithGlyphs:count:toBezierPath:): New method. + Patch by Christopher Armstrong . + * Source/art/ftfont.m, + * Source/art/ftfont-old.m: Moved ligature handling code from here + to gui. + * Source/cairo/CairoFontInfo.m (-glyphIsEncoded:): Report all + ligatures as not supported, as we have no way to determine if they + exist in the font. + 2008-04-03 Fred Kiefer * Source/cairo/CairoFontInfo.m (-appendBezierPathWithGlyphs:...): diff --git a/Source/art/ftfont-old.m b/Source/art/ftfont-old.m index 85f85ea..c09d1b2 100644 --- a/Source/art/ftfont-old.m +++ b/Source/art/ftfont-old.m @@ -34,6 +34,8 @@ #include #include #include +#include + #include #include #include @@ -105,11 +107,6 @@ static int subpixel_text; unsigned int cachedGlyph[CACHE_SIZE]; NSSize cachedSize[CACHE_SIZE]; - - /* Glyph generation */ - NSGlyph ligature_ff,ligature_fi,ligature_fl,ligature_ffl,ligature_ffi; - - float lineHeight; } @end @@ -258,24 +255,6 @@ static FT_Error ft_get_face(FTC_FaceID fid, FT_Library lib, FT_Pointer data, FT_ fontBBox.origin.x, fontBBox.origin.y, fontBBox.size.width, fontBBox.size.height);*/ - { - FTC_CMapDescRec cmap; - cmap.face_id = imgd.font.face_id; - cmap.u.encoding = ft_encoding_unicode; - cmap.type = FTC_CMAP_BY_ENCODING; - ligature_ff = FTC_CMapCache_Lookup(ftc_cmapcache, &cmap, 0xfb00); - ligature_fi = FTC_CMapCache_Lookup(ftc_cmapcache, &cmap, 0xfb01); - ligature_fl = FTC_CMapCache_Lookup(ftc_cmapcache, &cmap, 0xfb02); - ligature_ffi = FTC_CMapCache_Lookup(ftc_cmapcache, &cmap, 0xfb03); - ligature_ffl = FTC_CMapCache_Lookup(ftc_cmapcache, &cmap, 0xfb04); -/* printf("ligatures %04x %04x %04x %04x %04x | %02x %02x %02x for |%@|\n", - ligature_ff,ligature_fi,ligature_fl,ligature_ffi,ligature_ffl, - FTC_CMapCache_Lookup(ftc_cmapcache, &cmap, 'f'), - FTC_CMapCache_Lookup(ftc_cmapcache, &cmap, 'l'), - FTC_CMapCache_Lookup(ftc_cmapcache, &cmap, 'i'), - fontName);*/ - } - { float xx, yy; #ifdef FT212_STUFF @@ -362,8 +341,6 @@ static FT_Error ft_get_face(FTC_FaceID fid, FT_Library lib, FT_Pointer data, FT_ } -#include - /* TODO: the current point probably needs updating after drawing is done */ /* draw string at point, clipped, w/given color and alpha, and possible deltas: @@ -2364,6 +2341,22 @@ static int filters[3][7]= } } +-(NSGlyph) glyphForCharacter: (unichar)ch +{ + NSGlyph g; + + FTC_CMapDescRec cmap; + + cmap.face_id = imgd.font.face_id; + cmap.u.encoding = ft_encoding_unicode; + cmap.type = FTC_CMAP_BY_ENCODING; + + g = FTC_CMapCache_Lookup(ftc_cmapcache, &cmap, ch); + if (g) + return g + 1; + else + return NSNullGlyph; +} @end @@ -2748,242 +2741,6 @@ static int filters[3][7]= @end - -@interface NSFont (backend) --(NSGlyph) glyphForCharacter: (unichar)ch; --(NSString *) nameOfGlyph: (NSGlyph)glyph; -@end - -@implementation NSFont (backend) --(NSGlyph) glyphForCharacter: (unichar)ch -{ - FTFontInfo *fi=fontInfo; - NSGlyph g; - - FTC_CMapDescRec cmap; - - cmap.face_id = fi->imgd.font.face_id; - cmap.u.encoding = ft_encoding_unicode; - cmap.type = FTC_CMAP_BY_ENCODING; - - g = FTC_CMapCache_Lookup(ftc_cmapcache, &cmap, ch); - if (g) - return g + 1; - else - return NSNullGlyph; -} - --(NSString *) nameOfGlyph: (NSGlyph)glyph -{ - FTFontInfo *fi=fontInfo; - FT_Face face; - - char buf[256]; - - glyph--; - - if (FTC_Manager_Lookup_Size(ftc_manager, &fi->imgd.font, &face, 0)) - return nil; - - if (FT_Get_Glyph_Name(face,glyph,buf,sizeof(buf))) - return nil; - - return [NSString stringWithCString: buf]; /* TODO: really cstring? */ -} -@end - - -/* -GSLayoutManager glyph generation code. - -TODO: clean this up -*/ -#include -#include -#include -#include - -@implementation GSLayoutManager (backend) - -/* -This is a fairly simple implementation. It will use "ff", "fl", "fi", -"ffl", and "ffi" ligatures if available. If a glyph for a character isn't -available, it will try to decompose it before giving up. - -TODO: how should words like "pfffffffffff" be handled? - -0066 'f' -0069 'i' -006c 'l' -fb00 'ff' -fb01 'fi' -fb02 'fl' -fb03 'ffi' -fb04 'ffl' -*/ - --(unsigned int) _findSafeBreakMovingBackwardFrom: (unsigned int)ch -{ - NSString *str=[_textStorage string]; - while (ch>0 && [str characterAtIndex: ch-1]=='f') - ch--; - return ch; -} - --(unsigned int) _findSafeBreakMovingForwardFrom: (unsigned int)ch -{ - unsigned int l=[_textStorage length]; - NSString *str=[_textStorage string]; - while (ch0 && [str characterAtIndex: ch-1]=='f') - ch++; - return ch; -} - --(void) _generateGlyphsForRun: (glyph_run_t *)run at: (unsigned int)pos -{ - glyph_t *g; - unsigned int glyph_size; - unsigned int i,j; - unsigned int ch,ch2,ch3; - - FTFontInfo *fi=[run->font fontInfo]; - FTC_CMapDescRec cmap; - - NSCharacterSet *cs=[NSCharacterSet controlCharacterSet]; - IMP characterIsMember=[cs methodForSelector: @selector(characterIsMember:)]; - - unsigned int c=run->head.char_length; - unichar buf[c]; - - - [[_textStorage string] getCharacters: buf - range: NSMakeRange(pos,c)]; - - cmap.face_id = fi->imgd.font.face_id; - cmap.u.encoding = ft_encoding_unicode; - cmap.type = FTC_CMAP_BY_ENCODING; - - /* first guess */ - glyph_size=c; - g=run->glyphs=malloc(sizeof(glyph_t)*glyph_size); - memset(g,0,sizeof(glyph_t)*glyph_size); - - for (i=j=0;ichar_offset=i; - if (characterIsMember(cs,@selector(characterIsMember:),ch)) - { - g->g=NSControlGlyph; - continue; - } - - if (ch == NSAttachmentCharacter) - { - g->g=GSAttachmentGlyph; - continue; - } - - if (run->ligature>=1) - { - if (ch=='f' && ch2=='f' && ch3=='l' && fi->ligature_ffl) - { - g->g=fi->ligature_ffl + 1; - i+=2; - continue; - } - if (ch=='f' && ch2=='f' && ch3=='i' && fi->ligature_ffi) - { - g->g=fi->ligature_ffi + 1; - i+=2; - continue; - } - if (ch=='f' && ch2=='f' && fi->ligature_ff) - { - g->g=fi->ligature_ff + 1; - i++; - continue; - } - if (ch=='f' && ch2=='i' && fi->ligature_fi) - { - g->g=fi->ligature_fi + 1; - i++; - continue; - } - if (ch=='f' && ch2=='l' && fi->ligature_fl) - { - g->g=fi->ligature_fl + 1; - i++; - continue; - } - } - - if (ch>=0xd800 && ch<=0xdfff) - { - if (ch >= 0xd800 && ch < 0xdc00 && ch2 >= 0xdc00 && ch2 <= 0xdfff) - { - ch = ((ch & 0x3ff) << 10) + (ch2 & 0x3ff) + 0x10000; - i++; - } - else - ch = 0xfffd; - } - - g->g=FTC_CMapCache_Lookup(ftc_cmapcache, &cmap, ch) + 1; - - if (g->g == 1 && ch<0x10000) - { - unichar *decomp; - decomp=uni_is_decomp(ch); - if (decomp) - { - int c=0; - for (;*decomp;decomp++) - { - glyph_size++; - run->glyphs=realloc(run->glyphs,sizeof(glyph_t)*glyph_size); - g=run->glyphs+j; - memset(&run->glyphs[glyph_size-1],0,sizeof(glyph_t)); - - g->g=FTC_CMapCache_Lookup(ftc_cmapcache, &cmap, *decomp) + 1; - if (g->g == 1) - break; - c++; - g++; - j++; - g->char_offset=i; - } - if (*decomp) - { - g-=c; - j-=c; - g->g=0; - } - else - { - g--; - j--; - } - } - } - } - - /* TODO: shrink allocated array if possible */ - run->head.glyph_length=j; -} -@end - - @interface FTFontInfo (experimental_glyph_printing_extension) -(const char *) nameOfGlyph: (NSGlyph)g; @end diff --git a/Source/art/ftfont.m b/Source/art/ftfont.m index f6be12e..b5f6ad3 100644 --- a/Source/art/ftfont.m +++ b/Source/art/ftfont.m @@ -45,6 +45,8 @@ #include #include #include +#include + #include #include #include @@ -111,11 +113,6 @@ static int subpixel_text; unsigned int cachedGlyph[CACHE_SIZE]; NSSize cachedSize[CACHE_SIZE]; - - /* Glyph generation */ - NSGlyph ligature_ff,ligature_fi,ligature_fl,ligature_ffl,ligature_ffi; - - float lineHeight; } @end @@ -162,9 +159,10 @@ static FT_Error ft_get_face(FTC_FaceID fid, FT_Library lib, FT_Pointer data, FT_ @implementation FTFontInfo + - (id) initWithFontName: (NSString *)name - matrix: (const float *)fmatrix - screenFont: (BOOL)p_screenFont + matrix: (const float *)fmatrix + screenFont: (BOOL)p_screenFont { NSArray *rfi; FTFaceInfo *font_entry; @@ -251,7 +249,7 @@ static FT_Error ft_get_face(FTC_FaceID fid, FT_Library lib, FT_Pointer data, FT_ if ((error = FTC_Manager_LookupSize(ftc_manager, &scaler, &ft_size))) { NSLog(@"FTC_Manager_LookupSize() failed for '%@', error %08x!", - name, error); + name, error); return self; } @@ -291,24 +289,6 @@ static FT_Error ft_get_face(FTC_FaceID fid, FT_Library lib, FT_Pointer data, FT_ } } } - { - ligature_ff - = FTC_CMapCache_Lookup(ftc_cmapcache, faceId, unicodeCmap, 0xfb00); - ligature_fi - = FTC_CMapCache_Lookup(ftc_cmapcache, faceId, unicodeCmap, 0xfb01); - ligature_fl - = FTC_CMapCache_Lookup(ftc_cmapcache, faceId, unicodeCmap, 0xfb02); - ligature_ffi - = FTC_CMapCache_Lookup(ftc_cmapcache, faceId, unicodeCmap, 0xfb03); - ligature_ffl - = FTC_CMapCache_Lookup(ftc_cmapcache, faceId, unicodeCmap, 0xfb04); -/* printf("ligatures %04x %04x %04x %04x %04x | %02x %02x %02x for |%@|\n", - ligature_ff,ligature_fi,ligature_fl,ligature_ffi,ligature_ffl, - FTC_CMapCache_Lookup(ftc_cmapcache, &cmap, 'f'), - FTC_CMapCache_Lookup(ftc_cmapcache, &cmap, 'l'), - FTC_CMapCache_Lookup(ftc_cmapcache, &cmap, 'i'), - fontName);*/ - } if (screenFont) { @@ -429,8 +409,6 @@ static FT_Error ft_get_face(FTC_FaceID fid, FT_Library lib, FT_Pointer data, FT_ return numberOfGlyphs; } -#include - /* TODO: the current point probably needs updating after drawing is done */ /* draw string at point, clipped, w/given color and alpha, and possible deltas: @@ -2253,6 +2231,16 @@ static int filters[3][7]= } } +- (NSGlyph) glyphForCharacter: (unichar)ch +{ + NSGlyph g; + + g = FTC_CMapCache_Lookup(ftc_cmapcache, faceId, unicodeCmap, ch); + if (g) + return g + 1; + else + return NSNullGlyph; +} @end @@ -2623,233 +2611,6 @@ static int filters[3][7]= @end - -@interface NSFont (backend) -- (NSGlyph) glyphForCharacter: (unichar)ch; -- (NSString *) nameOfGlyph: (NSGlyph)glyph; -@end - -@implementation NSFont (backend) -- (NSGlyph) glyphForCharacter: (unichar)ch -{ - FTFontInfo *fi=fontInfo; - NSGlyph g; - - g = FTC_CMapCache_Lookup(ftc_cmapcache, fi->faceId, fi->unicodeCmap, ch); - if (g) - return g + 1; - else - return NSNullGlyph; -} - -- (NSString *) nameOfGlyph: (NSGlyph)glyph -{ - FTFontInfo *fi=fontInfo; - FT_Face face; - FT_Size size; - - char buf[256]; - - glyph--; - - if (FTC_Manager_LookupSize(ftc_manager, &fi->scaler, &size)) - return nil; - face = size->face; - - if (FT_Get_Glyph_Name(face,glyph,buf,sizeof(buf))) - return nil; - - return [NSString stringWithCString: buf]; /* TODO: really cstring? */ -} -@end - - -/* -GSLayoutManager glyph generation code. - -TODO: clean this up -*/ -#include -#include -#include -#include - -@implementation GSLayoutManager (backend) - -/* -This is a fairly simple implementation. It will use "ff", "fl", "fi", -"ffl", and "ffi" ligatures if available. If a glyph for a character isn't -available, it will try to decompose it before giving up. - -TODO: how should words like "pfffffffffff" be handled? - -0066 'f' -0069 'i' -006c 'l' -fb00 'ff' -fb01 'fi' -fb02 'fl' -fb03 'ffi' -fb04 'ffl' -*/ - -- (unsigned int) _findSafeBreakMovingBackwardFrom: (unsigned int)ch -{ - NSString *str=[_textStorage string]; - while (ch>0 && [str characterAtIndex: ch-1]=='f') - ch--; - return ch; -} - -- (unsigned int) _findSafeBreakMovingForwardFrom: (unsigned int)ch -{ - unsigned int l=[_textStorage length]; - NSString *str=[_textStorage string]; - while (ch0 && [str characterAtIndex: ch-1]=='f') - ch++; - return ch; -} - -- (void) _generateGlyphsForRun: (glyph_run_t *)run at: (unsigned int)pos -{ - glyph_t *g; - unsigned int glyph_size; - unsigned int i,j; - unsigned int ch,ch2,ch3; - - FTFontInfo *fi = (FTFontInfo *)[run->font fontInfo]; - - NSCharacterSet *cs = [NSCharacterSet controlCharacterSet]; - IMP characterIsMember = [cs methodForSelector: @selector(characterIsMember:)]; - - unsigned int c=run->head.char_length; - unichar buf[c]; - - - [[_textStorage string] getCharacters: buf - range: NSMakeRange(pos,c)]; - - /* first guess */ - glyph_size=c; - g=run->glyphs=malloc(sizeof(glyph_t)*glyph_size); - memset(g,0,sizeof(glyph_t)*glyph_size); - - for (i=j=0;ichar_offset=i; - if (characterIsMember(cs,@selector(characterIsMember:),ch)) - { - g->g=NSControlGlyph; - continue; - } - - if (ch == NSAttachmentCharacter) - { - g->g=GSAttachmentGlyph; - continue; - } - - if (run->ligature>=1) - { - if (ch=='f' && ch2=='f' && ch3=='l' && fi->ligature_ffl) - { - g->g=fi->ligature_ffl + 1; - i+=2; - continue; - } - if (ch=='f' && ch2=='f' && ch3=='i' && fi->ligature_ffi) - { - g->g=fi->ligature_ffi + 1; - i+=2; - continue; - } - if (ch=='f' && ch2=='f' && fi->ligature_ff) - { - g->g=fi->ligature_ff + 1; - i++; - continue; - } - if (ch=='f' && ch2=='i' && fi->ligature_fi) - { - g->g=fi->ligature_fi + 1; - i++; - continue; - } - if (ch=='f' && ch2=='l' && fi->ligature_fl) - { - g->g=fi->ligature_fl + 1; - i++; - continue; - } - } - - if (ch>=0xd800 && ch<=0xdfff) - { - if (ch >= 0xd800 && ch < 0xdc00 && ch2 >= 0xdc00 && ch2 <= 0xdfff) - { - ch = ((ch & 0x3ff) << 10) + (ch2 & 0x3ff) + 0x10000; - i++; - } - else - ch = 0xfffd; - } - - g->g=FTC_CMapCache_Lookup(ftc_cmapcache, fi->faceId, fi->unicodeCmap, ch) + 1; - - if (g->g == 1 && ch<0x10000) - { - unichar *decomp; - decomp = uni_is_decomp(ch); - if (decomp) - { - int c=0; - for (;*decomp;decomp++) - { - glyph_size++; - run->glyphs=realloc(run->glyphs,sizeof(glyph_t)*glyph_size); - g=run->glyphs+j; - memset(&run->glyphs[glyph_size-1],0,sizeof(glyph_t)); - - g->g = FTC_CMapCache_Lookup(ftc_cmapcache, fi->faceId, fi->unicodeCmap, *decomp) + 1; - if (g->g == 1) - break; - c++; - g++; - j++; - g->char_offset=i; - } - if (*decomp) - { - g-=c; - j-=c; - g->g=0; - } - else - { - g--; - j--; - } - } - } - } - - /* TODO: shrink allocated array if possible */ - run->head.glyph_length=j; -} -@end - - @interface FTFontInfo (experimental_glyph_printing_extension) - (const char *) nameOfGlyph: (NSGlyph)g; @end diff --git a/Source/cairo/CairoFontInfo.m b/Source/cairo/CairoFontInfo.m index 354ad72..b719058 100644 --- a/Source/cairo/CairoFontInfo.m +++ b/Source/cairo/CairoFontInfo.m @@ -175,8 +175,15 @@ - (BOOL) glyphIsEncoded: (NSGlyph)glyph { - /* subclass should override */ - return YES; + /* FIXME: There is no proper way to determine with the toy font API, + whether a glyph is supported or not. We will just ignore ligatures + and report all other glyph as existing. + return !NSEqualSizes([self advancementForGlyph: glyph], NSZeroSize); + */ + if ((glyph >= 0xFB00) && (glyph <= 0xFB05)) + return NO; + else + return YES; } static @@ -459,5 +466,5 @@ BOOL _cairo_extents_for_NSGlyph(cairo_scaled_font_t *scaled_font, NSGlyph glyph, cairo_status_to_string(cairo_status(ct)), str); } } - + @end diff --git a/Source/winlib/WIN32FontInfo.m b/Source/winlib/WIN32FontInfo.m index d133a5b..e947af2 100644 --- a/Source/winlib/WIN32FontInfo.m +++ b/Source/winlib/WIN32FontInfo.m @@ -29,6 +29,7 @@ #include #include #include +#include #include "winlib/WIN32FontInfo.h" @@ -80,14 +81,14 @@ NSString *win32_font_family(NSString *fontName); HDC hdc; HFONT old; - hdc = GetDC(NULL); + hdc = CreateCompatibleDC(NULL); old = SelectObject(hdc, hFont); GetTextExtentPoint32W(hdc, (const unichar*)[string cStringUsingEncoding: NSUnicodeStringEncoding], [string length], &size); SelectObject(hdc, old); - ReleaseDC(NULL, hdc); + DeleteDC(hdc); return size.cx; } @@ -105,12 +106,12 @@ NSString *win32_font_family(NSString *fontName); ABCFLOAT abc; HFONT old; - hdc = GetDC(NULL); + hdc = CreateCompatibleDC(NULL); old = SelectObject(hdc, hFont); // FIXME ... currently a gnustep glyph is a unichar ... what if that changes. GetCharABCWidthsFloatW(hdc, u, u, &abc); SelectObject(hdc, old); - ReleaseDC(NULL, hdc); + DeleteDC(hdc); //NSLog(@"Width for %d is %f or %f", glyph, w, (abc.abcfA + abc.abcfB + abc.abcfC)); w = abc.abcfA + abc.abcfB + abc.abcfC; @@ -126,13 +127,13 @@ NSString *win32_font_family(NSString *fontName); GLYPHMETRICS gm; NSRect rect; - hdc = GetDC(NULL); + hdc = CreateCompatibleDC(NULL); old = SelectObject(hdc, hFont); // Convert from GNUstep glyph (unichar) to windows glyph. if (GetGlyphIndicesW(hdc, &c, 1, &windowsGlyph, 0) == GDI_ERROR) { SelectObject(hdc, old); - ReleaseDC(NULL, hdc); + DeleteDC(hdc); NSLog(@"No glyph for U%d", c); return NSMakeRect(0, 0, 0, 0); // No such glyph } @@ -150,14 +151,30 @@ NSLog(@"No glyph for U%d", c); } SelectObject(hdc, old); - ReleaseDC(NULL, hdc); + DeleteDC(hdc); return rect; } - (BOOL) glyphIsEncoded: (NSGlyph)glyph { - return YES; + WORD c = (WORD)glyph; + WORD windowsGlyph; + HDC hdc; + HFONT old; + BOOL result = YES; + + hdc = CreateCompatibleDC(NULL); + old = SelectObject(hdc, hFont); + // Convert from GNUstep glyph (unichar) to windows glyph. + if ((GetGlyphIndicesW(hdc, &c, 1, &windowsGlyph, 0) == GDI_ERROR) + || (windowsGlyph == 0xFFFF)) + { + result = NO; + } + SelectObject(hdc, old); + DeleteDC(hdc); + return result; } - (NSGlyph) glyphWithName: (NSString*)glyphName @@ -183,7 +200,7 @@ NSLog(@"No glyph for U%d", c); HFONT old; ms = [NSMutableCharacterSet new]; - hdc = GetDC(NULL); + hdc = CreateCompatibleDC(NULL); old = SelectObject(hdc, hFont); count = (unsigned)GetFontUnicodeRanges(hdc, 0); if (count > 0) @@ -218,7 +235,7 @@ NSLog(@"No glyph for U%d", c); objc_free(gs); } SelectObject(hdc, old); - ReleaseDC(NULL, hdc); + DeleteDC(hdc); coveredCharacterSet = [ms copy]; RELEASE(ms); } @@ -227,8 +244,8 @@ NSLog(@"No glyph for U%d", c); } - (void) drawString: (NSString*)string - onDC: (HDC)hdc - at: (POINT)p + onDC: (HDC)hdc + at: (POINT)p { HFONT old; @@ -252,9 +269,9 @@ NSLog(@"No glyph for U%d", c); } - (void) drawGlyphs: (const NSGlyph*)s - length: (int)len - onDC: (HDC)hdc - at: (POINT)p + length: (int)len + onDC: (HDC)hdc + at: (POINT)p { WORD buf[len]; HFONT old; @@ -282,6 +299,117 @@ NSLog(@"No glyph for U%d", c); return numberOfGlyphs; } +- (void) appendBezierPathWithGlyphs: (NSGlyph *)glyphs + count: (int)length + toBezierPath: (NSBezierPath *)path +{ + WORD buf[length]; + int i; + SIZE sBoundBox; + int h; + int iPoints; + POINT *ptPoints; + BYTE *bTypes; + NSPoint startPoint; + HDC hDC = CreateCompatibleDC(NULL); + + if (!hDC) + { + NSDebugLLog(@"WIN32FontInfo", + @"Problem creating HDC for appendBezierPathWithGlyphs:"); + return; + } + + SetGraphicsMode(hDC, GM_ADVANCED); + SetMapMode(hDC, MM_ANISOTROPIC); + SetWindowExtEx(hDC, 1, 1, NULL); + SetViewportExtEx(hDC, 1, -1, NULL); + SetViewportOrgEx(hDC, 0, 0, NULL); + + /* + * For now, assume that a glyph is a unicode character and can be + * stored in a windows WORD + */ + for (i = 0; i < length; i++) + { + buf[i] = glyphs[i]; + } + + SelectObject(hDC, hFont); + GetTextExtentPoint32W(hDC, buf, length, &sBoundBox); + h = sBoundBox.cy; + + if ([path elementCount] > 0) + { + startPoint = [path currentPoint]; + } + else + { + startPoint = NSZeroPoint; + } + + SetBkMode(hDC, TRANSPARENT); + BeginPath(hDC); + SetTextAlign(hDC, TA_LEFT | TA_TOP); + TextOutW(hDC, startPoint.x, -startPoint.y, buf, length); + EndPath(hDC); + + iPoints = GetPath(hDC, NULL, NULL, 0); + if (iPoints == 0) + { + DeleteDC(hDC); + return; + } + + ptPoints = objc_malloc(sizeof(POINT) * iPoints); + if (!ptPoints) + { + DeleteDC(hDC); + return; + } + bTypes = objc_malloc(sizeof(BYTE) * iPoints); + if (!bTypes) + { + objc_free(ptPoints); + DeleteDC(hDC); + return; + } + GetPath(hDC, ptPoints, bTypes, iPoints); + + // Now append the glyphs to the path + i = 0; + while (i < iPoints) + { + if (bTypes[i] == PT_MOVETO) + { + [path moveToPoint: NSMakePoint(ptPoints[i].x, h - ptPoints[i].y)]; + i++; + } + else if (bTypes[i] & PT_LINETO) + { + [path lineToPoint: NSMakePoint(ptPoints[i].x, h - ptPoints[i].y)]; + if (bTypes[i] & PT_CLOSEFIGURE) + [path closePath]; + i++; + } + else if (bTypes[i] & PT_BEZIERTO) + { + // FIXME: We assume windows isn't lying here about the bezier points + [path curveToPoint: NSMakePoint(ptPoints[i+2].x, h - ptPoints[i+2].y) + controlPoint1: NSMakePoint(ptPoints[i].x, h - ptPoints[i].y) + controlPoint2: NSMakePoint(ptPoints[i+1].x, h - ptPoints[i+1].y)]; + if ((bTypes[i] & PT_CLOSEFIGURE) || (bTypes[i+1] & PT_CLOSEFIGURE) + || (bTypes[i+2] & PT_CLOSEFIGURE)) + [path closePath]; + i += 3; + } + } + + objc_free(bTypes); + objc_free(ptPoints); + DeleteDC(hDC); +} + @end @implementation WIN32FontInfo (Private) @@ -297,7 +425,7 @@ NSLog(@"No glyph for U%d", c); //NSLog(@"Creating Font %@ of size %f", fontName, matrix[0]); ASSIGN(familyName, win32_font_family(fontName)); memset(&logfont, 0, sizeof(LOGFONT)); - hdc = GetDC(NULL); + hdc = CreateCompatibleDC(NULL); // FIXME This hack gets the font size about right, but what is the real solution? logfont.lfHeight = (int)(matrix[0] * 4 / 3); //logfont.lfHeight = -MulDiv(matrix[0], GetDeviceCaps(hdc, LOGPIXELSY), 72); @@ -318,14 +446,14 @@ NSLog(@"No glyph for U%d", c); if (!hFont) { NSLog(@"Could not create font %@", fontName); - ReleaseDC(NULL, hdc); + DeleteDC(hdc); return NO; } old = SelectObject(hdc, hFont); GetTextMetricsW(hdc, &metric); SelectObject(hdc, old); - ReleaseDC(NULL, hdc); + DeleteDC(hdc); // Fill the ivars isFixedPitch = TMPF_FIXED_PITCH & metric.tmPitchAndFamily;