2 * Based on the code from the ttf.library by Richard Griffith.
5 #include "ttfglyphengine.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
)
28 if((ge
->cmap_index
) & 0x10000)
30 if(charcode
>32 && charcode
<128)
32 gi
= charcode
- 32 + ((ge
->cmap_index
) & 0xFFFF);
33 if(gi
> ge
->properties
.num_Glyphs
)
40 gi
=TT_Char_Index(ge
->char_map
, ge
->codepage
[charcode
]);
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
,
54 + ge
->properties
.os2
->usFirstCharIndex
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
)
80 int xoffset
, yoffset
, do_transform
;
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
,
93 /* TTLOAD_SCALE_GLYPH); */ /* test disable hinting */
96 D(bug("Error loading glyph %ld code = %ld.\n",
97 (LONG
)ge
->request_char
, (LONG
) error
));
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
);
109 /* apply shear transform to the outline */
110 TT_Transform_Outline( &ge
->outline
, &ge
->shear_matrix
);
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
;
120 TT_Transform_Vector(&trans_x
,
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 */
144 D(bug("no bitmap for glyph %ld\n",ge
->request_char
));
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
));
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
);
166 D(bug("Error rendering glyph %ld code = %ld.\n",
167 (LONG
)ge
->request_char
, (LONG
) error
));
168 FreeVec(bitmap
.bitmap
);
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
;
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
);
190 F266toI((ge
->metrics
.advance
- ge
->metrics
.bearingX
));
192 ge
->GMap
->glm_Y1
= ge
->GMap
->glm_Y0
;
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
;
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
));
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
));
252 /* set current glyph to no character glyph (#0)
253 assume Gmap already allocated
255 void XeroGlyph(TTF_GlyphEngine
*ge
)
258 D(bug("Xeroing %ld\n",(LONG
)i
));
261 /* allocate GMap space */
262 ge
->GMap
=AllocVec((ULONG
)sizeof(struct GlyphMap
),
263 MEMF_PUBLIC
| MEMF_CLEAR
);
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
)
278 if (ge
->cmap_index
==NO_CMAP_SET
&& ChooseEncoding(ge
)!=0)
282 if(ge
->request_char
>255)
290 UnicodeToGlyphIndex(ge
);
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
);
301 set_last_error(ge
,OTERR_UnknownGlyph
);
305 /* odd ball glyph (includes SPACE, arrrgghhh) mimic bullet */
306 if (ge
->GMap
->glm_Width
== 0)
308 set_last_error(ge
,OTERR_UnknownGlyph
);