16 |
/****************************************************************************/ |
/****************************************************************************/ |
17 |
|
|
18 |
|
|
19 |
#include "ftcommon.i" |
#include "ftcommon.h" |
20 |
|
#include "common.h" |
21 |
#include <math.h> |
#include <math.h> |
22 |
|
|
23 |
|
/* the following header shouldn't be used in normal programs */ |
24 |
|
#include FT_INTERNAL_DEBUG_H |
25 |
|
#include FT_STROKER_H |
26 |
|
#include FT_SYNTHESIS_H |
27 |
|
|
28 |
|
#define MAXPTSIZE 500 /* dtp */ |
29 |
|
#define HEADER_HEIGHT 8 |
30 |
|
|
31 |
static FT_Error |
#ifdef CEIL |
32 |
Render_GammaGrid( void ) |
#undef CEIL |
33 |
{ |
#endif |
34 |
int g; |
#define CEIL( x ) ( ( (x) + 63 ) >> 6 ) |
|
int yside = 11; |
|
|
int xside = 10; |
|
|
int levels = 17; |
|
|
int gammas = 30; |
|
|
int x_0 = (bit.width - levels*xside)/2; |
|
|
int y_0 = (bit.rows - gammas*(yside+1))/2; |
|
|
int pitch = bit.pitch; |
|
|
|
|
|
if ( pitch < 0 ) |
|
|
pitch = -pitch; |
|
|
|
|
|
memset( bit.buffer, 100, pitch*bit.rows ); |
|
|
|
|
|
grGotobitmap( &bit ); |
|
|
|
|
|
for ( g = 1; g <= gammas; g += 1 ) |
|
|
{ |
|
|
double ggamma = g/10.0; |
|
|
char temp[6]; |
|
|
int y = y_0 + (yside+1)*(g-1); |
|
|
int nx, ny; |
|
|
|
|
|
unsigned char* line = bit.buffer + y*bit.pitch; |
|
|
|
|
|
if ( bit.pitch < 0 ) |
|
|
line -= bit.pitch*(bit.rows-1); |
|
|
|
|
|
line += x_0*3; |
|
|
|
|
|
grSetPixelMargin( x_0-32, y + (yside-8)/2 ); |
|
|
grGotoxy( 0, 0 ); |
|
|
|
|
|
sprintf( temp, "%.1f", ggamma ); |
|
|
grWrite( temp ); |
|
|
|
|
|
for ( ny = 0; ny < yside; ny++, line += bit.pitch ) |
|
|
{ |
|
|
unsigned char* dst = line; |
|
35 |
|
|
36 |
for ( nx = 0; nx < levels; nx++, dst += 3 * xside ) |
#define INIT_SIZE( size, start_x, start_y, step_x, step_y, x, y ) \ |
37 |
{ |
do { \ |
38 |
double p = nx/(double)(levels - 1); |
start_x = 4; \ |
39 |
int gm = (int)( 255.0 * pow( p, ggamma ) ); |
start_y = CEIL( size->metrics.height ) + 2 * HEADER_HEIGHT; \ |
40 |
|
step_x = CEIL( size->metrics.max_advance ); \ |
41 |
|
step_y = CEIL( size->metrics.height ) + 4; \ |
42 |
|
\ |
43 |
|
x = start_x; \ |
44 |
|
y = start_y; \ |
45 |
|
} while ( 0 ) |
46 |
|
|
47 |
|
#define X_TOO_LONG( x, size, display) \ |
48 |
|
( ( x ) + ( ( size )->metrics.max_advance >> 6 ) > ( display )->bitmap->width ) |
49 |
|
#define Y_TOO_LONG( y, size, display) \ |
50 |
|
( ( y ) >= ( display )->bitmap->rows ) |
51 |
|
|
52 |
|
enum { |
53 |
|
RENDER_MODE_ALL = 0, |
54 |
|
RENDER_MODE_EMBOLDEN, |
55 |
|
RENDER_MODE_STROKE, |
56 |
|
RENDER_MODE_TEXT, |
57 |
|
RENDER_MODE_WATERFALL, |
58 |
|
N_RENDER_MODES |
59 |
|
}; |
60 |
|
|
61 |
|
static struct { |
62 |
|
int render_mode; |
63 |
|
FT_Encoding encoding; |
64 |
|
int res; |
65 |
|
int ptsize; /* current point size */ |
66 |
|
double gamma; |
67 |
|
|
68 |
|
int debug; |
69 |
|
int trace_level; |
70 |
|
int font_index; |
71 |
|
int dump_cache_stats; /* do we need to dump cache statistics? */ |
72 |
|
int Num; /* current first index */ |
73 |
|
char* header; |
74 |
|
char header_buffer[256]; |
75 |
|
int Fail; |
76 |
|
|
77 |
|
} status = { RENDER_MODE_ALL, FT_ENCODING_NONE, 72, 48, 1.0 }; |
78 |
|
|
79 |
|
|
80 |
|
static FTDemo_Display* display; |
81 |
|
static FTDemo_Handle* handle; |
82 |
|
|
83 |
|
|
84 |
|
static const unsigned char* Text = (unsigned char*) |
85 |
|
"The quick brown fox jumps over the lazy dog 0123456789 " |
86 |
|
"\342\352\356\373\364\344\353\357\366\374\377\340\371\351\350\347 " |
87 |
|
"&#~\"\'(-`_^@)=+\260 ABCDEFGHIJKLMNOPQRSTUVWXYZ " |
88 |
|
"$\243^\250*\265\371%!\247:/;.,?<>"; |
89 |
|
|
|
memset( dst, gm, xside * 3 ); |
|
|
} |
|
|
} |
|
|
} |
|
|
return 0; |
|
|
} |
|
90 |
|
|
91 |
|
|
92 |
static FT_Error |
static FT_Error |
93 |
Render_Stroke( int first_index ) |
Render_Stroke( int num_indices, |
94 |
|
int first_index ) |
95 |
{ |
{ |
96 |
FT_F26Dot6 start_x, start_y, step_x, step_y, x, y; |
int start_x, start_y, step_x, step_y, x, y; |
97 |
FTC_ScalerRec scaler; |
int i; |
98 |
FT_Stroker stroker = NULL; |
FT_Size size; |
99 |
int i; |
FT_Stroker stroker = NULL; |
|
grBitmap bit3; |
|
100 |
|
|
101 |
|
|
102 |
start_x = 4; |
error = FTDemo_Get_Size( handle, &size ); |
|
start_y = 16 + current_font.height; |
|
103 |
|
|
104 |
|
if ( error ) |
105 |
|
{ |
106 |
|
/* probably a non-existent bitmap font size */ |
107 |
|
return error; |
108 |
|
} |
109 |
|
|
110 |
scaler.face_id = current_font.face_id; |
INIT_SIZE( size, start_x, start_y, step_x, step_y, x, y ); |
|
scaler.width = current_font.width; |
|
|
scaler.height = current_font.height; |
|
|
scaler.pixel = 1; |
|
111 |
|
|
112 |
error = FTC_Manager_LookupSize( cache_manager, &scaler, &size ); |
i = first_index; |
|
if ( error ) |
|
|
goto Exit; |
|
113 |
|
|
114 |
error = FT_Stroker_New( size->face->memory, &stroker ); |
error = FT_Stroker_New( size->face->memory, &stroker ); |
115 |
if ( error ) |
if ( error ) |
116 |
goto Exit; |
goto Exit; |
117 |
|
|
118 |
FT_Stroker_Set( stroker, |
FT_Stroker_Set( stroker, 64, |
|
64, |
|
119 |
FT_STROKER_LINECAP_ROUND, |
FT_STROKER_LINECAP_ROUND, |
120 |
FT_STROKER_LINEJOIN_ROUND, |
FT_STROKER_LINEJOIN_ROUND, |
121 |
0 ); |
0 ); |
122 |
|
|
123 |
step_x = size->metrics.x_ppem + 4; |
while ( i < num_indices ) |
124 |
step_y = ( size->metrics.height >> 6 ) + 4; |
{ |
125 |
|
int gindex; |
126 |
|
FT_GlyphSlot slot; |
127 |
|
|
|
x = start_x; |
|
|
y = start_y; |
|
128 |
|
|
129 |
i = first_index; |
if ( handle->encoding == FT_ENCODING_NONE ) |
130 |
i = first_index; |
gindex = i; |
131 |
|
else |
132 |
|
gindex = FTDemo_Get_Index( handle, i ); |
133 |
|
|
134 |
|
error = FT_Load_Glyph( size->face, gindex, |
135 |
|
handle->image_type.flags | FT_LOAD_NO_BITMAP ); |
136 |
|
slot = size->face->glyph; |
137 |
|
|
|
while ( i < face->num_glyphs ) |
|
|
{ |
|
|
int left, top, x_advance, y_advance, x_top, y_top; |
|
|
FT_GlyphSlot slot = size->face->glyph; |
|
|
FT_Glyph glyphp; |
|
|
|
|
|
#if 0 |
|
|
gindex = *(unsigned char*)p; |
|
|
if ( encoding == FT_ENCODING_NONE ) |
|
|
gindex = get_glyph_index( gindex ); |
|
|
#endif |
|
|
error = FT_Load_Glyph( size->face, i, FT_LOAD_NO_BITMAP ); |
|
138 |
if ( !error && slot->format == FT_GLYPH_FORMAT_OUTLINE ) |
if ( !error && slot->format == FT_GLYPH_FORMAT_OUTLINE ) |
139 |
{ |
{ |
140 |
FT_Glyph glyphb; |
FT_Glyph glyph; |
141 |
|
|
142 |
error = FT_Get_Glyph( slot, &glyphp ); |
error = FT_Get_Glyph( slot, &glyph ); |
143 |
if ( error ) |
if ( error ) |
144 |
goto Next; |
goto Next; |
145 |
|
|
146 |
error = FT_Glyph_Stroke( &glyphp, stroker, 1 ); |
error = FT_Glyph_Stroke( &glyph, stroker, 1 ); |
147 |
if ( error ) |
if ( error ) |
148 |
{ |
{ |
149 |
FT_Done_Glyph( glyphp ); |
FT_Done_Glyph( glyph ); |
150 |
goto Next; |
goto Next; |
151 |
} |
} |
152 |
|
|
153 |
error = glyph_to_bitmap( glyphp, &bit3, &left, &top, |
error = FTDemo_Draw_Glyph( handle, display, glyph, &x, &y ); |
154 |
&x_advance, &y_advance, (FT_Pointer*)&glyphb ); |
FT_Done_Glyph( glyph ); |
|
if ( !error ) |
|
|
{ |
|
|
/* now render the bitmap into the display surface */ |
|
|
x_top = x + left; |
|
|
y_top = y - top; |
|
|
grBlitGlyphToBitmap( &bit, &bit3, x_top, y_top, fore_color ); |
|
|
|
|
|
FT_Done_Glyph( glyphb ); |
|
|
FT_Done_Glyph( glyphp ); |
|
|
|
|
|
x += x_advance + 1; |
|
|
|
|
|
if ( x + size->metrics.x_ppem > bit.width ) |
|
|
{ |
|
|
x = start_x; |
|
|
y += step_y; |
|
|
|
|
|
if ( y >= bit.rows ) |
|
|
goto Exit; |
|
|
} |
|
|
} |
|
|
else |
|
|
FT_Done_Glyph( glyphp ); |
|
155 |
|
|
156 |
if ( error ) |
if ( error ) |
157 |
goto Next; |
status.Fail++; |
158 |
|
else if ( X_TOO_LONG( x, size, display ) ) |
159 |
|
{ |
160 |
|
x = start_x; |
161 |
|
y += step_y; |
162 |
|
|
163 |
|
if ( Y_TOO_LONG( y, size, display ) ) |
164 |
|
break; |
165 |
|
} |
166 |
} |
} |
167 |
else |
else |
168 |
{ |
{ |
169 |
Next: |
Next: |
170 |
Fail++; |
status.Fail++; |
171 |
} |
} |
172 |
|
|
173 |
i++; |
i++; |
181 |
} |
} |
182 |
|
|
183 |
|
|
|
/* most code is copied from Render_Stroke */ |
|
184 |
static FT_Error |
static FT_Error |
185 |
Render_Embolden( int first_index ) |
Render_Embolden( int num_indices, |
186 |
|
int first_index ) |
187 |
{ |
{ |
188 |
FT_F26Dot6 start_x, start_y, step_x, step_y, x, y; |
int start_x, start_y, step_x, step_y, x, y; |
189 |
FTC_ScalerRec scaler; |
int i; |
190 |
int i; |
FT_Size size; |
|
grBitmap bit3; |
|
|
|
|
|
|
|
|
start_x = 4; |
|
|
start_y = 16 + current_font.height; |
|
191 |
|
|
192 |
|
|
193 |
scaler.face_id = current_font.face_id; |
error = FTDemo_Get_Size( handle, &size ); |
|
scaler.width = current_font.width; |
|
|
scaler.height = current_font.height; |
|
|
scaler.pixel = 1; |
|
194 |
|
|
|
error = FTC_Manager_LookupSize( cache_manager, &scaler, &size ); |
|
195 |
if ( error ) |
if ( error ) |
196 |
goto Exit; |
{ |
197 |
|
/* probably a non-existent bitmap font size */ |
198 |
step_x = size->metrics.x_ppem + 4; |
return error; |
199 |
step_y = ( size->metrics.height >> 6 ) + 4; |
} |
200 |
|
|
201 |
x = start_x; |
INIT_SIZE( size, start_x, start_y, step_x, step_y, x, y ); |
|
y = start_y; |
|
202 |
|
|
203 |
i = first_index; |
i = first_index; |
|
i = first_index; |
|
204 |
|
|
205 |
while ( i < face->num_glyphs ) |
while ( i < num_indices ) |
206 |
{ |
{ |
207 |
int left, top, x_advance, y_advance, x_top, y_top; |
int gindex; |
208 |
FT_GlyphSlot slot = size->face->glyph; |
FT_Face face = size->face; |
209 |
FT_Glyph glyphp; |
|
210 |
|
if ( handle->encoding == FT_ENCODING_NONE ) |
211 |
#if 0 |
gindex = i; |
212 |
gindex = *(unsigned char*)p; |
else |
213 |
if ( encoding == FT_ENCODING_NONE ) |
gindex = FTDemo_Get_Index( handle, i ); |
214 |
gindex = get_glyph_index( gindex ); |
|
215 |
#endif |
error = FT_Load_Glyph( face, gindex, handle->image_type.flags ); |
|
error = FT_Load_Glyph( size->face, i, FT_LOAD_DEFAULT ); |
|
216 |
if ( !error ) |
if ( !error ) |
217 |
{ |
{ |
218 |
FT_Glyph glyphb; |
FT_GlyphSlot_Embolden( face->glyph ); |
219 |
|
|
220 |
|
error = FTDemo_Draw_Slot( handle, display, face->glyph, &x, &y ); |
221 |
|
|
|
FT_GlyphSlot_Embolden( slot ); |
|
|
error = FT_Get_Glyph( slot, &glyphp ); |
|
222 |
if ( error ) |
if ( error ) |
223 |
goto Next; |
status.Fail++; |
224 |
|
else if ( X_TOO_LONG( x, size, display ) ) |
|
error = glyph_to_bitmap( glyphp, &bit3, &left, &top, |
|
|
&x_advance, &y_advance, |
|
|
(FT_Pointer*)&glyphb ); |
|
|
if ( !error ) |
|
225 |
{ |
{ |
226 |
/* now render the bitmap into the display surface */ |
x = start_x; |
227 |
x_top = x + left; |
y += step_y; |
|
y_top = y - top; |
|
|
grBlitGlyphToBitmap( &bit, &bit3, x_top, y_top, fore_color ); |
|
|
|
|
|
FT_Done_Glyph( glyphb ); |
|
|
FT_Done_Glyph( glyphp ); |
|
|
|
|
|
x += x_advance + 1; |
|
|
|
|
|
if ( x + size->metrics.x_ppem > bit.width ) |
|
|
{ |
|
|
x = start_x; |
|
|
y += step_y; |
|
|
|
|
|
if ( y >= bit.rows ) |
|
|
goto Exit; |
|
|
} |
|
|
} |
|
|
else |
|
|
FT_Done_Glyph( glyphp ); |
|
228 |
|
|
229 |
if ( error ) |
if ( Y_TOO_LONG( y, size, display ) ) |
230 |
goto Next; |
break; |
231 |
|
} |
232 |
} |
} |
233 |
else |
else |
234 |
{ |
status.Fail++; |
|
Next: |
|
|
Fail++; |
|
|
} |
|
235 |
|
|
236 |
i++; |
i++; |
237 |
} |
} |
238 |
|
|
|
Exit: |
|
239 |
return error; |
return error; |
240 |
} |
} |
241 |
|
|
242 |
|
|
243 |
static FT_Error |
static FT_Error |
244 |
Render_All( int first_index ) |
Render_All( int num_indices, |
245 |
|
int first_index ) |
246 |
{ |
{ |
247 |
FT_F26Dot6 start_x, start_y, step_x, step_y, x, y; |
int start_x, start_y, step_x, step_y, x, y; |
248 |
FTC_ScalerRec scaler; |
int i; |
249 |
FT_Pointer glyf; |
FT_Size size; |
|
int i; |
|
|
grBitmap bit3; |
|
|
|
|
250 |
|
|
|
start_x = 4; |
|
|
start_y = 16 + current_font.height; |
|
251 |
|
|
252 |
scaler.face_id = current_font.face_id; |
error = FTDemo_Get_Size( handle, &size ); |
|
scaler.width = current_font.width; |
|
|
scaler.height = current_font.height; |
|
|
scaler.pixel = 1; |
|
253 |
|
|
|
error = FTC_Manager_LookupSize( cache_manager, &scaler, &size ); |
|
254 |
if ( error ) |
if ( error ) |
255 |
{ |
{ |
256 |
/* probably a non-existent bitmap font size */ |
/* probably a non-existent bitmap font size */ |
257 |
return error; |
return error; |
258 |
} |
} |
259 |
|
|
260 |
step_x = size->metrics.x_ppem + 4; |
INIT_SIZE( size, start_x, start_y, step_x, step_y, x, y ); |
|
step_y = ( size->metrics.height >> 6 ) + 4; |
|
|
|
|
|
x = start_x; |
|
|
y = start_y; |
|
261 |
|
|
262 |
i = first_index; |
i = first_index; |
263 |
|
|
|
#if 0 |
|
|
while ( i < first_index + 1 ) |
|
|
#else |
|
264 |
while ( i < num_indices ) |
while ( i < num_indices ) |
|
#endif |
|
265 |
{ |
{ |
266 |
int x_top, y_top, left, top, x_advance, y_advance; |
int gindex; |
267 |
|
|
268 |
|
|
269 |
error = get_glyph_bitmap( i, &bit3, &left, &top, |
if ( handle->encoding == FT_ENCODING_NONE ) |
270 |
&x_advance, &y_advance, &glyf ); |
gindex = i; |
271 |
if ( !error ) |
else |
272 |
{ |
gindex = FTDemo_Get_Index( handle, i ); |
|
/* now render the bitmap into the display surface */ |
|
|
x_top = x + left; |
|
|
y_top = y - top; |
|
|
grBlitGlyphToBitmap( &bit, &bit3, x_top, y_top, fore_color ); |
|
|
|
|
|
if ( glyf ) |
|
|
done_glyph_bitmap( glyf ); |
|
|
|
|
|
x += x_advance + 1; |
|
273 |
|
|
274 |
if ( x + size->metrics.x_ppem > bit.width ) |
error = FTDemo_Draw_Index( handle, display, gindex, &x, &y ); |
275 |
{ |
if ( error ) |
276 |
x = start_x; |
status.Fail++; |
277 |
y += step_y; |
else if ( X_TOO_LONG( x, size, display ) ) |
278 |
|
{ |
279 |
|
x = start_x; |
280 |
|
y += step_y; |
281 |
|
|
282 |
if ( y >= bit.rows ) |
if ( Y_TOO_LONG( y, size, display ) ) |
283 |
return FT_Err_Ok; |
break; |
|
} |
|
284 |
} |
} |
|
else |
|
|
Fail++; |
|
285 |
|
|
286 |
i++; |
i++; |
287 |
} |
} |
291 |
|
|
292 |
|
|
293 |
static FT_Error |
static FT_Error |
294 |
Render_Text( int first_index ) |
Render_Text( int num_indices, |
295 |
|
int first_index ) |
296 |
{ |
{ |
297 |
FT_F26Dot6 start_x, start_y, step_x, step_y, x, y; |
int start_x, start_y, step_x, step_y, x, y; |
298 |
FTC_ScalerRec scaler; |
int i; |
299 |
FT_Pointer glyf; |
FT_Size size; |
|
int i; |
|
|
grBitmap bit3; |
|
300 |
|
|
301 |
const unsigned char* p; |
const unsigned char* p; |
302 |
|
|
303 |
|
|
304 |
start_x = 4; |
error = FTDemo_Get_Size( handle, &size ); |
|
start_y = 16 + current_font.height; |
|
|
|
|
|
scaler.face_id = current_font.face_id; |
|
|
scaler.width = current_font.width; |
|
|
scaler.height = current_font.height; |
|
|
scaler.pixel = 1; |
|
|
|
|
|
error = FTC_Manager_LookupSize( cache_manager, &scaler, &size ); |
|
305 |
if ( error ) |
if ( error ) |
306 |
{ |
{ |
307 |
/* probably a non-existent bitmap font size */ |
/* probably a non-existent bitmap font size */ |
308 |
return error; |
return error; |
309 |
} |
} |
310 |
|
|
311 |
step_x = size->metrics.x_ppem + 4; |
INIT_SIZE( size, start_x, start_y, step_x, step_y, x, y ); |
|
step_y = ( size->metrics.height >> 6 ) + 4; |
|
|
|
|
|
x = start_x; |
|
|
y = start_y; |
|
312 |
|
|
313 |
i = first_index; |
i = first_index; |
314 |
|
|
315 |
p = Text; |
p = Text; |
316 |
|
|
317 |
while ( i > 0 && *p ) |
while ( i > 0 && *p ) |
318 |
{ |
{ |
319 |
p++; |
p++; |
322 |
|
|
323 |
while ( *p ) |
while ( *p ) |
324 |
{ |
{ |
|
int left, top, x_advance, y_advance, x_top, y_top; |
|
325 |
FT_UInt gindex; |
FT_UInt gindex; |
326 |
|
|
327 |
|
|
328 |
gindex = *(unsigned char*)p; |
gindex = FTDemo_Get_Index( handle, *p ); |
|
if ( encoding == FT_ENCODING_NONE ) |
|
|
gindex = get_glyph_index( gindex ); |
|
|
|
|
|
/* if a cmap is active, `get_glyph_bitmap' will convert the */ |
|
|
/* char code in `gindex' to a real glyph index */ |
|
|
error = get_glyph_bitmap( gindex, &bit3, &left, &top, |
|
|
&x_advance, &y_advance, &glyf ); |
|
|
if ( !error ) |
|
|
{ |
|
|
/* now render the bitmap into the display surface */ |
|
|
x_top = x + left; |
|
|
y_top = y - top; |
|
|
grBlitGlyphToBitmap( &bit, &bit3, x_top, y_top, fore_color ); |
|
|
|
|
|
if ( glyf ) |
|
|
done_glyph_bitmap( glyf ); |
|
|
|
|
|
x += x_advance + 1; |
|
329 |
|
|
330 |
if ( x + size->metrics.x_ppem > bit.width ) |
error = FTDemo_Draw_Index( handle, display, gindex, &x, &y ); |
331 |
{ |
if ( error ) |
332 |
x = start_x; |
status.Fail++; |
333 |
y += step_y; |
else if ( X_TOO_LONG( x, size, display ) ) |
334 |
|
{ |
335 |
|
x = start_x; |
336 |
|
y += step_y; |
337 |
|
|
338 |
if ( y >= bit.rows ) |
if ( Y_TOO_LONG( y, size, display ) ) |
339 |
return FT_Err_Ok; |
break; |
|
} |
|
340 |
} |
} |
|
else |
|
|
Fail++; |
|
341 |
|
|
342 |
p++; |
p++; |
343 |
} |
} |
349 |
static FT_Error |
static FT_Error |
350 |
Render_Waterfall( int first_size ) |
Render_Waterfall( int first_size ) |
351 |
{ |
{ |
352 |
FT_F26Dot6 start_x, start_y, step_x, step_y, x, y; |
int start_x, start_y, step_x, step_y, x, y; |
|
FT_Pointer glyf; |
|
353 |
int pt_size, max_size = 100000; |
int pt_size, max_size = 100000; |
354 |
grBitmap bit3; |
FT_Size size; |
355 |
|
FT_Face face; |
356 |
|
|
357 |
unsigned char text[256]; |
unsigned char text[256]; |
358 |
const unsigned char* p; |
const unsigned char* p; |
359 |
|
|
360 |
|
|
|
start_x = 4; |
|
|
start_y = 16; |
|
|
|
|
|
pt_size = first_size; |
|
|
|
|
361 |
{ |
{ |
362 |
error = FTC_Manager_LookupFace( cache_manager, current_font.face_id, &face ); |
error = FTC_Manager_LookupFace( handle->cache_manager, handle->image_type.face_id, &face ); |
363 |
if ( error ) |
if ( error ) |
364 |
{ |
{ |
365 |
/* can't access the font file. do not render anything */ |
/* can't access the font file. do not render anything */ |
366 |
fprintf( stderr, "can't access font file %p\n", current_font.face_id ); |
fprintf( stderr, "can't access font file %p\n", handle->image_type.face_id ); |
367 |
return 0; |
return 0; |
368 |
} |
} |
369 |
|
|
379 |
} |
} |
380 |
} |
} |
381 |
|
|
382 |
for (;;) |
start_x = 4; |
383 |
{ |
start_y = 2 * HEADER_HEIGHT; |
|
FTC_ScalerRec scaler; |
|
|
|
|
384 |
|
|
385 |
|
for ( pt_size = first_size; pt_size < max_size; pt_size++ ) |
386 |
|
{ |
387 |
sprintf( (char*)text, |
sprintf( (char*)text, |
388 |
"%d: the quick brown fox jumps over the lazy dog " |
"%d: the quick brown fox jumps over the lazy dog " |
389 |
"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", pt_size ); |
"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", pt_size ); |
390 |
|
|
391 |
p = text; |
p = text; |
392 |
|
|
393 |
set_current_pointsize( pt_size ); |
FTDemo_Set_Current_Pointsize( handle, pt_size, status.res ); |
|
|
|
|
if ( pt_size > max_size ) |
|
|
break; |
|
|
pt_size++; |
|
|
|
|
|
scaler.face_id = current_font.face_id; |
|
|
scaler.width = current_font.width; |
|
|
scaler.height = current_font.height; |
|
|
scaler.pixel = 1; |
|
394 |
|
|
395 |
error = FTC_Manager_LookupSize( cache_manager, &scaler, &size ); |
error = FTDemo_Get_Size( handle, &size ); |
396 |
if ( error ) |
if ( error ) |
397 |
{ |
{ |
398 |
/* probably a non-existent bitmap font size */ |
/* probably a non-existent bitmap font size */ |
399 |
continue; |
continue; |
400 |
} |
} |
401 |
|
|
402 |
step_x = size->metrics.x_ppem + 4; |
step_x = ( size->metrics.max_advance >> 6 ) + 4; |
403 |
step_y = ( size->metrics.height >> 6 ) + 1; |
step_y = ( size->metrics.height >> 6 ) + 1; |
404 |
|
|
405 |
x = start_x; |
x = start_x; |
407 |
|
|
408 |
start_y += step_y; |
start_y += step_y; |
409 |
|
|
410 |
if ( y >= bit.rows ) |
if ( y >= display->bitmap->rows ) |
411 |
break; |
break; |
412 |
|
|
413 |
while ( *p ) |
while ( *p ) |
414 |
{ |
{ |
|
int left, top, x_advance, y_advance, x_top, y_top; |
|
415 |
FT_UInt gindex; |
FT_UInt gindex; |
416 |
|
|
417 |
|
|
418 |
gindex = *(unsigned char*)p; |
gindex = FTDemo_Get_Index( handle, *p ); |
|
if ( encoding == FT_ENCODING_NONE ) |
|
|
gindex = get_glyph_index( gindex ); |
|
|
|
|
|
/* if a cmap is active, `get_glyph_bitmap' will convert the */ |
|
|
/* char code in `gindex' to a real glyph index */ |
|
|
error = get_glyph_bitmap( gindex, &bit3, &left, &top, |
|
|
&x_advance, &y_advance, &glyf ); |
|
|
if ( !error ) |
|
|
{ |
|
|
/* now render the bitmap into the display surface */ |
|
|
x_top = x + left; |
|
|
y_top = y - top; |
|
|
grBlitGlyphToBitmap( &bit, &bit3, x_top, y_top, fore_color ); |
|
|
|
|
|
if ( glyf ) |
|
|
done_glyph_bitmap( glyf ); |
|
|
|
|
|
x += x_advance + 1; |
|
419 |
|
|
420 |
if ( x + size->metrics.x_ppem > bit.width ) |
error = FTDemo_Draw_Index( handle, display, gindex, &x, &y ); |
421 |
break; |
if ( error ) |
422 |
} |
status.Fail++; |
423 |
else |
else if ( X_TOO_LONG( x, size, display ) ) |
424 |
Fail++; |
break; |
425 |
|
|
426 |
p++; |
p++; |
427 |
} |
} |
428 |
} |
} |
429 |
|
|
430 |
set_current_pointsize( first_size ); |
FTDemo_Set_Current_Pointsize( handle, first_size, status.res ); |
431 |
|
|
432 |
return FT_Err_Ok; |
return FT_Err_Ok; |
433 |
} |
} |
442 |
/*************************************************************************/ |
/*************************************************************************/ |
443 |
|
|
444 |
static void |
static void |
445 |
Help( void ) |
event_help( void ) |
446 |
{ |
{ |
447 |
grEvent dummy_event; |
grEvent dummy_event; |
448 |
|
|
449 |
|
|
450 |
Clear_Display(); |
FTDemo_Display_Clear( display ); |
451 |
grGotoxy( 0, 0 ); |
grGotoxy( 0, 0 ); |
452 |
grSetMargin( 2, 1 ); |
grSetMargin( 2, 1 ); |
453 |
grGotobitmap( &bit ); |
grGotobitmap( display->bitmap ); |
454 |
|
|
455 |
grWriteln( "FreeType Glyph Viewer - part of the FreeType test suite" ); |
grWriteln( "FreeType Glyph Viewer - part of the FreeType test suite" ); |
456 |
grLn(); |
grLn(); |
459 |
grLn(); |
grLn(); |
460 |
grWriteln( "Use the following keys:" ); |
grWriteln( "Use the following keys:" ); |
461 |
grLn(); |
grLn(); |
462 |
grWriteln( " F1 or ? : display this help screen" ); |
grWriteln( " F1 or ? : display this help screen" ); |
|
grWriteln( " a : toggle anti-aliasing" ); |
|
|
grWriteln( " L : cycle through rendering modes" ); |
|
|
grWriteln( " h : toggle outline hinting" ); |
|
|
grWriteln( " b : toggle embedded bitmaps" ); |
|
|
grWriteln( " l : toggle low precision rendering" ); |
|
|
grWriteln( " f : toggle forced auto-hinting" ); |
|
|
grWriteln( " space : toggle rendering mode" ); |
|
463 |
grLn(); |
grLn(); |
464 |
grWriteln( " c : toggle between cache modes" ); |
grWriteln( " a : toggle anti-aliasing" ); |
465 |
|
grWriteln( " b : toggle embedded bitmaps" ); |
466 |
|
grWriteln( " c : toggle between cache modes" ); |
467 |
|
grWriteln( " f : toggle forced auto-hinting" ); |
468 |
|
grWriteln( " h : toggle outline hinting" ); |
469 |
|
grWriteln( " l : toggle low precision rendering" ); |
470 |
grLn(); |
grLn(); |
471 |
grWriteln( " n : next font" ); |
grWriteln( " L : cycle through LCD modes" ); |
472 |
grWriteln( " p : previous font" ); |
grWriteln( " space : toggle rendering mode" ); |
473 |
|
grWriteln( " 1-5 : select rendering mode" ); |
474 |
grLn(); |
grLn(); |
475 |
grWriteln( " g : increase gamma by 0.1" ); |
grWriteln( " G : show gamma ramp" ); |
476 |
grWriteln( " v : decrease gamma by 0.1" ); |
grWriteln( " g : increase gamma by 0.1" ); |
477 |
|
grWriteln( " v : decrease gamma by 0.1" ); |
478 |
grLn(); |
grLn(); |
479 |
grWriteln( " K : show gamma ramp" ); |
grWriteln( " n : next font" ); |
480 |
|
grWriteln( " p : previous font" ); |
481 |
grLn(); |
grLn(); |
482 |
grWriteln( " Up : increase pointsize by 1 unit" ); |
grWriteln( " Up : increase pointsize by 1 unit" ); |
483 |
grWriteln( " Down : decrease pointsize by 1 unit" ); |
grWriteln( " Down : decrease pointsize by 1 unit" ); |
484 |
grWriteln( " Page Up : increase pointsize by 10 units" ); |
grWriteln( " Page Up : increase pointsize by 10 units" ); |
485 |
grWriteln( " Page Down : decrease pointsize by 10 units" ); |
grWriteln( " Page Down : decrease pointsize by 10 units" ); |
486 |
grLn(); |
grLn(); |
487 |
grWriteln( " Right : increment index" ); |
grWriteln( " Right : increment index" ); |
488 |
grWriteln( " Left : decrement index" ); |
grWriteln( " Left : decrement index" ); |
489 |
grLn(); |
grLn(); |
490 |
grWriteln( " F7 : decrement index by 10" ); |
grWriteln( " F7 : decrement index by 10" ); |
491 |
grWriteln( " F8 : increment index by 10" ); |
grWriteln( " F8 : increment index by 10" ); |
492 |
grWriteln( " F9 : decrement index by 100" ); |
grWriteln( " F9 : decrement index by 100" ); |
493 |
grWriteln( " F10 : increment index by 100" ); |
grWriteln( " F10 : increment index by 100" ); |
494 |
grWriteln( " F11 : decrement index by 1000" ); |
grWriteln( " F11 : decrement index by 1000" ); |
495 |
grWriteln( " F12 : increment index by 1000" ); |
grWriteln( " F12 : increment index by 1000" ); |
496 |
grLn(); |
grLn(); |
497 |
grWriteln( "press any key to exit this help screen" ); |
grWriteln( "press any key to exit this help screen" ); |
498 |
|
|
499 |
grRefreshSurface( surface ); |
grRefreshSurface( display->surface ); |
500 |
grListenSurface( surface, gr_event_key, &dummy_event ); |
grListenSurface( display->surface, gr_event_key, &dummy_event ); |
501 |
|
} |
502 |
|
|
503 |
|
|
504 |
|
static void |
505 |
|
event_gamma_grid( void ) |
506 |
|
{ |
507 |
|
grEvent dummy_event; |
508 |
|
int g; |
509 |
|
int yside = 11; |
510 |
|
int xside = 10; |
511 |
|
int levels = 17; |
512 |
|
int gammas = 30; |
513 |
|
int x_0 = (display->bitmap->width - levels*xside)/2; |
514 |
|
int y_0 = (display->bitmap->rows - gammas*(yside+1))/2; |
515 |
|
int pitch = display->bitmap->pitch; |
516 |
|
|
517 |
|
|
518 |
|
FTDemo_Display_Clear( display ); |
519 |
|
grGotobitmap( display->bitmap ); |
520 |
|
|
521 |
|
if ( pitch < 0 ) |
522 |
|
pitch = -pitch; |
523 |
|
|
524 |
|
memset( display->bitmap->buffer, 100, pitch*display->bitmap->rows ); |
525 |
|
|
526 |
|
grWriteCellString( display->bitmap, 0, 0, "Gamma grid", display->fore_color ); |
527 |
|
|
528 |
|
for ( g = 1; g <= gammas; g += 1 ) |
529 |
|
{ |
530 |
|
double ggamma = g / 10.0; |
531 |
|
char temp[6]; |
532 |
|
int y = y_0 + ( yside + 1 ) * ( g - 1 ); |
533 |
|
int nx, ny; |
534 |
|
|
535 |
|
unsigned char* line = display->bitmap->buffer + y * display->bitmap->pitch; |
536 |
|
|
537 |
|
if ( display->bitmap->pitch < 0 ) |
538 |
|
line -= display->bitmap->pitch * ( display->bitmap->rows - 1 ); |
539 |
|
|
540 |
|
line += x_0 * 3; |
541 |
|
|
542 |
|
grSetPixelMargin( x_0 - 32, y + ( yside - 8 ) / 2 ); |
543 |
|
grGotoxy( 0, 0 ); |
544 |
|
|
545 |
|
sprintf( temp, "%.1f", ggamma ); |
546 |
|
grWrite( temp ); |
547 |
|
|
548 |
|
for ( ny = 0; ny < yside; ny++, line += display->bitmap->pitch ) |
549 |
|
{ |
550 |
|
unsigned char* dst = line; |
551 |
|
|
552 |
|
for ( nx = 0; nx < levels; nx++, dst += 3 * xside ) |
553 |
|
{ |
554 |
|
double p = nx/(double)(levels - 1); |
555 |
|
int gm = (int)( 255.0 * pow( p, ggamma ) ); |
556 |
|
|
557 |
|
memset( dst, gm, xside * 3 ); |
558 |
|
} |
559 |
|
} |
560 |
|
} |
561 |
|
|
562 |
|
|
563 |
|
grRefreshSurface( display->surface ); |
564 |
|
grListenSurface( display->surface, gr_event_key, &dummy_event ); |
565 |
|
} |
566 |
|
|
567 |
|
|
568 |
|
static void |
569 |
|
event_gamma_change( double delta ) |
570 |
|
{ |
571 |
|
status.gamma += delta; |
572 |
|
|
573 |
|
if ( status.gamma > 3.0 ) |
574 |
|
status.gamma = 3.0; |
575 |
|
else if ( status.gamma < 0.0 ) |
576 |
|
status.gamma = 0.0; |
577 |
|
|
578 |
|
grSetGlyphGamma( status.gamma ); |
579 |
|
|
580 |
|
sprintf( status.header_buffer, "gamma changed to %.1f%s", |
581 |
|
status.gamma, status.gamma == 0.0 ? " (sRGB mode)" : "" ); |
582 |
|
|
583 |
|
status.header = status.header_buffer; |
584 |
|
} |
585 |
|
|
586 |
|
|
587 |
|
static void |
588 |
|
event_size_change( int delta ) |
589 |
|
{ |
590 |
|
status.ptsize += delta; |
591 |
|
|
592 |
|
if ( status.ptsize < 1 ) |
593 |
|
status.ptsize = 1; |
594 |
|
else if ( status.ptsize > MAXPTSIZE ) |
595 |
|
status.ptsize = MAXPTSIZE; |
596 |
|
|
597 |
|
FTDemo_Set_Current_Pointsize( handle, status.ptsize, status.res ); |
598 |
|
} |
599 |
|
|
600 |
|
|
601 |
|
static void |
602 |
|
event_index_change( int delta ) |
603 |
|
{ |
604 |
|
int num_indices = handle->current_font->num_indices; |
605 |
|
|
606 |
|
|
607 |
|
status.Num += delta; |
608 |
|
|
609 |
|
if ( status.Num < 0 ) |
610 |
|
status.Num = 0; |
611 |
|
else if ( status.Num >= num_indices ) |
612 |
|
status.Num = num_indices - 1; |
613 |
|
} |
614 |
|
|
615 |
|
|
616 |
|
static void |
617 |
|
event_render_mode_change( int delta ) |
618 |
|
{ |
619 |
|
|
620 |
|
if ( delta ) |
621 |
|
{ |
622 |
|
status.render_mode = ( status.render_mode + delta ) % N_RENDER_MODES; |
623 |
|
|
624 |
|
if ( status.render_mode < 0 ) |
625 |
|
status.render_mode += N_RENDER_MODES; |
626 |
|
} |
627 |
|
|
628 |
|
switch ( status.render_mode ) |
629 |
|
{ |
630 |
|
case RENDER_MODE_ALL: |
631 |
|
status.header = (char *)"rendering all glyphs in font"; |
632 |
|
break; |
633 |
|
case RENDER_MODE_EMBOLDEN: |
634 |
|
status.header = (char *)"rendering emboldened text"; |
635 |
|
break; |
636 |
|
case RENDER_MODE_STROKE: |
637 |
|
status.header = (char *)"rendering stroked text"; |
638 |
|
break; |
639 |
|
case RENDER_MODE_TEXT: |
640 |
|
status.header = (char *)"rendering test text string"; |
641 |
|
break; |
642 |
|
case RENDER_MODE_WATERFALL: |
643 |
|
status.header = (char *)"rendering glyph waterfall"; |
644 |
|
break; |
645 |
|
} |
646 |
|
} |
647 |
|
|
648 |
|
|
649 |
|
static void |
650 |
|
event_font_change( int delta ) |
651 |
|
{ |
652 |
|
int num_indices; |
653 |
|
|
654 |
|
|
655 |
|
if ( status.font_index + delta >= handle->num_fonts || |
656 |
|
status.font_index + delta < 0 ) |
657 |
|
return; |
658 |
|
|
659 |
|
status.font_index += delta; |
660 |
|
|
661 |
|
FTDemo_Set_Current_Font( handle, handle->fonts[status.font_index] ); |
662 |
|
FTDemo_Set_Current_Pointsize( handle, status.ptsize, status.res ); |
663 |
|
FTDemo_Update_Current_Flags( handle ); |
664 |
|
|
665 |
|
num_indices = handle->current_font->num_indices; |
666 |
|
|
667 |
|
if ( status.Num >= num_indices ) |
668 |
|
status.Num = num_indices - 1; |
669 |
} |
} |
670 |
|
|
671 |
|
|
672 |
static int |
static int |
673 |
Process_Event( grEvent* event ) |
Process_Event( grEvent* event ) |
674 |
{ |
{ |
675 |
int i; |
int ret = 0; |
676 |
|
|
677 |
|
if ( event->key >= '1' && event->key < '1' + N_RENDER_MODES ) |
678 |
|
{ |
679 |
|
status.render_mode = event->key - '1'; |
680 |
|
event_render_mode_change( 0 ); |
681 |
|
|
682 |
|
return ret; |
683 |
|
} |
684 |
|
|
685 |
switch ( event->key ) |
switch ( event->key ) |
686 |
{ |
{ |
687 |
case grKeyEsc: /* ESC or q */ |
case grKeyEsc: |
688 |
case grKEY( 'q' ): |
case grKEY( 'q' ): |
689 |
return 0; |
ret = 1; |
690 |
|
break; |
691 |
|
|
692 |
|
case grKeyF1: |
693 |
|
case grKEY( '?' ): |
694 |
|
event_help(); |
695 |
|
break; |
696 |
|
|
697 |
case grKEY( 'a' ): |
case grKEY( 'a' ): |
698 |
antialias = !antialias; |
handle->antialias = !handle->antialias; |
699 |
new_header = antialias ? (char *)"anti-aliasing is now on" |
status.header = handle->antialias |
700 |
: (char *)"anti-aliasing is now off"; |
? (char *)"anti-aliasing is now on" |
701 |
set_current_image_type(); |
: (char *)"anti-aliasing is now off"; |
|
return 1; |
|
702 |
|
|
703 |
case grKEY( 'g' ): |
FTDemo_Update_Current_Flags( handle ); |
704 |
if ( the_gamma >= 3.0 ) |
break; |
705 |
the_gamma = 3.0; |
|
706 |
else |
case grKEY( 'b' ): |
707 |
the_gamma += 0.1; |
handle->use_sbits = !handle->use_sbits; |
708 |
|
status.header = handle->use_sbits |
709 |
|
? (char *)"embedded bitmaps are now used when available" |
710 |
|
: (char *)"embedded bitmaps are now ignored"; |
711 |
|
|
712 |
goto SetGamma; |
FTDemo_Update_Current_Flags( handle ); |
713 |
|
break; |
714 |
|
|
715 |
case grKEY( 'v' ): |
case grKEY( 'c' ): |
716 |
if ( the_gamma <= 0 ) |
handle->use_sbits_cache = !handle->use_sbits_cache; |
717 |
the_gamma = 0; |
status.header = handle->use_sbits_cache |
718 |
else |
? (char *)"now using sbits cache" |
719 |
the_gamma -= 0.1; |
: (char *)"now using normal cache"; |
720 |
|
break; |
721 |
|
|
722 |
goto SetGamma; |
case grKEY( 'f' ): |
723 |
|
handle->autohint = !handle->autohint; |
724 |
|
status.header = handle->autohint |
725 |
|
? (char *)"forced auto-hinting is now on" |
726 |
|
: (char *)"forced auto-hinting is now off"; |
727 |
|
|
728 |
|
FTDemo_Update_Current_Flags( handle ); |
729 |
|
break; |
730 |
|
|
731 |
|
case grKEY( 'h' ): |
732 |
|
handle->hinted = !handle->hinted; |
733 |
|
status.header = handle->hinted |
734 |
|
? (char *)"glyph hinting is now active" |
735 |
|
: (char *)"glyph hinting is now ignored"; |
736 |
|
|
737 |
|
FTDemo_Update_Current_Flags( handle ); |
738 |
|
break; |
739 |
|
|
740 |
|
case grKEY( 'l' ): |
741 |
|
handle->low_prec = !handle->low_prec; |
742 |
|
status.header = handle->low_prec |
743 |
|
? (char *)"rendering precision is now forced to low" |
744 |
|
: (char *)"rendering precision is now normal"; |
745 |
|
|
746 |
SetGamma: |
FTDemo_Update_Current_Flags( handle ); |
|
grSetGlyphGamma( the_gamma ); |
|
|
sprintf( Header, "gamma changed to %.1f %s", the_gamma, the_gamma == 0.0 ? "(sRGB mode)" : "" ); |
|
|
new_header = Header; |
|
747 |
break; |
break; |
748 |
|
|
749 |
case grKEY( 'L' ): |
case grKEY( 'L' ): |
750 |
lcd_mode = ( lcd_mode + 1 ) % 6; |
handle->lcd_mode = ( handle->lcd_mode + 1 ) % N_LCD_MODES; |
751 |
|
|
752 |
switch ( lcd_mode ) |
switch ( handle->lcd_mode ) |
753 |
{ |
{ |
754 |
case 0: |
case LCD_MODE_AA: |
755 |
new_header = (char *)"normal anti-aliased rendering on"; |
status.header = (char *)"normal anti-aliased rendering on"; |
756 |
break; |
break; |
757 |
case 1: |
case LCD_MODE_LIGHT: |
758 |
new_header = (char *)"light anti-aliased rendering on"; |
status.header = (char *)"light anti-aliased rendering on"; |
759 |
break; |
break; |
760 |
case 2: |
case LCD_MODE_RGB: |
761 |
new_header = (char *)"horizontal LCD-optimized rendering on (RGB)"; |
status.header = (char *)"horizontal LCD-optimized rendering on (RGB)"; |
762 |
break; |
break; |
763 |
case 3: |
case LCD_MODE_BGR: |
764 |
new_header = (char *)"horizontal LCD-optimized rendering on (BGR)"; |
status.header = (char *)"horizontal LCD-optimized rendering on (BGR)"; |
765 |
break; |
break; |
766 |
case 4: |
case LCD_MODE_VRGB: |
767 |
new_header = (char *)"vertical LCD-optimized rendering on (RGB)"; |
status.header = (char *)"vertical LCD-optimized rendering on (RGB)"; |
768 |
break; |
break; |
769 |
case 5: |
case LCD_MODE_VBGR: |
770 |
new_header = (char *)"vertical LCD-optimized rendering on (BGR)"; |
status.header = (char *)"vertical LCD-optimized rendering on (BGR)"; |
771 |
break; |
break; |
|
default: |
|
|
; |
|
772 |
} |
} |
|
set_current_image_type(); |
|
|
return 1; |
|
|
|
|
|
case grKEY( 'c' ): |
|
|
use_sbits_cache = !use_sbits_cache; |
|
|
new_header = use_sbits_cache ? (char *)"now using sbits cache" |
|
|
: (char *)"now using normal cache"; |
|
|
return 1; |
|
773 |
|
|
774 |
case grKEY( 'f' ): |
FTDemo_Update_Current_Flags( handle ); |
775 |
autohint = !autohint; |
break; |
|
new_header = autohint ? (char *)"forced auto-hinting is now on" |
|
|
: (char *)"forced auto-hinting is now off"; |
|
|
set_current_image_type(); |
|
|
return 1; |
|
|
|
|
|
case grKEY( 'b' ): |
|
|
use_sbits = !use_sbits; |
|
|
new_header = use_sbits |
|
|
? (char *)"embedded bitmaps are now used when available" |
|
|
: (char *)"embedded bitmaps are now ignored"; |
|
|
set_current_image_type(); |
|
|
return 1; |
|
776 |
|
|
777 |
case grKEY( 'n' ): |
case grKEY( ' ' ): |
778 |
case grKEY( 'p' ): |
event_render_mode_change( 1 ); |
779 |
return (int)event->key; |
break; |
780 |
|
|
781 |
case grKEY( 'l' ): |
case grKEY( 'G' ): |
782 |
low_prec = !low_prec; |
event_gamma_grid(); |
|
new_header = low_prec |
|
|
? (char *)"rendering precision is now forced to low" |
|
|
: (char *)"rendering precision is now normal"; |
|
783 |
break; |
break; |
784 |
|
|
785 |
case grKEY( 'h' ): |
case grKEY( 'g' ): |
786 |
hinted = !hinted; |
event_gamma_change( 0.1 ); |
|
new_header = hinted ? (char *)"glyph hinting is now active" |
|
|
: (char *)"glyph hinting is now ignored"; |
|
|
set_current_image_type(); |
|
787 |
break; |
break; |
788 |
|
|
789 |
case grKEY( 'K' ): |
case grKEY( 'v' ): |
790 |
render_mode = RENDER_MODE_GAMMAGRID; |
event_gamma_change( -0.1 ); |
|
new_header = (char*)"rendering gamma grid"; |
|
791 |
break; |
break; |
792 |
|
|
793 |
case grKEY( ' ' ): |
case grKEY( 'n' ): |
794 |
render_mode = ( render_mode + 1 ) % RENDER_MODE_GAMMAGRID; |
event_font_change( 1 ); |
|
switch ( render_mode ) |
|
|
{ |
|
|
case RENDER_MODE_ALL: |
|
|
new_header = (char*)"rendering all glyphs in font"; |
|
|
break; |
|
|
case RENDER_MODE_EMBOLDEN: |
|
|
new_header = (char*)"rendering emboldened text"; |
|
|
break; |
|
|
case RENDER_MODE_STROKE: |
|
|
new_header = (char*)"rendering stroked text"; |
|
|
break; |
|
|
case RENDER_MODE_TEXT: |
|
|
new_header = (char*)"rendering test text string"; |
|
|
break; |
|
|
case RENDER_MODE_WATERFALL: |
|
|
new_header = (char*)"rendering glyph waterfall"; |
|
|
break; |
|
|
case RENDER_MODE_GAMMAGRID: /* never happen */ |
|
|
new_header = (char*)"rendering gamma grid"; |
|
|
break; |
|
|
} |
|
795 |
break; |
break; |
796 |
|
|
797 |
case grKeyF1: |
case grKEY( 'p' ): |
798 |
case grKEY( '?' ): |
event_font_change( -1 ); |
799 |
Help(); |
break; |
|
return 1; |
|
800 |
|
|
801 |
case grKeyPageUp: i = 10; goto Do_Scale; |
case grKeyUp: event_size_change( 1 ); break; |
802 |
case grKeyPageDown: i = -10; goto Do_Scale; |
case grKeyDown: event_size_change( -1 ); break; |
803 |
case grKeyUp: i = 1; goto Do_Scale; |
case grKeyPageUp: event_size_change( 10 ); break; |
804 |
case grKeyDown: i = -1; goto Do_Scale; |
case grKeyPageDown: event_size_change( -10 ); break; |
805 |
|
|
806 |
case grKeyLeft: i = -1; goto Do_Glyph; |
case grKeyLeft: event_index_change( -1 ); break; |
807 |
case grKeyRight: i = 1; goto Do_Glyph; |
case grKeyRight: event_index_change( 1 ); break; |
808 |
case grKeyF7: i = -10; goto Do_Glyph; |
case grKeyF7: event_index_change( -10 ); break; |
809 |
case grKeyF8: i = 10; goto Do_Glyph; |
case grKeyF8: event_index_change( 10 ); break; |
810 |
case grKeyF9: i = -100; goto Do_Glyph; |
case grKeyF9: event_index_change( -100 ); break; |
811 |
case grKeyF10: i = 100; goto Do_Glyph; |
case grKeyF10: event_index_change( 100 ); break; |
812 |
case grKeyF11: i = -1000; goto Do_Glyph; |
case grKeyF11: event_index_change( -1000 ); break; |
813 |
case grKeyF12: i = 1000; goto Do_Glyph; |
case grKeyF12: event_index_change( 1000 ); break; |
814 |
|
|
815 |
default: |
default: |
816 |
; |
; |
817 |
} |
} |
|
return 1; |
|
|
|
|
|
Do_Scale: |
|
|
ptsize += i; |
|
|
if ( ptsize < 1 ) ptsize = 1; |
|
|
if ( ptsize > MAXPTSIZE ) ptsize = MAXPTSIZE; |
|
|
return 1; |
|
|
|
|
|
Do_Glyph: |
|
|
Num += i; |
|
|
if ( Num < 0 ) Num = 0; |
|
|
if ( Num >= num_indices ) Num = num_indices - 1; |
|
818 |
|
|
819 |
return 1; |
return ret; |
820 |
} |
} |
821 |
|
|
822 |
|
|
823 |
|
static char* |
824 |
|
error_message( FT_Error error_code ) |
825 |
|
{ |
826 |
|
FT_Face face; |
827 |
|
const char* basename; |
828 |
|
|
829 |
|
|
830 |
|
error = FTC_Manager_LookupFace( handle->cache_manager, |
831 |
|
handle->image_type.face_id, &face ); |
832 |
|
if ( error ) |
833 |
|
PanicZ( "can't access font file" ); |
834 |
|
|
835 |
|
basename = ft_basename( handle->current_font->filepathname ); |
836 |
|
|
837 |
|
switch ( error_code ) |
838 |
|
{ |
839 |
|
case FT_Err_Ok: |
840 |
|
sprintf( status.header_buffer, "%s %s (file `%s')", face->family_name, |
841 |
|
face->style_name, basename ); |
842 |
|
break; |
843 |
|
case FT_Err_Invalid_Pixel_Size: |
844 |
|
sprintf( status.header_buffer, "Invalid pixel size (file `%s')", basename ); |
845 |
|
break; |
846 |
|
case FT_Err_Invalid_PPem: |
847 |
|
sprintf( status.header_buffer, "Invalid ppem value (file `%s')", basename ); |
848 |
|
break; |
849 |
|
default: |
850 |
|
sprintf( status.header_buffer, "File `%s': error 0x%04x", basename, |
851 |
|
(FT_UShort)error_code ); |
852 |
|
break; |
853 |
|
} |
854 |
|
|
855 |
|
return status.header_buffer; |
856 |
|
} |
857 |
|
|
858 |
static void |
static void |
859 |
usage( char* execname ) |
usage( char* execname ) |
860 |
{ |
{ |
862 |
fprintf( stderr, "ftview: simple glyph viewer -- part of the FreeType project\n" ); |
fprintf( stderr, "ftview: simple glyph viewer -- part of the FreeType project\n" ); |
863 |
fprintf( stderr, "-----------------------------------------------------------\n" ); |
fprintf( stderr, "-----------------------------------------------------------\n" ); |
864 |
fprintf( stderr, "\n" ); |
fprintf( stderr, "\n" ); |
865 |
fprintf( stderr, "Usage: %s [options below] ppem fontname[.ttf|.ttc] ...\n", |
fprintf( stderr, "Usage: %s [status below] ppem fontname[.ttf|.ttc] ...\n", |
866 |
execname ); |
execname ); |
867 |
fprintf( stderr, "\n" ); |
fprintf( stderr, "\n" ); |
868 |
fprintf( stderr, " -r R use resolution R dpi (default: 72 dpi)\n" ); |
fprintf( stderr, " -r R use resolution R dpi (default: 72 dpi)\n" ); |
875 |
} |
} |
876 |
|
|
877 |
|
|
878 |
int |
static void |
879 |
main( int argc, |
parse_cmdline( int* argc, |
880 |
char* argv[] ) |
char** argv[] ) |
881 |
{ |
{ |
882 |
int old_ptsize, orig_ptsize, font_index; |
char* execname; |
883 |
int first_index = 0; |
int option; |
|
int XisSetup = 0; |
|
|
char* execname; |
|
|
int option; |
|
|
const char* Header_format; |
|
|
|
|
|
grEvent event; |
|
884 |
|
|
885 |
|
|
886 |
execname = ft_basename( argv[0] ); |
execname = ft_basename( (*argv)[0] ); |
887 |
|
|
888 |
while ( 1 ) |
while ( 1 ) |
889 |
{ |
{ |
890 |
option = getopt( argc, argv, "Dde:f:l:r:" ); |
option = getopt( *argc, *argv, "Dde:f:l:r:" ); |
891 |
|
|
892 |
if ( option == -1 ) |
if ( option == -1 ) |
893 |
break; |
break; |
895 |
switch ( option ) |
switch ( option ) |
896 |
{ |
{ |
897 |
case 'd': |
case 'd': |
898 |
debug = 1; |
status.debug = 1; |
899 |
break; |
break; |
900 |
|
|
901 |
case 'D': |
case 'D': |
902 |
dump_cache_stats = 1; |
status.dump_cache_stats = 1; |
903 |
break; |
break; |
904 |
|
|
905 |
case 'e': |
case 'e': |
906 |
encoding = (FT_Encoding)make_tag( optarg ); |
status.encoding = FTDemo_Make_Encoding_Tag( optarg ); |
907 |
break; |
break; |
908 |
|
|
909 |
case 'f': |
case 'f': |
910 |
first_index = atoi( optarg ); |
status.Num = atoi( optarg ); |
911 |
break; |
break; |
912 |
|
|
913 |
case 'l': |
case 'l': |
914 |
trace_level = atoi( optarg ); |
status.trace_level = atoi( optarg ); |
915 |
if ( trace_level < 1 || trace_level > 7 ) |
if ( status.trace_level < 1 || status.trace_level > 7 ) |
916 |
usage( execname ); |
usage( execname ); |
917 |
break; |
break; |
918 |
|
|
919 |
case 'r': |
case 'r': |
920 |
res = atoi( optarg ); |
status.res = atoi( optarg ); |
921 |
if ( res < 1 ) |
if ( status.res < 1 ) |
922 |
usage( execname ); |
usage( execname ); |
923 |
break; |
break; |
924 |
|
|
928 |
} |
} |
929 |
} |
} |
930 |
|
|
931 |
argc -= optind; |
*argc -= optind; |
932 |
argv += optind; |
*argv += optind; |
933 |
|
|
934 |
Header_format = encoding != FT_ENCODING_NONE |
if ( *argc <= 1 ) |
|
? "at %d points, first char code = 0x%x" |
|
|
: "at %d points, first glyph index = %d"; |
|
|
|
|
|
if ( argc <= 1 ) |
|
935 |
usage( execname ); |
usage( execname ); |
936 |
|
|
937 |
if ( sscanf( argv[0], "%d", &orig_ptsize ) != 1 ) |
status.ptsize = atoi( *argv[0] ); |
938 |
orig_ptsize = 64; |
if ( status.ptsize == 0 ) |
939 |
|
status.ptsize = 64; |
940 |
|
|
941 |
|
(*argc)--; |
942 |
|
(*argv)++; |
943 |
|
} |
944 |
|
|
945 |
|
|
946 |
|
int |
947 |
|
main( int argc, |
948 |
|
char* argv[] ) |
949 |
|
{ |
950 |
|
grEvent event; |
951 |
|
const char* header_format; |
952 |
|
|
953 |
|
|
954 |
|
parse_cmdline( &argc, &argv ); |
955 |
|
|
956 |
#if FREETYPE_MAJOR == 2 && FREETYPE_MINOR == 0 && FREETYPE_PATCH <= 8 |
#if FREETYPE_MAJOR == 2 && FREETYPE_MINOR == 0 && FREETYPE_PATCH <= 8 |
957 |
if ( debug ) |
if ( status.debug ) |
958 |
{ |
{ |
959 |
# ifdef FT_DEBUG_LEVEL_TRACE |
# ifdef FT_DEBUG_LEVEL_TRACE |
960 |
FT_SetTraceLevel( trace_any, (FT_Byte)trace_level ); |
FT_SetTraceLevel( trace_any, (FT_Byte)status.trace_level ); |
961 |
# else |
# else |
962 |
trace_level = 0; |
status.trace_level = 0; |
963 |
# endif |
# endif |
964 |
} |
} |
965 |
#elif 0 |
#elif 0 |
966 |
/* "setenv/putenv" is not ANSI and I don't want to mess */ |
/* "setenv/putenv" is not ANSI and I don't want to mess */ |
967 |
/* with this portability issue right now.. */ |
/* with this portability issue right now.. */ |
968 |
if ( debug ) |
if ( status.debug ) |
969 |
{ |
{ |
970 |
char temp[32]; |
char temp[32]; |
971 |
|
|
972 |
sprintf( temp, "any=%d", trace_level ); |
sprintf( temp, "any=%d", status.trace_level ); |
973 |
setenv( "FT2_DEBUG", temp ); |
setenv( "FT2_DEBUG", temp ); |
974 |
} |
} |
975 |
#endif |
#endif |
976 |
|
|
977 |
|
header_format = status.encoding != FT_ENCODING_NONE |
978 |
|
? "at %d points, first char code = 0x%x" |
979 |
|
: "at %d points, first glyph index = %d"; |
980 |
|
|
981 |
/* Initialize engine */ |
/* Initialize engine */ |
982 |
init_freetype(); |
handle = FTDemo_New( status.encoding ); |
983 |
|
|
|
argc--; |
|
|
argv++; |
|
984 |
for ( ; argc > 0; argc--, argv++ ) |
for ( ; argc > 0; argc--, argv++ ) |
985 |
install_font_file( argv[0] ); |
FTDemo_Install_Font( handle, argv[0] ); |
986 |
|
|
987 |
if ( num_fonts == 0 ) |
if ( handle->num_fonts == 0 ) |
988 |
PanicZ( "could not find/open any font file" ); |
PanicZ( "could not find/open any font file" ); |
989 |
|
|
990 |
font_index = 0; |
display = FTDemo_Display_New( gr_pixel_mode_rgb24 ); |
991 |
ptsize = orig_ptsize; |
if ( !display ) |
992 |
|
PanicZ( "could not allocate display surface" ); |
|
NewFile: |
|
|
set_current_face( fonts[font_index] ); |
|
|
set_current_pointsize( ptsize ); |
|
|
set_current_image_type(); |
|
|
num_indices = fonts[font_index]->num_indices; |
|
|
|
|
|
error = FTC_Manager_LookupFace( cache_manager, |
|
|
current_font.face_id, &face ); |
|
|
if ( error ) |
|
|
{ |
|
|
/* can't access the font file; do not render anything */ |
|
|
fprintf( stderr, "can't access font file %p\n", |
|
|
current_font.face_id ); |
|
|
exit( 1 ); |
|
|
} |
|
|
|
|
|
/* initialize graphics if needed */ |
|
|
if ( !XisSetup ) |
|
|
{ |
|
|
XisSetup = 1; |
|
|
Init_Display(); |
|
|
} |
|
|
|
|
|
grSetTitle( surface, "FreeType Glyph Viewer - press F1 for help" ); |
|
|
old_ptsize = ptsize; |
|
993 |
|
|
994 |
if ( num_fonts >= 1 ) |
memset( display->fore_color.chroma, 0, 4 ); |
995 |
{ |
memset( display->back_color.chroma, 0xff, 4 ); |
996 |
Fail = 0; |
grSetTitle( display->surface, "FreeType Glyph Viewer - press F1 for help" ); |
|
Num = first_index; |
|
997 |
|
|
998 |
if ( Num >= num_indices ) |
status.Fail = 0; |
|
Num = num_indices - 1; |
|
999 |
|
|
1000 |
if ( Num < 0 ) |
event_font_change( 0 ); |
|
Num = 0; |
|
|
} |
|
1001 |
|
|
1002 |
for ( ;; ) |
for ( ;; ) |
1003 |
{ |
{ |
1004 |
int key; |
FTDemo_Display_Clear( display ); |
1005 |
|
|
1006 |
|
switch ( status.render_mode ) |
|
Clear_Display(); |
|
|
|
|
|
if ( num_fonts >= 1 ) |
|
1007 |
{ |
{ |
1008 |
error = FT_Err_Ok; |
case RENDER_MODE_ALL: |
1009 |
|
error = Render_All( handle->current_font->num_indices, status.Num ); |
1010 |
|
break; |
|
switch ( render_mode ) |
|
|
{ |
|
|
case RENDER_MODE_ALL: |
|
|
error = Render_All( Num ); |
|
|
break; |
|
|
|
|
|
case RENDER_MODE_EMBOLDEN: |
|
|
error = Render_Embolden( Num ); |
|
|
break; |
|
|
|
|
|
case RENDER_MODE_STROKE: |
|
|
error = Render_Stroke( Num ); |
|
|
break; |
|
|
|
|
|
case RENDER_MODE_TEXT: |
|
|
error = Render_Text( Num ); |
|
|
break; |
|
1011 |
|
|
1012 |
case RENDER_MODE_WATERFALL: |
case RENDER_MODE_EMBOLDEN: |
1013 |
error = Render_Waterfall( ptsize ); |
error = Render_Embolden( handle->current_font->num_indices, status.Num ); |
1014 |
break; |
break; |
1015 |
|
|
1016 |
case RENDER_MODE_GAMMAGRID: |
case RENDER_MODE_STROKE: |
1017 |
error = Render_GammaGrid(); |
error = Render_Stroke( handle->current_font->num_indices, status.Num ); |
1018 |
render_mode = RENDER_MODE_ALL; |
break; |
|
} |
|
1019 |
|
|
1020 |
if ( !new_header ) |
case RENDER_MODE_TEXT: |
1021 |
{ |
error = Render_Text( handle->current_font->num_indices, status.Num ); |
1022 |
if ( size ) |
break; |
|
sprintf( Header, "%s %s (file `%s')", |
|
|
face->family_name, |
|
|
face->style_name, |
|
|
ft_basename( ((PFont)current_font.face_id)->filepathname ) ); |
|
|
else |
|
|
{ |
|
|
if ( error == FT_Err_Invalid_Pixel_Size ) |
|
|
sprintf( Header, "Invalid pixel size (file `%s')", |
|
|
ft_basename( ((PFont)current_font.face_id)->filepathname ) ); |
|
|
else if ( error == FT_Err_Invalid_PPem ) |
|
|
sprintf( Header, "Invalid ppem value (file `%s')", |
|
|
ft_basename( ((PFont)current_font.face_id)->filepathname ) ); |
|
|
else |
|
|
sprintf( Header, "File `%s': error 0x%04x", |
|
|
ft_basename( ((PFont)current_font.face_id)->filepathname ), |
|
|
(FT_UShort)error ); |
|
|
} |
|
1023 |
|
|
1024 |
new_header = Header; |
case RENDER_MODE_WATERFALL: |
1025 |
} |
error = Render_Waterfall( status.ptsize ); |
1026 |
|
break; |
1027 |
|
} |
1028 |
|
|
1029 |
grWriteCellString( &bit, 0, 0, new_header, fore_color ); |
if ( !status.header ) |
1030 |
new_header = 0; |
status.header = error_message( error ); |
1031 |
|
|
1032 |
sprintf( Header, Header_format, ptsize, Num ); |
/* write header */ |
1033 |
} |
grWriteCellString( display->bitmap, 0, 0, status.header, display->fore_color ); |
1034 |
|
sprintf( status.header_buffer, header_format, status.ptsize, status.Num ); |
1035 |
|
grWriteCellString( display->bitmap, 0, HEADER_HEIGHT, status.header_buffer, |
1036 |
|
display->fore_color ); |
1037 |
|
|
1038 |
grWriteCellString( &bit, 0, 8, Header, fore_color ); |
grRefreshSurface( display->surface ); |
|
grRefreshSurface( surface ); |
|
1039 |
|
|
1040 |
if ( dump_cache_stats ) |
if ( status.dump_cache_stats ) |
1041 |
{ |
{ |
1042 |
/* dump simple cache manager statistics */ |
/* dump simple cache manager statistics */ |
1043 |
fprintf( stderr, "cache manager [ nodes, bytes, average ] = " |
fprintf( stderr, "cache manager [ nodes, bytes, average ] = " |
1044 |
" [ %d, %ld, %f ]\n", |
" [ %d, %ld, %f ]\n", |
1045 |
cache_manager->num_nodes, |
handle->cache_manager->num_nodes, |
1046 |
cache_manager->cur_weight, |
handle->cache_manager->cur_weight, |
1047 |
cache_manager->num_nodes > 0 |
handle->cache_manager->num_nodes > 0 |
1048 |
? cache_manager->cur_weight * 1.0 / |
? handle->cache_manager->cur_weight * 1.0 / |
1049 |
cache_manager->num_nodes |
handle->cache_manager->num_nodes |
1050 |
: 0.0 ); |
: 0.0 ); |
1051 |
} |
} |
1052 |
|
|
1053 |
grListenSurface( surface, 0, &event ); |
status.header = 0; |
1054 |
if ( !( key = Process_Event( &event ) ) ) |
grListenSurface( display->surface, 0, &event ); |
1055 |
goto End; |
if ( Process_Event( &event ) ) |
1056 |
|
break; |
|
if ( key == 'n' ) |
|
|
{ |
|
|
if ( font_index + 1 < num_fonts ) |
|
|
font_index++; |
|
|
|
|
|
goto NewFile; |
|
|
} |
|
|
|
|
|
if ( key == 'p' ) |
|
|
{ |
|
|
if ( font_index > 0 ) |
|
|
font_index--; |
|
|
|
|
|
goto NewFile; |
|
|
} |
|
|
|
|
|
if ( ptsize != old_ptsize ) |
|
|
{ |
|
|
set_current_pointsize( ptsize ); |
|
|
old_ptsize = ptsize; |
|
|
} |
|
1057 |
} |
} |
1058 |
|
|
|
End: |
|
1059 |
printf( "Execution completed successfully.\n" ); |
printf( "Execution completed successfully.\n" ); |
1060 |
printf( "Fails = %d\n", Fail ); |
printf( "Fails = %d\n", status.Fail ); |
1061 |
|
|
1062 |
done_freetype(); |
FTDemo_Display_Done( display ); |
1063 |
|
FTDemo_Done( handle ); |
1064 |
exit( 0 ); /* for safety reasons */ |
exit( 0 ); /* for safety reasons */ |
1065 |
|
|
1066 |
return 0; /* never reached */ |
return 0; /* never reached */ |
1067 |
} |
} |
1068 |
|
|