mirror of
https://github.com/gnustep/libs-back.git
synced 2025-02-24 12:21:34 +00:00
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/back/trunk@19820 72102866-910b-0410-8b05-ffd578937521
405 lines
8.5 KiB
Objective-C
405 lines
8.5 KiB
Objective-C
/*
|
|
* CairoFontInfo.m
|
|
*
|
|
* Copyright (C) 2003 Free Software Foundation, Inc.
|
|
* April 27, 2004
|
|
* Written by Banlu Kemiyatorn <lastlifeintheuniverse at hotmail dot com>
|
|
* Base on original code of Alex Malmberg
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
|
|
* You should have received a copy of the GNU Library General Public
|
|
* License along with this library; if not, write to the Free
|
|
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
|
*/
|
|
|
|
#include "cairo/CairoFontInfo.h"
|
|
#include <cairo.h>
|
|
@class NSAffineTransform;
|
|
|
|
|
|
@implementation CairoFontInfo
|
|
|
|
/* TODO port this freetype code so it can be shared with other backends */
|
|
/* TODO or simply use cairo's text/glyph extense */
|
|
|
|
static FT_Library ft_library;
|
|
static FTC_Manager ftc_manager;
|
|
|
|
+ (void) initializeBackend
|
|
{
|
|
NSLog(@"CairoFreeTypeFontInfo : Initializing...");
|
|
[super initializeBackend];
|
|
|
|
[GSFontInfo setDefaultClass: self];
|
|
|
|
if (FT_Init_FreeType(&ft_library))
|
|
NSLog(@"FT_Init_FreeType failed");
|
|
}
|
|
|
|
- (void) setFaceId:(void *)face_id
|
|
{
|
|
_imgd.font.face_id = (FTC_FaceID)face_id;
|
|
}
|
|
|
|
- (id) initWithFontName:(NSString *)name
|
|
matrix:(const float *)fmatrix
|
|
screenFont:(BOOL)p_screenFont
|
|
{
|
|
FT_Size size;
|
|
FT_Face face;
|
|
|
|
[super initWithFontName:name
|
|
matrix:fmatrix
|
|
screenFont:p_screenFont];
|
|
|
|
_imgd.font.pix_width = fabs(matrix[0]);
|
|
_imgd.font.pix_height = fabs(matrix[3]);
|
|
if ((error=FTC_Manager_Lookup_Size(ftc_manager, &_imgd.font, &face, &size)))
|
|
{
|
|
NSLog(@"FTC_Manager_Lookup_Size() failed for '%@', error %08x!\n", name, error);
|
|
return self;
|
|
}
|
|
|
|
ascender = fabs(((int)size->metrics.ascender) / 64.0);
|
|
descender = fabs(((int)size->metrics.descender) / 64.0);
|
|
xHeight = ascender * 0.5; /* TODO */
|
|
maximumAdvancement = NSMakeSize((_size->metrics.max_advance / 64.0), ascender + descender);
|
|
|
|
fontBBox = NSMakeRect(0, descender, maximumAdvancement.width, ascender + descender);
|
|
descender = -descender;
|
|
|
|
{
|
|
float xx, yy;
|
|
|
|
FTC_ImageTypeRec cur;
|
|
|
|
cur = _imgd;
|
|
|
|
xx = matrix[0];
|
|
yy = matrix[3];
|
|
|
|
if (xx == yy && xx < 16 && xx >= 8)
|
|
{
|
|
int rh = _faceInfo->_render_hints_hack;
|
|
if (rh & 0x10000)
|
|
{
|
|
cur.flags = FT_LOAD_TARGET_NORMAL;
|
|
rh = (rh >> 8) & 0xff;
|
|
}
|
|
else
|
|
{
|
|
cur.flags = FT_LOAD_TARGET_MONO;
|
|
rh = rh & 0xff;
|
|
}
|
|
if (rh & 1)
|
|
cur.flags |= FT_LOAD_FORCE_AUTOHINT;
|
|
if (!(rh & 2))
|
|
cur.flags |= FT_LOAD_NO_HINTING;
|
|
}
|
|
else if (xx < 8)
|
|
cur.flags = FT_LOAD_TARGET_NORMAL | FT_LOAD_NO_HINTING;
|
|
else
|
|
cur.flags = FT_LOAD_TARGET_NORMAL;
|
|
_advancementImgd = cur;
|
|
}
|
|
|
|
/* create font here */
|
|
|
|
FT_New_Face(ft_library, [[_faceInfo->files] objectAtIndex:0]);
|
|
_font = cairo_ft_font_create(&face);
|
|
|
|
|
|
return self;
|
|
}
|
|
|
|
- (BOOL) glyphIsEncoded: (NSGlyph)glyph
|
|
{
|
|
[self subclassResponsibility: _cmd];
|
|
return NO;
|
|
}
|
|
|
|
- (NSSize) advancementForGlyph: (NSGlyph)glyph
|
|
{
|
|
cairo_glyph_t cglyph;
|
|
cairo_text_extents_t ctext;
|
|
|
|
glyph--;
|
|
|
|
|
|
if (screenFont)
|
|
{
|
|
int entry = glyph % CACHE_SIZE;
|
|
|
|
if (cachedGlyph[entry] == glyph)
|
|
return cachedSize[entry];
|
|
|
|
if ((error=FTC_SBitCache_Lookup(ftc_sbitcache, &advancementImgd, glyph, &sbit, NULL)))
|
|
{
|
|
NSLog(@"FTC_SBitCache_Lookup() failed with error %08x (%08x, %08x, %ix%i, %08x)\n",
|
|
error, glyph, advancementImgd.font.face_id,
|
|
advancementImgd.font.pix_width, advancementImgd.font.pix_height,
|
|
advancementImgd.flags
|
|
);
|
|
return NSZeroSize;
|
|
}
|
|
|
|
cachedGlyph[entry] = glyph;
|
|
cachedSize[entry] = NSMakeSize(sbit->xadvance, sbit->yadvance);
|
|
return cachedSize[entry];
|
|
}
|
|
else
|
|
{
|
|
FT_Face face;
|
|
FT_Glyph gl;
|
|
FT_Matrix ftmatrix;
|
|
FT_Vector ftdelta;
|
|
float f;
|
|
NSSize s;
|
|
|
|
f = fabs(matrix[0] * matrix[3] - matrix[1] * matrix[2]);
|
|
if (f > 1)
|
|
f = sqrt(f);
|
|
else
|
|
f = 1.0;
|
|
|
|
f = (int)f;
|
|
|
|
ftmatrix.xx = matrix[0] / f * 65536.0;
|
|
ftmatrix.xy = matrix[1] / f * 65536.0;
|
|
ftmatrix.yx = matrix[2] / f * 65536.0;
|
|
ftmatrix.yy = matrix[3] / f * 65536.0;
|
|
ftdelta.x = ftdelta.y = 0;
|
|
|
|
if (FTC_Manager_Lookup_Size(ftc_manager, &_imgd.font, &face, 0))
|
|
return NSZeroSize;
|
|
|
|
if (FT_Load_Glyph(face, glyph, FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP))
|
|
return NSZeroSize;
|
|
|
|
if (FT_Get_Glyph(face->glyph, &gl))
|
|
return NSZeroSize;
|
|
|
|
if (FT_Glyph_Transform(gl, &ftmatrix, &ftdelta))
|
|
return NSZeroSize;
|
|
|
|
s = NSMakeSize(gl->advance.x / 65536.0, gl->advance.y / 65536.0);
|
|
|
|
FT_Done_Glyph(gl);
|
|
|
|
return s;
|
|
}
|
|
}
|
|
|
|
- (NSRect) boundingRectForGlyph: (NSGlyph)glyph
|
|
{
|
|
FTC_ImageTypeRec *cur;
|
|
FT_BBox bbox;
|
|
FT_Glyph g;
|
|
FT_Error error;
|
|
|
|
glyph--;
|
|
/* TODO: this is ugly */
|
|
cur = &_imgd;
|
|
if ((error=FTC_ImageCache_Lookup(ftc_imagecache, cur, glyph, &g, NULL)))
|
|
{
|
|
NSLog(@"FTC_ImageCache_Lookup() failed with error %08x",error);
|
|
// NSLog(@"boundingRectForGlyph: %04x -> %i\n", aGlyph, glyph);
|
|
return fontBBox;
|
|
}
|
|
|
|
FT_Glyph_Get_CBox(g, ft_glyph_bbox_gridfit, &bbox);
|
|
|
|
/* printf("got cbox for %04x: %i, %i - %i, %i\n",
|
|
aGlyph, bbox.xMin, bbox.yMin, bbox.xMax, bbox.yMax);*/
|
|
|
|
return NSMakeRect(bbox.xMin / 64.0, bbox.yMin / 64.0,
|
|
(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;
|
|
|
|
g--;
|
|
prev--;
|
|
|
|
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;
|
|
int i, c = [string length];
|
|
int total;
|
|
|
|
FTC_CMapDescRec cmap;
|
|
unsigned int glyph;
|
|
|
|
FTC_SBit sbit;
|
|
|
|
FTC_ImageTypeRec *cur;
|
|
|
|
cmap.face_id = _imgd.font.face_id;
|
|
cmap.u.encoding = ft_encoding_unicode;
|
|
cmap.type = FTC_CMAP_BY_ENCODING;
|
|
|
|
total = 0;
|
|
for (i = 0; i < c; i++)
|
|
{
|
|
ch = [string characterAtIndex: i];
|
|
cur = &_imgd;
|
|
glyph = FTC_CMapCache_Lookup(ftc_cmapcache, &cmap, ch);
|
|
|
|
/* TODO: shouldn't use sbit cache for this */
|
|
if (1)
|
|
{
|
|
if (FTC_SBitCache_Lookup(ftc_sbitcache, cur, glyph, &sbit, NULL))
|
|
continue;
|
|
|
|
total += sbit->xadvance;
|
|
}
|
|
else
|
|
{
|
|
NSLog(@"non-sbit code not implemented");
|
|
}
|
|
}
|
|
return total;
|
|
}
|
|
|
|
-(NSGlyph) glyphWithName: (NSString *)glyphName
|
|
{
|
|
FT_Face face;
|
|
NSGlyph g;
|
|
|
|
if (FTC_Manager_Lookup_Size(ftc_manager, &_imgd.font, &face, 0))
|
|
return NSNullGlyph;
|
|
|
|
g = FT_Get_Name_Index(face, (FT_String *)[glyphName lossyCString]);
|
|
if (g)
|
|
return g + 1;
|
|
|
|
return NSNullGlyph;
|
|
}
|
|
|
|
/* need cairo to export its cairo_path_t first */
|
|
-(void) appendBezierPathWithGlyphs: (NSGlyph *)glyphs
|
|
count: (int)count
|
|
toBezierPath: (NSBezierPath *)path
|
|
{
|
|
cairo_t *ct;
|
|
int i;
|
|
/* TODO LATER
|
|
NSPoint start = [path currentPoint];
|
|
|
|
|
|
cairo_glyph_t *cairo_glyphs;
|
|
cairo_glyphs = malloc(sizeof(cairo_glyph_t) * count);
|
|
|
|
ct = cairo_create();
|
|
|
|
|
|
cairo_destroy(ct);
|
|
*/
|
|
|
|
#if 0
|
|
int i;
|
|
NSGlyph glyph;
|
|
|
|
FT_Matrix ftmatrix;
|
|
FT_Vector ftdelta;
|
|
|
|
NSPoint p = [path currentPoint];
|
|
|
|
ftmatrix.xx = 65536;
|
|
ftmatrix.xy = 0;
|
|
ftmatrix.yx = 0;
|
|
ftmatrix.yy = 65536;
|
|
ftdelta.x = p.x * 64.0;
|
|
ftdelta.y = p.y * 64.0;
|
|
|
|
for (i = 0; i < count; i++, glyphs++)
|
|
{
|
|
FT_Face face;
|
|
FT_Glyph gl;
|
|
FT_OutlineGlyph og;
|
|
|
|
glyph = *glyphs - 1;
|
|
|
|
if (FTC_Manager_Lookup_Size(ftc_manager, &_imgd.font, &face, 0))
|
|
continue;
|
|
if (FT_Load_Glyph(face, glyph, FT_LOAD_DEFAULT))
|
|
continue;
|
|
|
|
if (FT_Get_Glyph(face->glyph, &gl))
|
|
continue;
|
|
|
|
if (FT_Glyph_Transform(gl, &ftmatrix, &ftdelta))
|
|
{
|
|
NSLog(@"glyph transformation failed!");
|
|
continue;
|
|
}
|
|
og = (FT_OutlineGlyph)gl;
|
|
|
|
ftdelta.x += gl->advance.x >> 10;
|
|
ftdelta.y += gl->advance.y >> 10;
|
|
|
|
FT_Outline_Decompose(&og->outline, &bezierpath_funcs, path);
|
|
|
|
FT_Done_Glyph(gl);
|
|
}
|
|
|
|
if (count)
|
|
{
|
|
[path moveToPoint: NSMakePoint(ftdelta.x / 64.0, ftdelta.y / 64.0)];
|
|
}
|
|
#endif
|
|
}
|
|
|
|
- (void) set
|
|
{
|
|
NSLog(@"ignore -set method of font '%@'\n", fontName);
|
|
}
|
|
|
|
/*** CairoFontInfo Protocol ***/
|
|
|
|
|
|
@end
|