mirror of
https://github.com/gnustep/libs-back.git
synced 2025-04-22 15:31:14 +00:00
Implement the glyph generation backend methods. Implement GSShowGlyphs operator. Handle glyphs properly in FTFontInfo.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/back/branches/text-system-branch@15060 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
385d843bec
commit
438d0b4474
4 changed files with 663 additions and 38 deletions
|
@ -1,3 +1,9 @@
|
|||
2002-11-24 00:35 Alexander Malmberg <alexander@malmberg.org>
|
||||
|
||||
* Source/art/ARTContext.m, Source/art/ftfont.h, Source/art/ftfont.m:
|
||||
Implement the glyph generation backend methods. Implement the
|
||||
GSShowGlyphs operator. Handle glyphs properly in FTFontInfo.
|
||||
|
||||
2002-11-21 Adam Fedor <fedor@gnu.org>
|
||||
|
||||
* Version: 0.8.3
|
||||
|
|
|
@ -28,7 +28,9 @@
|
|||
|
||||
#include "ARTGState.h"
|
||||
|
||||
#ifndef RDS
|
||||
#include "x11/XWindowBuffer.h"
|
||||
#endif
|
||||
#include "blit.h"
|
||||
#include "ftfont.h"
|
||||
|
||||
|
@ -295,7 +297,7 @@ very expensive
|
|||
if (all_clipped)
|
||||
return;
|
||||
|
||||
if ([path isEmpty]) return;
|
||||
if (!path || [path isEmpty]) return;
|
||||
p = [path currentPoint];
|
||||
|
||||
x = p.x;
|
||||
|
@ -311,6 +313,31 @@ very expensive
|
|||
}
|
||||
|
||||
|
||||
- (void) GSShowGlyphs: (const NSGlyph *)glyphs : (size_t) length
|
||||
{
|
||||
NSPoint p;
|
||||
int x, y;
|
||||
|
||||
if (!wi || !wi->data) return;
|
||||
if (all_clipped)
|
||||
return;
|
||||
|
||||
if (!path || [path isEmpty]) return;
|
||||
p = [path currentPoint];
|
||||
|
||||
x = p.x;
|
||||
y = wi->sy - p.y;
|
||||
[(id<FTFontInfo>)font
|
||||
drawGlyphs: glyphs : length
|
||||
at: x:y
|
||||
to: clip_x0:clip_y0:clip_x1:clip_y1 : CLIP_DATA : wi->bytes_per_line
|
||||
color: fill_color[0]:fill_color[1]:fill_color[2]:fill_color[3]
|
||||
transform: ctm
|
||||
drawinfo: &DI];
|
||||
UPDATE_UNBUFFERED
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
/* Gstate operations */
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
@ -556,7 +583,9 @@ very expensive
|
|||
XWindowBuffer *new_wi;
|
||||
[self setOffset: NSMakePoint(x, y)];
|
||||
|
||||
#ifndef RDS
|
||||
di.drawing_depth = DI.drawing_depth;
|
||||
#endif
|
||||
di.bytes_per_pixel = DI.bytes_per_pixel;
|
||||
di.inline_alpha = DI.inline_alpha;
|
||||
di.inline_alpha_ofs = DI.inline_alpha_ofs;
|
||||
|
@ -622,6 +651,15 @@ very expensive
|
|||
[gstate DPSsetalpha: 1.0];
|
||||
[gstate DPSsetlinewidth: 1.0];
|
||||
|
||||
#ifdef RDS
|
||||
{
|
||||
RDSServer *s=(RDSServer *)server;
|
||||
int bpp;
|
||||
int red_mask,green_mask,blue_mask;
|
||||
[s getPixelFormat: &bpp masks: &red_mask : &green_mask : &blue_mask];
|
||||
artcontext_setup_draw_info(&DI,red_mask,green_mask,blue_mask,bpp);
|
||||
}
|
||||
#else
|
||||
{
|
||||
Display *d=[(XGServer *)server xDisplay];
|
||||
Visual *v=DefaultVisual(d,DefaultScreen(d));
|
||||
|
@ -632,6 +670,7 @@ very expensive
|
|||
|
||||
artcontext_setup_draw_info(&DI,v->red_mask,v->green_mask,v->blue_mask,bpp);
|
||||
}
|
||||
#endif
|
||||
|
||||
return self;
|
||||
}
|
||||
|
@ -639,7 +678,9 @@ very expensive
|
|||
|
||||
- (void) flushGraphics
|
||||
{ /* TODO: _really_ flush? (ie. force updates and wait for shm completion?) */
|
||||
#ifndef RDS
|
||||
XFlush([(XGServer *)server xDisplay]);
|
||||
#endif
|
||||
}
|
||||
|
||||
+(void) waitAllContexts
|
||||
|
@ -647,6 +688,7 @@ very expensive
|
|||
}
|
||||
|
||||
|
||||
#ifndef RDS
|
||||
+(void) _gotShmCompletion: (Drawable)d
|
||||
{
|
||||
[XWindowBuffer _gotShmCompletion: d];
|
||||
|
@ -656,6 +698,7 @@ very expensive
|
|||
{
|
||||
[XWindowBuffer _gotShmCompletion: d];
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// Read the Color at a Screen Position
|
||||
|
@ -668,7 +711,10 @@ very expensive
|
|||
|
||||
- (void) beep
|
||||
{
|
||||
NSLog(@"ARTContext -beep: why here?");
|
||||
#ifndef RDS
|
||||
XBell([(XGServer *)server xDisplay], 50);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Private backend methods */
|
||||
|
|
|
@ -35,6 +35,15 @@
|
|||
transform: (NSAffineTransform *)transform
|
||||
drawinfo: (struct draw_info_s *)di;
|
||||
|
||||
-(void) drawGlyphs: (const NSGlyph *)glyphs : (int)length
|
||||
at: (int)x : (int)y
|
||||
to: (int)x0 : (int)y0 : (int)x1 : (int)y1
|
||||
: (unsigned char *)buf : (int)bpl
|
||||
color: (unsigned char)r : (unsigned char)g : (unsigned char)b
|
||||
: (unsigned char)alpha
|
||||
transform: (NSAffineTransform *)transform
|
||||
drawinfo: (struct draw_info_s *)di;
|
||||
|
||||
/* TODO: see if this is really necessary */
|
||||
-(void) drawString: (const char *)s
|
||||
at: (int)x:(int)y
|
||||
|
|
|
@ -75,12 +75,17 @@ static BOOL anti_alias_by_default;
|
|||
|
||||
@interface FTFontInfo : GSFontInfo <FTFontInfo>
|
||||
{
|
||||
@public
|
||||
const char *filename;
|
||||
FTC_ImageDesc imgd;
|
||||
|
||||
FTC_ImageDesc fallback;
|
||||
|
||||
FTFaceInfo *face_info;
|
||||
|
||||
|
||||
/* Glyph generation */
|
||||
NSGlyph ligature_ff,ligature_fi,ligature_fl,ligature_ffl,ligature_ffi;
|
||||
}
|
||||
@end
|
||||
|
||||
|
@ -589,10 +594,10 @@ static FT_Error ft_get_face(FTC_FaceID fid, FT_Library lib, FT_Pointer data, FT_
|
|||
self = [super init];
|
||||
|
||||
|
||||
NSDebugLLog(@"ftfont", @"[%@ -initWithFontName: %@ matrix: (%g %g %g %g %g %g)]\n",
|
||||
/* NSDebugLLog(@"ftfont", @"[%@ -initWithFontName: %@ matrix: (%g %g %g %g %g %g)]\n",
|
||||
self, name,
|
||||
fmatrix[0], fmatrix[1], fmatrix[2],
|
||||
fmatrix[3], fmatrix[4], fmatrix[5]);
|
||||
fmatrix[3], fmatrix[4], fmatrix[5]);*/
|
||||
|
||||
font_entry = [fcfg_all_fonts objectForKey: name];
|
||||
if (!font_entry)
|
||||
|
@ -649,20 +654,39 @@ static FT_Error ft_get_face(FTC_FaceID fid, FT_Library lib, FT_Pointer data, FT_
|
|||
}
|
||||
|
||||
// xHeight = size->metrics.height / 64.0;
|
||||
ascender = fabs(size->metrics.ascender / 64.0);
|
||||
descender = fabs(size->metrics.descender / 64.0);
|
||||
/* TODO: these are _really_ messed up when fonts are flipped */
|
||||
ascender = fabs(((int)size->metrics.ascender) / 64.0);
|
||||
descender = fabs(((int)size->metrics.descender) / 64.0);
|
||||
xHeight = ascender + descender; /* TODO */
|
||||
maximumAdvancement = NSMakeSize((size->metrics.max_advance / 64.0), ascender + descender);
|
||||
|
||||
fontBBox = NSMakeRect(0, descender, maximumAdvancement.width, ascender + descender);
|
||||
descender = -descender;
|
||||
|
||||
/* printf("h=%g a=%g d=%g max=(%g %g) (%g %g)+(%g %g)\n",
|
||||
/* printf("(%@) h=%g a=%g d=%g max=(%g %g) (%g %g)+(%g %g)\n",name,
|
||||
xHeight, ascender, descender,
|
||||
maximumAdvancement.width, maximumAdvancement.height,
|
||||
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);*/
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
@ -1084,29 +1108,336 @@ extern void GSToUnicode();
|
|||
}
|
||||
|
||||
|
||||
- (NSSize) advancementForGlyph: (NSGlyph)aGlyph
|
||||
-(void) drawGlyphs: (const NSGlyph *)glyphs : (int)length
|
||||
at: (int)x : (int)y
|
||||
to: (int)x0 : (int)y0 : (int)x1 : (int)y1
|
||||
: (unsigned char *)buf : (int)bpl
|
||||
color: (unsigned char)r : (unsigned char)g : (unsigned char)b
|
||||
: (unsigned char)alpha
|
||||
transform: (NSAffineTransform *)transform
|
||||
drawinfo: (struct draw_info_s *)di
|
||||
{
|
||||
FTC_CMapDescRec cmap;
|
||||
unsigned int glyph;
|
||||
|
||||
FT_Glyph g;
|
||||
int use_sbit;
|
||||
|
||||
FTC_ImageDesc *cur;
|
||||
FTC_SBit sbit;
|
||||
FTC_ImageDesc cur;
|
||||
|
||||
cmap.face_id = imgd.font.face_id;
|
||||
cmap.u.encoding = ft_encoding_unicode;
|
||||
cmap.type = FTC_CMAP_BY_ENCODING;
|
||||
FT_Matrix ftmatrix;
|
||||
FT_Vector ftdelta;
|
||||
|
||||
cur = &imgd;
|
||||
glyph = FTC_CMapCache_Lookup(ftc_cmapcache, &cmap, aGlyph);
|
||||
if (!glyph)
|
||||
|
||||
if (!alpha)
|
||||
return;
|
||||
|
||||
/* TODO: if we had guaranteed upper bounds on glyph image size we
|
||||
could do some basic clipping here */
|
||||
|
||||
x1 -= x0;
|
||||
y1 -= y0;
|
||||
x -= x0;
|
||||
y -= y0;
|
||||
|
||||
|
||||
/* NSLog(@"[%@ draw using matrix: (%g %g %g %g %g %g)] transform=%@\n",
|
||||
self,
|
||||
matrix[0], matrix[1], matrix[2],
|
||||
matrix[3], matrix[4], matrix[5],
|
||||
transform
|
||||
);*/
|
||||
|
||||
cur = imgd;
|
||||
{
|
||||
float xx, xy, yx, yy;
|
||||
|
||||
xx = matrix[0] * transform->matrix.m11 + matrix[1] * transform->matrix.m21;
|
||||
yx = matrix[0] * transform->matrix.m12 + matrix[1] * transform->matrix.m22;
|
||||
xy = matrix[2] * transform->matrix.m11 + matrix[3] * transform->matrix.m21;
|
||||
yy = matrix[2] * transform->matrix.m12 + matrix[3] * transform->matrix.m22;
|
||||
|
||||
/* if we're drawing 'normal' text (unscaled, unrotated, reasonable
|
||||
size), we can and should use the sbit cache */
|
||||
if (fabs(xx - ((int)xx)) < 0.01 && fabs(yy - ((int)yy)) < 0.01 &&
|
||||
fabs(xy) < 0.01 && fabs(yx) < 0.01 &&
|
||||
xx < 72 && yy < 72 && xx > 0.5 && yy > 0.5)
|
||||
{
|
||||
use_sbit = 1;
|
||||
cur.font.pix_width = xx;
|
||||
cur.font.pix_height = yy;
|
||||
|
||||
if (xx == yy && xx < 16 && xx >= 8)
|
||||
{
|
||||
int rh = face_info->render_hints_hack;
|
||||
if (rh & 0x10000)
|
||||
{
|
||||
cur.type = ftc_image_grays;
|
||||
rh = (rh >> 8) & 0xff;
|
||||
}
|
||||
else
|
||||
{
|
||||
cur.type = ftc_image_mono;
|
||||
rh = rh & 0xff;
|
||||
}
|
||||
if (rh & 1)
|
||||
cur.type |= ftc_image_flag_autohinted;
|
||||
if (!(rh & 2))
|
||||
cur.type |= ftc_image_flag_unhinted;
|
||||
}
|
||||
else if (xx < 8)
|
||||
cur.type = ftc_image_grays | ftc_image_flag_unhinted;
|
||||
else
|
||||
cur.type = ftc_image_grays;
|
||||
}
|
||||
else
|
||||
{
|
||||
float f;
|
||||
use_sbit = 0;
|
||||
|
||||
f = fabs(xx * yy - xy * yx);
|
||||
if (f > 1)
|
||||
f = sqrt(f);
|
||||
else
|
||||
f = 1.0;
|
||||
|
||||
f = (int)f;
|
||||
|
||||
cur.font.pix_width = cur.font.pix_height = f;
|
||||
ftmatrix.xx = xx / f * 65536.0;
|
||||
ftmatrix.xy = xy / f * 65536.0;
|
||||
ftmatrix.yx = yx / f * 65536.0;
|
||||
ftmatrix.yy = yy / f * 65536.0;
|
||||
ftdelta.x = ftdelta.y = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* NSLog(@"drawString: '%s' at: %i:%i to: %i:%i:%i:%i:%p\n",
|
||||
s, x, y, x0, y0, x1, y1, buf);*/
|
||||
|
||||
for (; length; length--, glyphs++)
|
||||
{
|
||||
cmap.face_id = fallback.font.face_id;
|
||||
glyph = FTC_CMapCache_Lookup(ftc_cmapcache, &cmap, aGlyph);
|
||||
if (glyph)
|
||||
cur = &fallback;
|
||||
}
|
||||
glyph = *glyphs;
|
||||
|
||||
if (use_sbit)
|
||||
{
|
||||
if (FTC_SBitCache_Lookup(ftc_sbitcache, &cur, glyph, &sbit, NULL))
|
||||
continue;
|
||||
|
||||
if (!sbit->buffer)
|
||||
{
|
||||
x += sbit->xadvance;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sbit->format == ft_pixel_mode_grays)
|
||||
{
|
||||
int gx = x + sbit->left, gy = y - sbit->top;
|
||||
int sbpl = sbit->pitch;
|
||||
int sx = sbit->width, sy = sbit->height;
|
||||
const unsigned char *src = sbit->buffer;
|
||||
unsigned char *dst = buf;
|
||||
|
||||
if (gy < 0)
|
||||
{
|
||||
sy += gy;
|
||||
src -= sbpl * gy;
|
||||
gy = 0;
|
||||
}
|
||||
else if (gy > 0)
|
||||
{
|
||||
dst += bpl * gy;
|
||||
}
|
||||
|
||||
sy += gy;
|
||||
if (sy > y1)
|
||||
sy = y1;
|
||||
|
||||
if (gx < 0)
|
||||
{
|
||||
sx += gx;
|
||||
src -= gx;
|
||||
gx = 0;
|
||||
}
|
||||
else if (gx > 0)
|
||||
{
|
||||
dst += DI.bytes_per_pixel * gx;
|
||||
}
|
||||
|
||||
sx += gx;
|
||||
if (sx > x1)
|
||||
sx = x1;
|
||||
sx -= gx;
|
||||
|
||||
if (sx > 0)
|
||||
{
|
||||
if (alpha >= 255)
|
||||
for (; gy < sy; gy++, src += sbpl, dst += bpl)
|
||||
RENDER_BLIT_ALPHA_OPAQUE(dst, src, r, g, b, sx);
|
||||
else
|
||||
for (; gy < sy; gy++, src += sbpl, dst += bpl)
|
||||
RENDER_BLIT_ALPHA(dst, src, r, g, b, alpha, sx);
|
||||
}
|
||||
}
|
||||
else if (sbit->format == ft_pixel_mode_mono)
|
||||
{
|
||||
int gx = x + sbit->left, gy = y - sbit->top;
|
||||
int sbpl = sbit->pitch;
|
||||
int sx = sbit->width, sy = sbit->height;
|
||||
const unsigned char *src = sbit->buffer;
|
||||
unsigned char *dst = buf;
|
||||
int src_ofs = 0;
|
||||
|
||||
if (gy < 0)
|
||||
{
|
||||
sy += gy;
|
||||
src -= sbpl * gy;
|
||||
gy = 0;
|
||||
}
|
||||
else if (gy > 0)
|
||||
{
|
||||
dst += bpl * gy;
|
||||
}
|
||||
|
||||
sy += gy;
|
||||
if (sy > y1)
|
||||
sy = y1;
|
||||
|
||||
if (gx < 0)
|
||||
{
|
||||
sx += gx;
|
||||
src -= gx / 8;
|
||||
src_ofs = (-gx) & 7;
|
||||
gx = 0;
|
||||
}
|
||||
else if (gx > 0)
|
||||
{
|
||||
dst += DI.bytes_per_pixel * gx;
|
||||
}
|
||||
|
||||
sx += gx;
|
||||
if (sx > x1)
|
||||
sx = x1;
|
||||
sx -= gx;
|
||||
|
||||
if (sx > 0)
|
||||
{
|
||||
if (alpha >= 255)
|
||||
for (; gy < sy; gy++, src += sbpl, dst += bpl)
|
||||
RENDER_BLIT_MONO_OPAQUE(dst, src, src_ofs, r, g, b, sx);
|
||||
else
|
||||
for (; gy < sy; gy++, src += sbpl, dst += bpl)
|
||||
RENDER_BLIT_MONO(dst, src, src_ofs, r, g, b, alpha, sx);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NSLog(@"unhandled font bitmap format %i", sbit->format);
|
||||
}
|
||||
|
||||
x += sbit->xadvance;
|
||||
}
|
||||
else
|
||||
{
|
||||
FT_Face face;
|
||||
FT_Glyph gl;
|
||||
FT_BitmapGlyph gb;
|
||||
|
||||
if (FTC_Manager_Lookup_Size(ftc_manager, &cur.font, &face, 0))
|
||||
continue;
|
||||
|
||||
/* TODO: for rotations of 90, 180, 270, and integer
|
||||
scales hinting might still be a good idea. */
|
||||
if (FT_Load_Glyph(face, glyph, FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP))
|
||||
continue;
|
||||
|
||||
if (FT_Get_Glyph(face->glyph, &gl))
|
||||
continue;
|
||||
|
||||
if (FT_Glyph_Transform(gl, &ftmatrix, &ftdelta))
|
||||
{
|
||||
NSLog(@"glyph transformation failed!");
|
||||
continue;
|
||||
}
|
||||
if (FT_Glyph_To_Bitmap(&gl, ft_render_mode_normal, 0, 1))
|
||||
{
|
||||
FT_Done_Glyph(gl);
|
||||
continue;
|
||||
}
|
||||
gb = (FT_BitmapGlyph)gl;
|
||||
|
||||
|
||||
if (gb->bitmap.pixel_mode == ft_pixel_mode_grays)
|
||||
{
|
||||
int gx = x + gb->left, gy = y - gb->top;
|
||||
int sbpl = gb->bitmap.pitch;
|
||||
int sx = gb->bitmap.width, sy = gb->bitmap.rows;
|
||||
const unsigned char *src = gb->bitmap.buffer;
|
||||
unsigned char *dst = buf;
|
||||
|
||||
if (gy < 0)
|
||||
{
|
||||
sy += gy;
|
||||
src -= sbpl * gy;
|
||||
gy = 0;
|
||||
}
|
||||
else if (gy > 0)
|
||||
{
|
||||
dst += bpl * gy;
|
||||
}
|
||||
|
||||
sy += gy;
|
||||
if (sy > y1)
|
||||
sy = y1;
|
||||
|
||||
if (gx < 0)
|
||||
{
|
||||
sx += gx;
|
||||
src -= gx;
|
||||
gx = 0;
|
||||
}
|
||||
else if (gx > 0)
|
||||
{
|
||||
dst += DI.bytes_per_pixel * gx;
|
||||
}
|
||||
|
||||
sx += gx;
|
||||
if (sx > x1)
|
||||
sx = x1;
|
||||
sx -= gx;
|
||||
|
||||
if (sx > 0)
|
||||
{
|
||||
if (alpha >= 255)
|
||||
for (; gy < sy; gy++, src += sbpl, dst += bpl)
|
||||
RENDER_BLIT_ALPHA_OPAQUE(dst, src, r, g, b, sx);
|
||||
else
|
||||
for (; gy < sy; gy++, src += sbpl, dst += bpl)
|
||||
RENDER_BLIT_ALPHA(dst, src, r, g, b, alpha, sx);
|
||||
}
|
||||
}
|
||||
/* TODO: will this case ever appear? */
|
||||
/* else if (gb->bitmap.pixel_mode==ft_pixel_mode_mono)*/
|
||||
else
|
||||
{
|
||||
NSLog(@"unhandled font bitmap format %i", gb->bitmap.pixel_mode);
|
||||
}
|
||||
|
||||
ftdelta.x += gl->advance.x >> 10;
|
||||
ftdelta.y += gl->advance.y >> 10;
|
||||
|
||||
FT_Done_Glyph(gl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (NSSize) advancementForGlyph: (NSGlyph)glyph
|
||||
{
|
||||
FT_Glyph g;
|
||||
FTC_ImageDesc *cur;
|
||||
/* TODO: this is ugly */
|
||||
cur = &imgd;
|
||||
if (FTC_ImageCache_Lookup(ftc_imagecache, cur, glyph, &g, NULL))
|
||||
{
|
||||
// NSLog(@"advancementForGlyph: %04x -> %i not found\n", aGlyph, glyph);
|
||||
|
@ -1119,29 +1450,14 @@ extern void GSToUnicode();
|
|||
return NSMakeSize(g->advance.x / 65536.0, g->advance.y / 65536.0);
|
||||
}
|
||||
|
||||
- (NSRect) boundingRectForGlyph: (NSGlyph)aGlyph
|
||||
- (NSRect) boundingRectForGlyph: (NSGlyph)glyph
|
||||
{
|
||||
FTC_CMapDescRec cmap;
|
||||
FTC_ImageDesc *cur;
|
||||
unsigned int glyph;
|
||||
FT_BBox bbox;
|
||||
|
||||
FT_Glyph g;
|
||||
|
||||
cmap.face_id = imgd.font.face_id;
|
||||
cmap.u.encoding = ft_encoding_unicode;
|
||||
cmap.type = FTC_CMAP_BY_ENCODING;
|
||||
|
||||
/* TODO: this is ugly */
|
||||
cur = &imgd;
|
||||
glyph = FTC_CMapCache_Lookup(ftc_cmapcache, &cmap, aGlyph);
|
||||
if (!glyph)
|
||||
{
|
||||
cmap.face_id = fallback.font.face_id;
|
||||
glyph = FTC_CMapCache_Lookup(ftc_cmapcache, &cmap, aGlyph);
|
||||
if (glyph)
|
||||
cur = &fallback;
|
||||
}
|
||||
|
||||
if (FTC_ImageCache_Lookup(ftc_imagecache, cur, glyph, &g, NULL))
|
||||
{
|
||||
// NSLog(@"boundingRectForGlyph: %04x -> %i\n", aGlyph, glyph);
|
||||
|
@ -1157,6 +1473,45 @@ extern void GSToUnicode();
|
|||
(bbox.xMax - bbox.xMin) / 64.0, (bbox.yMax - bbox.yMin) / 64.0);
|
||||
}
|
||||
|
||||
-(NSPoint) positionOfGlyph: (NSGlyph)g
|
||||
precededByGlyph: (NSGlyph)prev
|
||||
isNominal: (BOOL *)nominal
|
||||
{
|
||||
NSPoint a;
|
||||
FT_Face face;
|
||||
FT_Vector vec;
|
||||
FT_GlyphSlot glyph;
|
||||
|
||||
if (nominal)
|
||||
*nominal = YES;
|
||||
|
||||
if (g == NSControlGlyph || prev == NSControlGlyph)
|
||||
return NSZeroPoint;
|
||||
|
||||
if (FTC_Manager_Lookup_Size(ftc_manager, &imgd.font, &face, 0))
|
||||
return NSZeroPoint;
|
||||
|
||||
if (FT_Load_Glyph(face, prev, FT_LOAD_DEFAULT))
|
||||
return NSZeroPoint;
|
||||
|
||||
glyph = face->glyph;
|
||||
a = NSMakePoint(glyph->advance.x / 64.0, glyph->advance.y / 64.0);
|
||||
|
||||
if (FT_Get_Kerning(face, prev, g, ft_kerning_default, &vec))
|
||||
return a;
|
||||
|
||||
if (vec.x == 0 && vec.y == 0)
|
||||
return a;
|
||||
|
||||
if (nominal)
|
||||
*nominal = NO;
|
||||
|
||||
a.x += vec.x / 64.0;
|
||||
a.y += vec.y / 64.0;
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
- (float) widthOfString: (NSString*)string
|
||||
{
|
||||
unichar ch;
|
||||
|
@ -1958,3 +2313,212 @@ 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;
|
||||
|
||||
FTC_CMapDescRec cmap;
|
||||
|
||||
cmap.face_id = fi->imgd.font.face_id;
|
||||
cmap.u.encoding = ft_encoding_unicode;
|
||||
cmap.type = FTC_CMAP_BY_ENCODING;
|
||||
|
||||
return FTC_CMapCache_Lookup(ftc_cmapcache, &cmap, ch);
|
||||
}
|
||||
|
||||
-(NSString *) nameOfGlyph: (NSGlyph)glyph
|
||||
{
|
||||
FTFontInfo *fi=fontInfo;
|
||||
FT_Face face;
|
||||
|
||||
char buf[256];
|
||||
|
||||
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.
|
||||
*/
|
||||
#include <AppKit/GSLayoutManager_internal.h>
|
||||
#include <AppKit/NSTextStorage.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;
|
||||
int i,j;
|
||||
unichar 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];
|
||||
|
||||
|
||||
// printf("_generateGlyphsForRun: %p %i+%i\n",run,pos,run->head.char_length);
|
||||
|
||||
[[_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 (run->ligature>=1)
|
||||
{
|
||||
if (ch=='f' && ch2=='f' && ch3=='l' && fi->ligature_ffl)
|
||||
{
|
||||
g->g=fi->ligature_ffl;
|
||||
i+=2;
|
||||
continue;
|
||||
}
|
||||
if (ch=='f' && ch2=='f' && ch3=='i' && fi->ligature_ffi)
|
||||
{
|
||||
g->g=fi->ligature_ffi;
|
||||
i+=2;
|
||||
continue;
|
||||
}
|
||||
if (ch=='f' && ch2=='f' && fi->ligature_ff)
|
||||
{
|
||||
g->g=fi->ligature_ff;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (ch=='f' && ch2=='i' && fi->ligature_fi)
|
||||
{
|
||||
g->g=fi->ligature_fi;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (ch=='f' && ch2=='l' && fi->ligature_fl)
|
||||
{
|
||||
g->g=fi->ligature_fl;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
g->g=FTC_CMapCache_Lookup(ftc_cmapcache, &cmap, ch);
|
||||
|
||||
if (!g->g)
|
||||
{
|
||||
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);
|
||||
if (!g->g)
|
||||
break;
|
||||
c++;
|
||||
g++;
|
||||
j++;
|
||||
g->char_offset=i;
|
||||
}
|
||||
if (*decomp)
|
||||
{
|
||||
g-=c;
|
||||
j-=c;
|
||||
g->g=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
g--;
|
||||
j--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: shrink if necessary */
|
||||
run->head.glyph_length=j;
|
||||
}
|
||||
@end
|
||||
|
||||
|
|
Loading…
Reference in a new issue