contrib/OWB: add correct SDL dependency, fix compilers used
[AROS-Contrib.git] / freetype1 / lib / arch / amigaos / glyph.c
blob42429f1607ee241aa55e317bdb2c562d7204234d
1 /*
2 * Based on the code from the ttf.library by Richard Griffith.
3 */
4 #include "glyph.h"
5 #include "ttfglyphengine.h"
6 #include "ttfdebug.h"
8 #include <proto/exec.h>
9 #include <exec/memory.h>
10 #include <diskfont/oterrors.h>
12 /* convert freetype TT_F26Dot6 to Amiga FIXED */
13 #define F266toFX(x) (((x)<<10))
15 /* convert freetype TT_F26Dot6 to Integer */
16 #define F266toIR(x) (((x+32)>>6))
17 #define F266toI(x) ((x>>6))
19 /* return glyph index for charcode for current font of ge */
20 /* Convert an Amiga character to a glyph index. Actually, 2 translations
21 take place. First from 8 bit Amiga char to unicode, via the engine
22 codepage array. Then translate unicode to glyph index.
24 int char_to_glyph(TTF_GlyphEngine *ge,int charcode)
26 int gi=0;
28 if((ge->cmap_index) & 0x10000)
29 { /* raw encoding */
30 if(charcode>32 && charcode<128)
32 gi = charcode - 32 + ((ge->cmap_index) & 0xFFFF);
33 if(gi > ge->properties.num_Glyphs)
34 gi=0;
37 else
39 if(charcode<256)
40 gi=TT_Char_Index(ge->char_map, ge->codepage[charcode]);
41 else
42 { /* pick up the rest as unicode */
43 gi=TT_Char_Index( ge->char_map, charcode );
44 if(charcode==0x25A1) gi=0; /* "not a char" in bullet */
47 /* attempt to kludge in win symbol sets, blah, spit, yech! */
48 if(gi==0 && charcode>=0x20 && charcode<=255
49 && ge->properties.os2->usFirstCharIndex>=0xF000)
51 gi=TT_Char_Index( ge->char_map,
52 (charcode
53 - 0x20
54 + ge->properties.os2->usFirstCharIndex
60 return(gi);
63 /* call char_to_glyph for request_char in GlyphEngine and set
64 glyph_code appropriately
66 int UnicodeToGlyphIndex(TTF_GlyphEngine *ge)
68 ge->glyph_code= char_to_glyph(ge,ge->request_char);
70 return(ge->glyph_code);
74 /* render a glyph into GMap of engine
75 caller in expected to have allocated GMap space (but not bitmap)
77 void RenderGlyph(TTF_GlyphEngine *ge)
79 TT_Error error;
80 int xoffset, yoffset, do_transform;
81 TT_Pos trans_x=0;
82 TT_Pos trans_y=0;
83 TT_Raster_Map bitmap;
85 /* these two values indicate no glyph rendered */
86 ge->GMap->glm_Width = 0;
87 ge->GMap->glm_BitMap = NULL;
89 error = TT_Load_Glyph(ge->instance,
90 ge->glyph,
91 ge->glyph_code,
92 TTLOAD_DEFAULT);
93 /* TTLOAD_SCALE_GLYPH); */ /* test disable hinting */
94 if(error)
96 D(bug("Error loading glyph %ld code = %ld.\n",
97 (LONG)ge->request_char, (LONG) error ));
98 return;
101 /* we will need the metrics, no matter what transform we apply */
102 TT_Get_Glyph_Metrics( ge->glyph, &ge->metrics );
104 TT_Get_Glyph_Outline( ge->glyph, &ge->outline );
106 do_transform=(ge->do_rotate || ge->do_shear);
108 if(ge->do_shear)
109 /* apply shear transform to the outline */
110 TT_Transform_Outline( &ge->outline, &ge->shear_matrix );
112 if(ge->do_rotate)
114 /* apply rotate transform to the outline */
115 TT_Transform_Outline( &ge->outline, &ge->rotate_matrix );
117 /* position for next glyph, uses original metrics */
118 trans_x=ge->metrics.advance;
119 trans_y=0;
120 TT_Transform_Vector(&trans_x,
121 &trans_y,
122 &ge->rotate_matrix);
125 if(do_transform)
126 /* transform is applied, correct or get metrics */
127 TT_Get_Outline_BBox( &ge->outline, &ge->metrics.bbox );
129 bitmap.flow = TT_Flow_Down; /* bitmap should be top first */
131 /* how big is glyph */
132 bitmap.width =(ge->metrics.bbox.xMax - ge->metrics.bbox.xMin) / 64;
133 bitmap.rows =(ge->metrics.bbox.yMax - ge->metrics.bbox.yMin) / 64;
135 /* adjust bitmap to 4 byte (32 bit) alignment for width */
136 bitmap.width = (bitmap.width + 31) & -32;
137 bitmap.cols = bitmap.width / 8; /* byte count */
138 bitmap.size = bitmap.rows * bitmap.cols;
140 /* some (i.e. space) have no bitmap. Bullet.library returns
141 a OTERR_UnknownGlyph, so we will ultimately, too */
142 if(bitmap.size==0)
144 D(bug("no bitmap for glyph %ld\n",ge->request_char));
145 return;
148 /* bitmap.bitmap= AllocPooled(ge->GlyphPool,(ULONG)bitmap.size); */
149 bitmap.bitmap= AllocVec((ULONG)bitmap.size,MEMF_PUBLIC | MEMF_CLEAR);
151 if(bitmap.bitmap==NULL)
153 D(bug("bitmap allocation for %ld bytes failed\n",bitmap.size));
154 return;
157 xoffset = 0 - ge->metrics.bbox.xMin;
158 yoffset = 0 - ge->metrics.bbox.yMin;
160 TT_Translate_Outline( &ge->outline, xoffset, yoffset );
162 error=TT_Get_Outline_Bitmap( ge->engine, &ge->outline, &bitmap );
164 if(error)
166 D(bug("Error rendering glyph %ld code = %ld.\n",
167 (LONG)ge->request_char, (LONG) error ));
168 FreeVec(bitmap.bitmap);
169 return;
172 ge->GMap->glm_BMModulo = bitmap.cols;
173 ge->GMap->glm_BMRows = bitmap.rows;
174 ge->GMap->glm_BlackLeft = 0;
175 ge->GMap->glm_BlackTop = 0;
176 ge->GMap->glm_BlackWidth =
177 F266toIR(ge->metrics.bbox.xMax - ge->metrics.bbox.xMin);
179 ge->GMap->glm_BlackHeight = bitmap.rows;
181 if(!(ge->do_rotate))
183 ge->GMap->glm_XOrigin = ~F266toFX(ge->metrics.bearingX)+1;
184 ge->GMap->glm_YOrigin = F266toFX(ge->metrics.bearingY);
186 ge->GMap->glm_X0 = 0-F266toI(ge->metrics.bearingX);
187 ge->GMap->glm_Y0 = F266toI(ge->metrics.bbox.yMax);
189 ge->GMap->glm_X1 =
190 F266toI((ge->metrics.advance - ge->metrics.bearingX));
192 ge->GMap->glm_Y1 = ge->GMap->glm_Y0;
194 else
196 ge->GMap->glm_XOrigin = ~F266toFX(ge->metrics.bbox.xMin)+1;
197 ge->GMap->glm_YOrigin = F266toFX(ge->metrics.bbox.yMax);
198 ge->GMap->glm_X0 = 0-F266toI(ge->metrics.bbox.xMin);
199 ge->GMap->glm_Y0 = F266toI(ge->metrics.bbox.yMax);
201 ge->GMap->glm_X1 = F266toI(trans_x-ge->metrics.bbox.xMin);
203 ge->GMap->glm_Y1 = F266toI(ge->metrics.bbox.yMax-trans_y);
205 /* horizontal pixels per EM square as 16.16 */
207 ge->GMap->glm_Width =
208 (ge->metrics.advance << 10) /
209 (( ge->imetrics.x_ppem
210 * ge->corrected_upem)
211 / ge->properties.header->Units_Per_EM);
214 ge->GMap->glm_BitMap = bitmap.bitmap;
216 #if 0
217 D(bug("render glyph %ld to %ld\n",(LONG)ge->glyph_code,(LONG)ge->request_char));
219 D(bug(" bbox.xMin=%lx ",(LONG)ge->metrics.bbox.xMin));
220 D(bug("bbox.yMin=%lx ",(LONG)ge->metrics.bbox.yMin));
221 D(bug("bbox.xMax=%lx ",(LONG)ge->metrics.bbox.xMax));
222 D(bug("bbox.yMax=%lx\n",(LONG)ge->metrics.bbox.yMax));
224 D(bug(" horiBearingX=%lx ",(LONG)ge->metrics.horiBearingX));
225 D(bug("horiBearingY=%lx\n",(LONG)ge->metrics.horiBearingY));
227 D(bug(" vertBearingX=%lx ",(LONG)ge->metrics.vertBearingX));
228 D(bug("vertBearingY=%lx\n",(LONG)ge->metrics.vertBearingY));
230 D(bug(" horiAdvance=%lx ",(LONG)ge->metrics.horiAdvance));
231 D(bug("vertAdvance=%lx\n",(LONG)ge->metrics.vertAdvance));
232 #endif
233 #if 0
234 D(bug(" glm_BMModulo = %lx\n",(LONG)ge->GMap->glm_BMModulo));
235 D(bug(" glm_BMRows = %lx\n",(LONG)ge->GMap->glm_BMRows));
236 D(bug(" glm_BlackLeft = %lx\n",(LONG)ge->GMap->glm_BlackLeft));
237 D(bug(" glm_BlackTop = %lx\n",(LONG)ge->GMap->glm_BlackTop));
238 D(bug(" glm_BlackWidth = %lx\n",(LONG)ge->GMap->glm_BlackWidth));
239 D(bug(" glm_BlackHeight = %lx\n",(LONG)ge->GMap->glm_BlackHeight));
241 D(bug(" glm_XOrigin = %lx\n",(LONG)ge->GMap->glm_XOrigin));
242 D(bug(" glm_YOrigin = %lx\n",(LONG)ge->GMap->glm_YOrigin));
243 D(bug(" glm_X0 = %lx\n",(LONG)ge->GMap->glm_X0));
244 D(bug(" glm_Y0 = %lx\n",(LONG)ge->GMap->glm_Y0));
246 D(bug(" glm_X1 = %lx\n",(LONG)ge->GMap->glm_X1));
247 D(bug(" glm_Y1 = %lx\n",(LONG)ge->GMap->glm_Y1));
248 D(bug(" glm_Width = %lx\n",(LONG)ge->GMap->glm_Width));
249 #endif
252 /* set current glyph to no character glyph (#0)
253 assume Gmap already allocated
255 void XeroGlyph(TTF_GlyphEngine *ge)
257 #if 0
258 D(bug("Xeroing %ld\n",(LONG)i));
259 #endif
260 ge->glyph_code=0;
261 /* allocate GMap space */
262 ge->GMap=AllocVec((ULONG)sizeof(struct GlyphMap),
263 MEMF_PUBLIC | MEMF_CLEAR);
264 if(ge->GMap)
265 RenderGlyph(ge);
268 /* given an Amiga character, return a filled in GlyphMap */
269 struct GlyphMap *GetGlyph(TTF_GlyphEngine *ge)
271 if (ge->instance_changed)
273 /* reset everything first */
274 if(SetInstance(ge)!=OTERR_Success)
275 return NULL;
278 if (ge->cmap_index==NO_CMAP_SET && ChooseEncoding(ge)!=0)
279 return NULL;
281 #if 0
282 if(ge->request_char>255)
284 /* out of range */
285 XeroGlyph(ge);
286 return ge->GMap;
288 #endif
290 UnicodeToGlyphIndex(ge);
291 if(ge->glyph_code)
292 { /* has code, try to render */
293 /* first, get a GlyphMap structure to fill in */
294 ge->GMap=AllocVec((ULONG)sizeof(struct GlyphMap),
295 MEMF_PUBLIC | MEMF_CLEAR);
296 if(ge->GMap)
297 RenderGlyph(ge);
299 else
301 set_last_error(ge,OTERR_UnknownGlyph);
302 return(NULL);
305 /* odd ball glyph (includes SPACE, arrrgghhh) mimic bullet */
306 if (ge->GMap->glm_Width == 0)
308 set_last_error(ge,OTERR_UnknownGlyph);
309 FreeVec(ge->GMap);
310 return(NULL);
313 return ge->GMap;