Moved ligature handling code from art to gui. Small improvements for

other font classes.


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/back/trunk@26431 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
fredkiefer 2008-04-04 22:07:03 +00:00
parent cdae5f32e9
commit 5a01087f39
5 changed files with 202 additions and 537 deletions

View file

@ -1,3 +1,15 @@
2008-04-04 Fred Kiefer <FredKiefer@gmx.de>
* Source/winlib/WIN32FontInfo.m
(-appendBezierPathWithGlyphs:count:toBezierPath:): New method.
Patch by Christopher Armstrong <carmstrong@fastmail.com.au>.
* 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 <FredKiefer@gmx.de>
* Source/cairo/CairoFontInfo.m (-appendBezierPathWithGlyphs:...):

View file

@ -34,6 +34,8 @@
#include <Foundation/NSUserDefaults.h>
#include <Foundation/NSBundle.h>
#include <Foundation/NSDebug.h>
#include <GNUstepBase/Unicode.h>
#include <GNUstepGUI/GSFontInfo.h>
#include <AppKit/NSAffineTransform.h>
#include <AppKit/NSBezierPath.h>
@ -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 <GNUstepBase/Unicode.h>
/* 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 <Foundation/NSCharacterSet.h>
#include <GNUstepGUI/GSLayoutManager_internal.h>
#include <AppKit/NSTextStorage.h>
#include <AppKit/NSTextAttachment.h>
@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 (ch<l && [str characterAtIndex: ch]=='f')
ch++;
if (ch<l && ch>0 && [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;i<c;i++,g++,j++)
{
ch=buf[i];
ch2=ch3=0;
if (i+1<c)
{
ch2=buf[i+1];
if (i+2<c)
ch3=buf[i+2];
}
g->char_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

View file

@ -45,6 +45,8 @@
#include <Foundation/NSUserDefaults.h>
#include <Foundation/NSBundle.h>
#include <Foundation/NSDebug.h>
#include <GNUstepBase/Unicode.h>
#include <GNUstepGUI/GSFontInfo.h>
#include <AppKit/NSAffineTransform.h>
#include <AppKit/NSBezierPath.h>
@ -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 <GNUstepBase/Unicode.h>
/* 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 <Foundation/NSCharacterSet.h>
#include <GNUstepGUI/GSLayoutManager_internal.h>
#include <AppKit/NSTextStorage.h>
#include <AppKit/NSTextAttachment.h>
@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 (ch<l && [str characterAtIndex: ch]=='f')
ch++;
if (ch<l && ch>0 && [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;i<c;i++,g++,j++)
{
ch=buf[i];
ch2=ch3=0;
if (i+1<c)
{
ch2=buf[i+1];
if (i+2<c)
ch3=buf[i+2];
}
g->char_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

View file

@ -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

View file

@ -29,6 +29,7 @@
#include <Foundation/NSString.h>
#include <Foundation/NSArray.h>
#include <Foundation/NSValue.h>
#include <AppKit/NSBezierPath.h>
#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;