]>
Commit | Line | Data |
---|---|---|
b75a7d8f | 1 | /* |
f3c0d7a5 A |
2 | ******************************************************************************* |
3 | * | |
4 | * © 2016 and later: Unicode, Inc. and others. | |
5 | * License & terms of use: http://www.unicode.org/copyright.html#License | |
6 | * | |
7 | ******************************************************************************* | |
b75a7d8f A |
8 | ******************************************************************************* |
9 | * | |
46f4442e | 10 | * Copyright (C) 1999-2007, International Business Machines |
b75a7d8f A |
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> | |
46f4442e A |
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> | |
b75a7d8f A |
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 | ||
36 | GnomeSurface::GnomeSurface(GtkWidget *theWidget) | |
37 | : fWidget(theWidget) | |
38 | { | |
46f4442e | 39 | fCairo = gdk_cairo_create(fWidget->window); |
b75a7d8f A |
40 | } |
41 | ||
42 | GnomeSurface::~GnomeSurface() | |
43 | { | |
46f4442e | 44 | cairo_destroy(fCairo); |
b75a7d8f A |
45 | } |
46 | ||
47 | void GnomeSurface::drawGlyphs(const LEFontInstance *font, const LEGlyphID *glyphs, le_int32 count, | |
73c04bcf | 48 | const float *positions, le_int32 x, le_int32 y, le_int32 /*width*/, le_int32 /*height*/) |
b75a7d8f A |
49 | { |
50 | GnomeFontInstance *gFont = (GnomeFontInstance *) font; | |
b75a7d8f | 51 | |
46f4442e | 52 | gFont->rasterizeGlyphs(fCairo, glyphs, count, positions, x, y); |
b75a7d8f A |
53 | } |
54 | ||
46f4442e | 55 | GnomeFontInstance::GnomeFontInstance(FT_Library engine, const char *fontPathName, le_int16 pointSize, LEErrorCode &status) |
b75a7d8f A |
56 | : FontTableCache(), fPointSize(pointSize), fUnitsPerEM(0), fAscent(0), fDescent(0), fLeading(0), |
57 | fDeviceScaleX(1), fDeviceScaleY(1), fMapper(NULL) | |
58 | { | |
46f4442e | 59 | FT_Error error; |
b75a7d8f | 60 | |
46f4442e A |
61 | fFace = NULL; |
62 | fCairoFace = NULL; | |
b75a7d8f | 63 | |
46f4442e | 64 | error = FT_New_Face(engine, fontPathName, 0, &fFace); |
b75a7d8f A |
65 | |
66 | if (error != 0) { | |
46f4442e | 67 | printf("OOPS! Got error code %d\n", error); |
b75a7d8f A |
68 | status = LE_FONT_FILE_NOT_FOUND_ERROR; |
69 | return; | |
70 | } | |
71 | ||
b75a7d8f | 72 | // FIXME: what about the display resolution? |
b75a7d8f A |
73 | fDeviceScaleX = ((float) 96) / 72; |
74 | fDeviceScaleY = ((float) 96) / 72; | |
75 | ||
46f4442e A |
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); | |
b75a7d8f | 79 | |
46f4442e | 80 | fUnitsPerEM = fFace->units_per_EM; |
b75a7d8f | 81 | |
46f4442e A |
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; | |
b75a7d8f A |
85 | |
86 | // printf("Face = %s, unitsPerEM = %d, ascent = %d, descent = %d\n", fontPathName, fUnitsPerEM, fAscent, fDescent); | |
87 | ||
b75a7d8f A |
88 | if (error != 0) { |
89 | status = LE_MEMORY_ALLOCATION_ERROR; | |
90 | return; | |
91 | } | |
92 | ||
93 | status = initMapper(); | |
94 | } | |
95 | ||
96 | GnomeFontInstance::~GnomeFontInstance() | |
97 | { | |
46f4442e A |
98 | cairo_font_face_destroy(fCairoFace); |
99 | ||
100 | if (fFace != NULL) { | |
101 | FT_Done_Face(fFace); | |
b75a7d8f A |
102 | } |
103 | } | |
104 | ||
105 | LEErrorCode 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 | ||
123 | const void *GnomeFontInstance::getFontTable(LETag tableTag) const | |
124 | { | |
125 | return FontTableCache::find(tableTag); | |
126 | } | |
127 | ||
128 | const void *GnomeFontInstance::readFontTable(LETag tableTag) const | |
129 | { | |
46f4442e A |
130 | FT_ULong len = 0; |
131 | FT_Byte *result = NULL; | |
b75a7d8f | 132 | |
46f4442e | 133 | FT_Load_Sfnt_Table(fFace, tableTag, 0, NULL, &len); |
b75a7d8f A |
134 | |
135 | if (len > 0) { | |
46f4442e A |
136 | result = LE_NEW_ARRAY(FT_Byte, len); |
137 | FT_Load_Sfnt_Table(fFace, tableTag, 0, result, &len); | |
b75a7d8f A |
138 | } |
139 | ||
140 | return result; | |
141 | } | |
142 | ||
143 | void GnomeFontInstance::getGlyphAdvance(LEGlyphID glyph, LEPoint &advance) const | |
144 | { | |
145 | advance.fX = 0; | |
146 | advance.fY = 0; | |
147 | ||
374ca955 | 148 | if (glyph >= 0xFFFE) { |
b75a7d8f A |
149 | return; |
150 | } | |
151 | ||
46f4442e | 152 | FT_Error error; |
b75a7d8f | 153 | |
46f4442e | 154 | error = FT_Load_Glyph(fFace, glyph, FT_LOAD_DEFAULT); |
b75a7d8f A |
155 | |
156 | if (error != 0) { | |
157 | return; | |
158 | } | |
159 | ||
46f4442e | 160 | advance.fX = fFace->glyph->metrics.horiAdvance >> 6; |
b75a7d8f A |
161 | return; |
162 | } | |
163 | ||
164 | le_bool GnomeFontInstance::getGlyphPoint(LEGlyphID glyph, le_int32 pointNumber, LEPoint &point) const | |
165 | { | |
46f4442e | 166 | FT_Error error; |
b75a7d8f | 167 | |
46f4442e | 168 | error = FT_Load_Glyph(fFace, glyph, FT_LOAD_DEFAULT); |
b75a7d8f A |
169 | |
170 | if (error != 0) { | |
374ca955 | 171 | return FALSE; |
b75a7d8f A |
172 | } |
173 | ||
46f4442e | 174 | if (pointNumber >= fFace->glyph->outline.n_points) { |
374ca955 | 175 | return FALSE; |
b75a7d8f A |
176 | } |
177 | ||
46f4442e A |
178 | point.fX = fFace->glyph->outline.points[pointNumber].x >> 6; |
179 | point.fY = fFace->glyph->outline.points[pointNumber].y >> 6; | |
b75a7d8f | 180 | |
374ca955 | 181 | return TRUE; |
b75a7d8f A |
182 | } |
183 | ||
46f4442e A |
184 | void GnomeFontInstance::rasterizeGlyphs(cairo_t *cairo, const LEGlyphID *glyphs, le_int32 glyphCount, const float *positions, |
185 | le_int32 x, le_int32 y) const | |
b75a7d8f | 186 | { |
46f4442e A |
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]); | |
b75a7d8f | 192 | |
46f4442e A |
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; | |
b75a7d8f | 199 | } |
b75a7d8f | 200 | } |
46f4442e A |
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); | |
b75a7d8f | 207 | } |