]>
Commit | Line | Data |
---|---|---|
b75a7d8f A |
1 | /* |
2 | ******************************************************************************* | |
3 | * | |
46f4442e | 4 | * Copyright (C) 1999-2007, International Business Machines |
b75a7d8f A |
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> | |
46f4442e A |
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> | |
b75a7d8f A |
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 | { | |
46f4442e | 33 | fCairo = gdk_cairo_create(fWidget->window); |
b75a7d8f A |
34 | } |
35 | ||
36 | GnomeSurface::~GnomeSurface() | |
37 | { | |
46f4442e | 38 | cairo_destroy(fCairo); |
b75a7d8f A |
39 | } |
40 | ||
41 | void GnomeSurface::drawGlyphs(const LEFontInstance *font, const LEGlyphID *glyphs, le_int32 count, | |
73c04bcf | 42 | const float *positions, le_int32 x, le_int32 y, le_int32 /*width*/, le_int32 /*height*/) |
b75a7d8f A |
43 | { |
44 | GnomeFontInstance *gFont = (GnomeFontInstance *) font; | |
b75a7d8f | 45 | |
46f4442e | 46 | gFont->rasterizeGlyphs(fCairo, glyphs, count, positions, x, y); |
b75a7d8f A |
47 | } |
48 | ||
46f4442e | 49 | GnomeFontInstance::GnomeFontInstance(FT_Library engine, const char *fontPathName, le_int16 pointSize, LEErrorCode &status) |
b75a7d8f A |
50 | : FontTableCache(), fPointSize(pointSize), fUnitsPerEM(0), fAscent(0), fDescent(0), fLeading(0), |
51 | fDeviceScaleX(1), fDeviceScaleY(1), fMapper(NULL) | |
52 | { | |
46f4442e | 53 | FT_Error error; |
b75a7d8f | 54 | |
46f4442e A |
55 | fFace = NULL; |
56 | fCairoFace = NULL; | |
b75a7d8f | 57 | |
46f4442e | 58 | error = FT_New_Face(engine, fontPathName, 0, &fFace); |
b75a7d8f A |
59 | |
60 | if (error != 0) { | |
46f4442e | 61 | printf("OOPS! Got error code %d\n", error); |
b75a7d8f A |
62 | status = LE_FONT_FILE_NOT_FOUND_ERROR; |
63 | return; | |
64 | } | |
65 | ||
b75a7d8f | 66 | // FIXME: what about the display resolution? |
b75a7d8f A |
67 | fDeviceScaleX = ((float) 96) / 72; |
68 | fDeviceScaleY = ((float) 96) / 72; | |
69 | ||
46f4442e A |
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); | |
b75a7d8f | 73 | |
46f4442e | 74 | fUnitsPerEM = fFace->units_per_EM; |
b75a7d8f | 75 | |
46f4442e A |
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; | |
b75a7d8f A |
79 | |
80 | // printf("Face = %s, unitsPerEM = %d, ascent = %d, descent = %d\n", fontPathName, fUnitsPerEM, fAscent, fDescent); | |
81 | ||
b75a7d8f A |
82 | if (error != 0) { |
83 | status = LE_MEMORY_ALLOCATION_ERROR; | |
84 | return; | |
85 | } | |
86 | ||
87 | status = initMapper(); | |
88 | } | |
89 | ||
90 | GnomeFontInstance::~GnomeFontInstance() | |
91 | { | |
46f4442e A |
92 | cairo_font_face_destroy(fCairoFace); |
93 | ||
94 | if (fFace != NULL) { | |
95 | FT_Done_Face(fFace); | |
b75a7d8f A |
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 | { | |
46f4442e A |
124 | FT_ULong len = 0; |
125 | FT_Byte *result = NULL; | |
b75a7d8f | 126 | |
46f4442e | 127 | FT_Load_Sfnt_Table(fFace, tableTag, 0, NULL, &len); |
b75a7d8f A |
128 | |
129 | if (len > 0) { | |
46f4442e A |
130 | result = LE_NEW_ARRAY(FT_Byte, len); |
131 | FT_Load_Sfnt_Table(fFace, tableTag, 0, result, &len); | |
b75a7d8f A |
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 | ||
374ca955 | 142 | if (glyph >= 0xFFFE) { |
b75a7d8f A |
143 | return; |
144 | } | |
145 | ||
46f4442e | 146 | FT_Error error; |
b75a7d8f | 147 | |
46f4442e | 148 | error = FT_Load_Glyph(fFace, glyph, FT_LOAD_DEFAULT); |
b75a7d8f A |
149 | |
150 | if (error != 0) { | |
151 | return; | |
152 | } | |
153 | ||
46f4442e | 154 | advance.fX = fFace->glyph->metrics.horiAdvance >> 6; |
b75a7d8f A |
155 | return; |
156 | } | |
157 | ||
158 | le_bool GnomeFontInstance::getGlyphPoint(LEGlyphID glyph, le_int32 pointNumber, LEPoint &point) const | |
159 | { | |
46f4442e | 160 | FT_Error error; |
b75a7d8f | 161 | |
46f4442e | 162 | error = FT_Load_Glyph(fFace, glyph, FT_LOAD_DEFAULT); |
b75a7d8f A |
163 | |
164 | if (error != 0) { | |
374ca955 | 165 | return FALSE; |
b75a7d8f A |
166 | } |
167 | ||
46f4442e | 168 | if (pointNumber >= fFace->glyph->outline.n_points) { |
374ca955 | 169 | return FALSE; |
b75a7d8f A |
170 | } |
171 | ||
46f4442e A |
172 | point.fX = fFace->glyph->outline.points[pointNumber].x >> 6; |
173 | point.fY = fFace->glyph->outline.points[pointNumber].y >> 6; | |
b75a7d8f | 174 | |
374ca955 | 175 | return TRUE; |
b75a7d8f A |
176 | } |
177 | ||
46f4442e A |
178 | void GnomeFontInstance::rasterizeGlyphs(cairo_t *cairo, const LEGlyphID *glyphs, le_int32 glyphCount, const float *positions, |
179 | le_int32 x, le_int32 y) const | |
b75a7d8f | 180 | { |
46f4442e A |
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]); | |
b75a7d8f | 186 | |
46f4442e A |
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; | |
b75a7d8f | 193 | } |
b75a7d8f | 194 | } |
46f4442e A |
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); | |
b75a7d8f | 201 | } |