1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru ******************************************************************************* 3ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 4ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Copyright (C) 1999-2007, International Business Machines 5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Corporation and others. All Rights Reserved. 6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru ******************************************************************************* 8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * file name: GnomeFontInstance.cpp 9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * created on: 08/30/2001 11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * created by: Eric R. Mader 12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <gnome.h> 15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <ft2build.h> 16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include FT_FREETYPE_H 17ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include FT_GLYPH_H 18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include FT_RENDER_H 19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include FT_TRUETYPE_TABLES_H 20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <cairo.h> 21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <cairo-ft.h> 22ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "layout/LETypes.h" 24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "layout/LESwaps.h" 25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "GnomeFontInstance.h" 27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "sfnt.h" 28ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "cmaps.h" 29ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 30ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruGnomeSurface::GnomeSurface(GtkWidget *theWidget) 31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru : fWidget(theWidget) 32ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fCairo = gdk_cairo_create(fWidget->window); 34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruGnomeSurface::~GnomeSurface() 37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 38ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru cairo_destroy(fCairo); 39ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid GnomeSurface::drawGlyphs(const LEFontInstance *font, const LEGlyphID *glyphs, le_int32 count, 42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru const float *positions, le_int32 x, le_int32 y, le_int32 /*width*/, le_int32 /*height*/) 43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru GnomeFontInstance *gFont = (GnomeFontInstance *) font; 45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru gFont->rasterizeGlyphs(fCairo, glyphs, count, positions, x, y); 47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruGnomeFontInstance::GnomeFontInstance(FT_Library engine, const char *fontPathName, le_int16 pointSize, LEErrorCode &status) 50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru : FontTableCache(), fPointSize(pointSize), fUnitsPerEM(0), fAscent(0), fDescent(0), fLeading(0), 51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fDeviceScaleX(1), fDeviceScaleY(1), fMapper(NULL) 52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru FT_Error error; 54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fFace = NULL; 56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fCairoFace = NULL; 57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru error = FT_New_Face(engine, fontPathName, 0, &fFace); 59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 60ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (error != 0) { 61ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru printf("OOPS! Got error code %d\n", error); 62ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru status = LE_FONT_FILE_NOT_FOUND_ERROR; 63ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 64ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // FIXME: what about the display resolution? 67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fDeviceScaleX = ((float) 96) / 72; 68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fDeviceScaleY = ((float) 96) / 72; 69ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 70ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru error = FT_Set_Char_Size(fFace, 0, pointSize << 6, 92, 92); 71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fCairoFace = cairo_ft_font_face_create_for_ft_face(fFace, 0); 73ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fUnitsPerEM = fFace->units_per_EM; 75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fAscent = (le_int32) (yUnitsToPoints(fFace->ascender) * fDeviceScaleY); 77ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fDescent = (le_int32) -(yUnitsToPoints(fFace->descender) * fDeviceScaleY); 78ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fLeading = (le_int32) (yUnitsToPoints(fFace->height) * fDeviceScaleY) - fAscent - fDescent; 79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // printf("Face = %s, unitsPerEM = %d, ascent = %d, descent = %d\n", fontPathName, fUnitsPerEM, fAscent, fDescent); 81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (error != 0) { 83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru status = LE_MEMORY_ALLOCATION_ERROR; 84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 86ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru status = initMapper(); 88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 90ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruGnomeFontInstance::~GnomeFontInstance() 91ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 92ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru cairo_font_face_destroy(fCairoFace); 93ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (fFace != NULL) { 95ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru FT_Done_Face(fFace); 96ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 97ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 98ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 99ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruLEErrorCode GnomeFontInstance::initMapper() 100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru LETag cmapTag = LE_CMAP_TABLE_TAG; 102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru const CMAPTable *cmap = (const CMAPTable *) readFontTable(cmapTag); 103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (cmap == NULL) { 105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return LE_MISSING_FONT_TABLE_ERROR; 106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fMapper = CMAPMapper::createUnicodeMapper(cmap); 109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (fMapper == NULL) { 111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return LE_MISSING_FONT_TABLE_ERROR; 112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return LE_NO_ERROR; 115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst void *GnomeFontInstance::getFontTable(LETag tableTag) const 118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return FontTableCache::find(tableTag); 120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst void *GnomeFontInstance::readFontTable(LETag tableTag) const 123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru FT_ULong len = 0; 125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru FT_Byte *result = NULL; 126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru FT_Load_Sfnt_Table(fFace, tableTag, 0, NULL, &len); 128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (len > 0) { 130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru result = LE_NEW_ARRAY(FT_Byte, len); 131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru FT_Load_Sfnt_Table(fFace, tableTag, 0, result, &len); 132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return result; 135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid GnomeFontInstance::getGlyphAdvance(LEGlyphID glyph, LEPoint &advance) const 138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru advance.fX = 0; 140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru advance.fY = 0; 141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (glyph >= 0xFFFE) { 143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru FT_Error error; 147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru error = FT_Load_Glyph(fFace, glyph, FT_LOAD_DEFAULT); 149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (error != 0) { 151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru advance.fX = fFace->glyph->metrics.horiAdvance >> 6; 155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 157ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querule_bool GnomeFontInstance::getGlyphPoint(LEGlyphID glyph, le_int32 pointNumber, LEPoint &point) const 159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru FT_Error error; 161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru error = FT_Load_Glyph(fFace, glyph, FT_LOAD_DEFAULT); 163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (error != 0) { 165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return FALSE; 166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (pointNumber >= fFace->glyph->outline.n_points) { 169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return FALSE; 170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru point.fX = fFace->glyph->outline.points[pointNumber].x >> 6; 173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru point.fY = fFace->glyph->outline.points[pointNumber].y >> 6; 174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return TRUE; 176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid GnomeFontInstance::rasterizeGlyphs(cairo_t *cairo, const LEGlyphID *glyphs, le_int32 glyphCount, const float *positions, 179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_int32 x, le_int32 y) const 180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru cairo_glyph_t *glyph_t = LE_NEW_ARRAY(cairo_glyph_t, glyphCount); 182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_int32 in, out; 183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru for (in = 0, out = 0; in < glyphCount; in += 1) { 185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru TTGlyphID glyph = LE_GET_GLYPH(glyphs[in]); 186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (glyph < 0xFFFE) { 188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru glyph_t[out].index = glyph; 189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru glyph_t[out].x = x + positions[in*2]; 190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru glyph_t[out].y = y + positions[in*2 + 1]; 191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru out += 1; 193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru cairo_set_font_face(cairo, fCairoFace); 197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru cairo_set_font_size(cairo, getXPixelsPerEm() * getScaleFactorX()); 198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru cairo_show_glyphs(cairo, glyph_t, out); 199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru LE_DELETE_ARRAY(glyph_t); 201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 202