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