when dropping into user mode make sure endian is set
[AROS.git] / workbench / system / ftmanager / fontbitmap_class.c
blob8622cd0ac45b51aa8a9238779763dde35bd0bc26
1 #include <aros/debug.h>
2 #include <libraries/mui.h>
3 #include <graphics/gfx.h>
4 #include <diskfont/diskfonttag.h>
6 #include <proto/alib.h>
7 #include <proto/exec.h>
8 #include <proto/graphics.h>
9 #include <proto/intuition.h>
10 #include <proto/utility.h>
11 #include <proto/muimaster.h>
12 #include <proto/freetype2.h>
14 #include <string.h>
16 #include "fontbitmap_class.h"
17 #include "globals.h"
19 struct FontBitmapData
21 int Width, Height;
22 struct BitMap BitMap;
23 struct BitMap *GrayBitMap;
26 typedef struct FontBitmapData FontBitmapData;
28 IPTR fbNew(Class *cl, Object *o, struct opSet *msg)
30 struct opSet method;
31 struct TagItem tags[5];
32 STRPTR filename = (STRPTR)GetTagData(MUIA_FontBitmap_Filename, (IPTR) NULL, msg->ops_AttrList);
33 STRPTR string = (STRPTR)GetTagData(MUIA_FontBitmap_String, (IPTR) "?", msg->ops_AttrList);
34 struct TagItem *otags = (struct TagItem *)GetTagData(MUIA_FontBitmap_OTags,
35 (IPTR) NULL, msg->ops_AttrList);
36 struct
38 struct GlyphMap *glyph;
39 int x;
40 int y;
41 } *info;
42 APTR engine;
43 struct BitMap bitmap;
44 struct BitMap *gray_bitmap = NULL;
45 int width, height;
46 int length = strlen(string);
47 int x, y, k;
48 int xmin, xmax, ymin, ymax;
49 int space_width, size, gray;
50 int previous;
51 Tag tag;
53 if (filename == NULL)
55 DEBUG_FONTBITMAP(dprintf("FontBitmap: no filename.\n"));
56 return 0;
59 engine = OpenEngine();
60 if (engine == NULL)
62 DEBUG_FONTBITMAP(dprintf("FontBitmap: no engine.\n"));
63 return 0;
66 size = GetTagData(MUIA_FontBitmap_Size, 30, msg->ops_AttrList);
67 gray = GetTagData(MUIA_FontBitmap_Gray, FALSE, msg->ops_AttrList);
69 SetInfo(engine,
70 OT_OTagList, (IPTR) otags,
71 OT_DeviceDPI, 72 | (72 << 16),
72 OT_PointHeight, size << 16,
73 TAG_END);
75 space_width = (int)(GetTagData(OT_SpaceWidth, 0, otags) / 65536.0 * size) ;
77 info = AllocVec(length * sizeof(*info), MEMF_CLEAR);
78 if (info == NULL)
80 DEBUG_FONTBITMAP(dprintf("FontBitmap: can't alloc glyphs.\n"));
81 length = 0;
84 x = 0;
85 y = 0;
86 previous = 0;
87 xmin = ymin = 0x7fffffff;
88 xmax = ymax = -0x80000000;
89 tag = gray ? OT_GlyphMap8Bit : OT_GlyphMap;
91 for (k = 0; k < length; ++k)
93 int code = string[k];
94 int x1, y1, x2, y2;
95 struct GlyphMap *g;
97 if (previous)
99 ULONG kerning;
101 SetInfo(engine,
102 OT_GlyphCode, previous,
103 OT_GlyphCode2, code,
104 TAG_END);
105 ObtainInfo(engine,
106 OT_TextKernPair, (IPTR)&kerning,
107 TAG_END);
109 x -= (int)(kerning / 65536.0 * size);
112 info[k].x = x;
113 info[k].y = y;
115 SetInfo(engine,
116 OT_GlyphCode, code,
117 TAG_END);
118 ObtainInfo(engine,
119 tag, (IPTR)&info[k].glyph,
120 TAG_END);
122 g = info[k].glyph;
124 if (!g)
126 x += space_width;
127 continue;
130 x1 = x - g->glm_X0 + g->glm_BlackLeft;
131 y1 = y - g->glm_Y0 + g->glm_BlackTop;
132 x2 = x1 + g->glm_BlackWidth;
133 y2 = y1 + g->glm_BlackHeight;
135 if (x1 < xmin)
136 xmin = x1;
137 if (y1 < ymin)
138 ymin = y1;
139 if (x2 > xmax)
140 xmax = x2;
141 if (y2 > ymax)
142 ymax = y2;
144 x += g->glm_X1 - g->glm_X0;
145 y += g->glm_Y1 - g->glm_Y0;
147 previous = code;
150 width = xmax - xmin + 1;
151 height = ymax - ymin + 1;
153 DEBUG_FONTBITMAP(dprintf("FontBitmap: bbox %d %d %d %d\n", xmin, ymin, xmax, ymax));
154 DEBUG_FONTBITMAP(dprintf("FontBitmap: width %d height %d\n", width, height));
156 if (width > 0 && height > 0 && width < 32000 && height < 32000)
158 if (gray)
160 UBYTE *array;
161 int width1 = (width + 15) & ~15;
163 array = AllocVec(width1 * height, MEMF_CLEAR);
164 if (array)
166 for (k = 0; k < length; ++k)
168 struct GlyphMap *g = info[k].glyph;
169 int x1, x2, y1, y2;
170 UBYTE *p;
172 if (!g)
174 x += space_width;
175 continue;
178 x = info[k].x - xmin;
179 y = info[k].y - ymin;
180 x -= g->glm_X0;
181 y -= g->glm_Y0;
182 x += g->glm_BlackLeft;
183 y += g->glm_BlackTop;
185 p = g->glm_BitMap;
186 x1 = x;
187 y1 = y;
188 x2 = x + g->glm_BlackWidth;
189 y2 = y + g->glm_BlackHeight;
191 if (x1 > width || x2 < 0 || y1 > height || y2 < 0)
192 continue;
194 if (x1 < 0)
196 p -= x1;
197 x1 = 0;
199 if (y1 < 0)
201 p -= y1 * g->glm_BMModulo;
202 y1 = 0;
204 if (x2 > width)
206 x2 = width;
208 if (y2 > height)
210 y2 = height;
213 while (y1 < y2)
215 int x;
217 for (x = x1; x < x2; ++x)
219 int t = array[width1 * y1 + x] + p[x - x1];
220 if (t > 255)
221 t = 255;
222 array[width1 * y1 + x] = t;
224 p += g->glm_BMModulo;
225 ++y1;
229 gray_bitmap = AllocBitMap(width, height, 8, 0, NULL);
230 if (gray_bitmap)
232 struct RastPort rp, tmp_rp;
234 InitRastPort(&rp);
235 InitRastPort(&tmp_rp);
237 rp.BitMap = gray_bitmap;
238 tmp_rp.BitMap = AllocBitMap(width, 1, 8, 0, NULL);
240 if (tmp_rp.BitMap)
242 WritePixelArray8(&rp,
245 width - 1,
246 height - 1,
247 array,
248 &tmp_rp);
249 FreeBitMap(tmp_rp.BitMap);
253 FreeVec(array);
256 else
258 InitBitMap(&bitmap, 1, width, height);
259 bitmap.Planes[0] = AllocRaster(width, height);
261 if (bitmap.Planes[0])
263 struct RastPort rp;
265 InitRastPort(&rp);
266 rp.BitMap = &bitmap;
267 SetRast(&rp, 0);
268 SetAPen(&rp, 1);
269 SetDrMd(&rp, JAM1);
271 for (k = 0; k < length; ++k)
273 struct GlyphMap *g = info[k].glyph;
275 if (!g)
276 continue;
278 x = info[k].x - xmin;
279 y = info[k].y - ymin;
280 x -= g->glm_X0;
281 y -= g->glm_Y0;
282 x += g->glm_BlackLeft;
283 y += g->glm_BlackTop;
285 /* glm_BitMap is not in chip mem.
286 * Oh well.
288 BltTemplate((const PLANEPTR)(g->glm_BitMap +
289 g->glm_BMModulo *
290 g->glm_BlackTop),
291 g->glm_BlackLeft,
292 g->glm_BMModulo,
293 &rp,
294 x, y,
295 g->glm_BlackWidth,
296 g->glm_BlackHeight);
301 tags[0].ti_Tag = MUIA_Bitmap_Width;
302 tags[0].ti_Data = width;
303 tags[1].ti_Tag = MUIA_Bitmap_Height;
304 tags[1].ti_Data = height;
305 tags[2].ti_Tag = MUIA_FixWidth;
306 tags[2].ti_Data = width;
307 tags[3].ti_Tag = MUIA_FixHeight;
308 tags[3].ti_Data = height;
309 tags[4].ti_Tag = TAG_MORE;
310 tags[4].ti_Data = (IPTR)msg->ops_AttrList;
312 method.MethodID = OM_NEW;
313 method.ops_AttrList = tags;
314 method.ops_GInfo = NULL;
316 o = (Object *)DoSuperMethodA(cl, o, (Msg)&method);
318 if (o)
320 FontBitmapData *dat = INST_DATA(cl, o);
322 dat->Width = width;
323 dat->Height = height;
324 dat->GrayBitMap = gray_bitmap;
326 if (gray)
328 static ULONG colors[256 * 3];
329 static BOOL init;
331 if (!init)
333 LONG k;
334 ULONG *p = colors, color;
335 for (k = 256; --k >= 0; p += 3)
337 color = (k << 24) | (k << 16) | (k << 8) | k;
338 p[0] = p[1] = p[2] = color;
340 init = TRUE;
343 SetAttrs(o,
344 MUIA_Bitmap_Bitmap, gray_bitmap,
345 MUIA_Bitmap_SourceColors, colors,
346 TAG_END);
348 else
350 dat->BitMap = bitmap;
351 set(o, MUIA_Bitmap_Bitmap, &dat->BitMap);
354 else
356 if (gray)
358 FreeBitMap(gray_bitmap);
360 else if (bitmap.Planes[0])
362 FreeRaster(bitmap.Planes[0], width, height);
366 else
368 o = NULL;
371 for (k = 0; k < length; ++k)
373 if (info[k].glyph)
375 ReleaseInfo(engine,
376 tag, (IPTR)info[k].glyph,
377 TAG_END);
381 FreeVec(info);
383 CloseEngine(engine);
385 DEBUG_FONTBITMAP(dprintf("FontBitmap: created object 0x%lx.\n", o));
387 return (IPTR)o;
390 IPTR fbDispose(Class *cl, Object *o)
392 FontBitmapData *dat = INST_DATA(cl, o);
394 DEBUG_FONTBITMAP(dprintf("FontBitmap: destroy object 0x%lx.\n", o));
396 if (dat->GrayBitMap)
398 FreeBitMap(dat->GrayBitMap);
400 else if (dat->BitMap.Planes[0])
402 FreeRaster(dat->BitMap.Planes[0], dat->Width, dat->Height);
405 return DoSuperMethod(cl, o, OM_DISPOSE);
408 AROS_UFH3(ULONG, FontBitmapDispatch,
409 AROS_UFHA(Class *, cl, A0),
410 AROS_UFHA(Object *, o, A2),
411 AROS_UFHA(Msg, msg, A1))
413 AROS_USERFUNC_INIT
415 ULONG ret;
417 switch (msg->MethodID)
419 case OM_NEW:
420 ret = fbNew(cl, o, (struct opSet *)msg);
421 break;
423 case OM_DISPOSE:
424 ret = fbDispose(cl, o);
425 break;
427 default:
428 ret = DoSuperMethodA(cl, o, msg);
429 break;
432 return ret;
434 AROS_USERFUNC_EXIT
438 void CleanupFontBitmapClass(void)
440 if (FontBitmapClass)
442 MUI_DeleteCustomClass(FontBitmapClass);
443 FontBitmapClass = NULL;
447 int InitFontBitmapClass(void)
449 FontBitmapClass = MUI_CreateCustomClass(NULL, MUIC_Bitmap, NULL,
450 sizeof(FontBitmapData), UFHN(FontBitmapDispatch));
451 return FontBitmapClass != NULL;