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