disable debug
[AROS.git] / workbench / libs / diskfont / bullet.c
blob6b8f7370bb0f496e25a6035f21d1d6c9a4b7a624
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Functions for reading .font files
6 */
8 /****************************************************************************************/
10 #include <dos/dos.h>
11 #include <diskfont/diskfont.h>
12 #include <diskfont/diskfonttag.h>
13 #include <diskfont/oterrors.h>
14 #include <diskfont/glyph.h>
15 #include <aros/macros.h>
16 #include <aros/debug.h>
18 #include <proto/exec.h>
19 #include <proto/dos.h>
20 #include <proto/utility.h>
21 #include <proto/bullet.h>
22 #include <proto/graphics.h>
24 #include <string.h>
26 #include "diskfont_intern.h"
28 /****************************************************************************************/
30 /* bold -> {OT_EmboldenX, 0xE75}, {OT_EmboldenY, 0x99E} */
31 /* italic -> {OT_ShearSin, 0x4690}, {OT_ShearCos, 0xF615} */
33 /* only if OT_InhibitAlgoStyle has corresponding bit cleared! */
35 /****************************************************************************************/
37 STRPTR OTAG_MakeFileName(CONST_STRPTR filename, struct DiskfontBase *DiskfontBase)
39 STRPTR retval;
40 LONG l;
42 l = strlen(filename) + 1;
43 if (l < 7) return NULL;
45 retval = AllocVec(l, MEMF_ANY);
46 if (retval)
48 memcpy(retval, filename, l - 5);
49 strcpy(retval + l - 5, "otag");
52 return retval;
55 /****************************************************************************************/
57 struct OTagList *OTAG_GetFile(CONST_STRPTR filename, struct DiskfontBase *DiskfontBase)
59 struct FileInfoBlock *fib;
60 struct OTagList *otaglist;
61 ULONG *srctag;
62 struct TagItem *ti;
63 STRPTR otagfilename;
64 BPTR otagfile;
65 LONG l;
66 BOOL ok;
68 otagfilename = OTAG_MakeFileName(filename, DiskfontBase);
69 if (!otagfilename) return NULL;
71 otagfile = Open(otagfilename, MODE_OLDFILE);
72 if (!otagfile)
74 FreeVec(otagfilename);
75 return NULL;
78 fib = AllocDosObject(DOS_FIB, NULL);
79 if (!fib)
81 FreeVec(otagfilename);
82 Close(otagfile);
83 return NULL;
86 ok = ExamineFH(otagfile, fib);
87 l = fib->fib_Size;
88 FreeDosObject(DOS_FIB, fib);
90 if (!ok)
92 FreeVec(otagfilename);
93 Close(otagfile);
94 return NULL;
97 otaglist = AllocVec(sizeof(struct OTagList) + l, MEMF_PUBLIC | MEMF_CLEAR);
98 if (!otaglist)
100 FreeVec(otagfilename);
101 Close(otagfile);
102 return NULL;
105 otaglist->filename = otagfilename;
107 ok = (Read(otagfile, otaglist->data, l) == l);
108 Close(otagfile);
110 if (AROS_LONG2BE(otaglist->data[0]) != OT_FileIdent)
111 ok = FALSE;
112 if (AROS_LONG2BE(otaglist->data[1]) != l)
113 ok = FALSE;
115 if (!ok)
117 OTAG_KillFile(otaglist, DiskfontBase);
118 return NULL;
122 * FIXME: The following suggests that there are no OT_TagList tags in the file.
123 * Is it always true?
126 #if (__WORDSIZE == 64)
128 * On 64-bit machines we need to convert otag items from ULONGs to IPTRs.
129 * We do it by allocating a new array and expanding all tags.
130 * Note that we also need to keep original buffer, because
131 * it also contains some supplied data. Pointers to these data are stored
132 * as offsets, we will resolve them too during conversion.
135 /* First count number of tags */
136 l = 1;
137 for (srctag = otaglist->data; srctag[0] != TAG_DONE; srctag += 2)
138 l++;
140 /* Then allocate a new buffer for them */
141 otaglist->tags = AllocVec(sizeof(struct TagItem) * l, MEMF_ANY);
142 if (!otaglist->tags)
144 OTAG_KillFile(otaglist, DiskfontBase);
145 return NULL;
147 #else
149 * On 32-bit machines we save some memory by simply converting
150 * endianess in place.
152 otaglist->tags = (struct TagItem *)otaglist->data;
153 #endif
155 ti = otaglist->tags;
156 for (srctag = otaglist->data;; srctag += 2)
158 ti->ti_Tag = AROS_LONG2BE(srctag[0]);
161 * Stop processing immediately when TAG_DONE encountered.
162 * We do it because some files (like ones generated by FTManager ;-))
163 * miss data portion of the final tag, saving four bytes.
164 * If we touch that location, we damage attached data.
166 if (ti->ti_Tag == TAG_DONE)
167 break;
169 ti->ti_Data = AROS_LONG2BE(srctag[1]);
170 if (ti->ti_Tag & OT_Indirect)
173 * Resolve the indirection. Note that we resolve it
174 * relative to original data buffer, because on 64-bit machines
175 * data and tags point to different regions.
177 ti->ti_Data = (IPTR)otaglist->data + ti->ti_Data;
180 ti++;
183 return otaglist;
186 /****************************************************************************************/
188 VOID OTAG_KillFile(struct OTagList *otaglist, struct DiskfontBase *DiskfontBase)
190 if (otaglist)
192 #if (__WORDSIZE == 64)
193 if (otaglist->tags)
194 FreeVec(otaglist->tags);
195 #endif
197 if (otaglist->filename)
198 FreeVec(otaglist->filename);
200 FreeVec(otaglist);
204 /****************************************************************************************/
206 UBYTE OTAG_GetFontStyle(struct OTagList *otaglist, struct DiskfontBase *DiskfontBase)
208 UBYTE style = 0;
210 /* A font becomes FSF_BOLD if OT_StemWeight >= 0x90 */
212 if (GetTagData(OT_StemWeight, 0, otaglist->tags) >= 0x90)
214 style |= FSF_BOLD;
217 /* A font becomes FSF_ITALIC if OT_SlantStyle != OTS_Upright */
219 if (GetTagData(OT_SlantStyle, OTS_Upright, otaglist->tags) != OTS_Upright)
221 style |= FSF_ITALIC;
224 /* A font becomes FSF_EXTENDED if OT_HorizStyle >= 0xA0 */
226 if (GetTagData(OT_HorizStyle, 0, otaglist->tags) >= 0xA0)
228 style |= FSF_EXTENDED;
231 return style;
234 /****************************************************************************************/
236 UBYTE OTAG_GetSupportedStyles(struct OTagList *otaglist,
237 struct DiskfontBase *DiskfontBase)
239 UBYTE inhibit, supported;
241 #define STYLES (FSF_BOLD | FSF_ITALIC | FSF_UNDERLINED)
244 ** If a style bit is set in OT_InhibitAlgoStyle, then this
245 ** style cannot be handled/calculated/created by the font engine.
247 ** If it is, then the font engine can handle/calculate/create it
250 inhibit = GetTagData(OT_InhibitAlgoStyle, 0, otaglist->tags);
251 supported = (inhibit & STYLES) ^ STYLES;
253 return supported;
256 /****************************************************************************************/
258 UBYTE OTAG_GetFontFlags(struct OTagList *otaglist, struct DiskfontBase *DiskfontBase)
260 UBYTE flags;
262 flags = FONTTYPE_OUTLINEFONT;
263 if (GetTagData(OT_IsFixed, FALSE, otaglist->tags) == FALSE)
265 flags |= FPF_PROPORTIONAL;
268 return flags;
271 /****************************************************************************************/
273 static BOOL OTAG_SetupFontEngine(struct TTextAttr *ta,
274 struct TTextAttr *ra,
275 struct OTagList *otag,
276 struct GlyphEngine *ge,
277 LONG *xdpi_ptr,
278 LONG *ydpi_ptr,
279 struct Library *BulletBase,
280 struct DiskfontBase *DiskfontBase)
282 struct TagItem maintags[] =
284 {OT_OTagList, (IPTR)otag->tags },
285 {OT_OTagPath, (IPTR)otag->filename },
286 {TAG_DONE }
288 struct TagItem sizetags[] =
290 {OT_PointHeight, 0 },
291 {OT_DeviceDPI , 0 },
292 {OT_DotSize , 0 },
293 {TAG_DONE }
295 LONG pointheight, xdot, ydot;
296 LONG xdpi, ydpi, taxdpi, taydpi;
297 LONG ysizefactor, ysizefactor_low, ysizefactor_high;
299 ysizefactor = GetTagData(OT_YSizeFactor, 0x10001, otag->tags);
300 ysizefactor_low = ysizefactor & 0xFFFF;
301 ysizefactor_high = (ysizefactor >> 16) & 0xFFFF;
303 if (!ysizefactor_low)
305 ysizefactor_low = ysizefactor_high = 1;
308 if ((ra->tta_Style & FSF_TAGGED) && ra->tta_Tags)
310 ULONG devicedpi;
312 devicedpi = GetTagData(TA_DeviceDPI, 0x10001, ra->tta_Tags);
313 taxdpi = (devicedpi >> 16) & 0xFFFF;
314 taydpi = devicedpi & 0xFFFF;
316 if (!taydpi)
318 taxdpi = taydpi = 1;
321 else
323 taxdpi = taydpi = 1;
326 xdpi = 72 * ysizefactor_high / ysizefactor_low * taxdpi / taydpi;
327 ydpi = 72 * ysizefactor_high / ysizefactor_low;
329 *xdpi_ptr = xdpi;
330 *ydpi_ptr = ydpi;
332 pointheight = ra->tta_YSize << 16;
333 xdot = ydot = 100;
335 sizetags[0].ti_Data = pointheight;
336 sizetags[1].ti_Data = (xdpi << 16) | ydpi;
337 sizetags[2].ti_Data = (xdot << 16) | ydot;
339 if (SetInfoA(ge, maintags) != OTERR_Success)
341 return FALSE;
344 return (SetInfoA(ge, sizetags) == OTERR_Success);
348 /****************************************************************************************/
350 static VOID OTAG_FreeAAGlyphMaps(struct GlyphEngine *ge,
351 struct GlyphMap **gm,
352 struct Library *BulletBase,
353 struct DiskfontBase *DiskfontBase)
355 UWORD i;
357 for(i = 0; i < 257; i++)
359 if (gm[i])
361 struct TagItem releasetags[] =
363 {OT_GlyphMap8Bits, (IPTR)gm[i]},
364 {TAG_DONE }
367 ReleaseInfoA(ge, releasetags);
369 gm[i] = NULL;
374 /****************************************************************************************/
376 static VOID OTAG_FreeGlyphMaps(struct GlyphEngine *ge,
377 struct GlyphMap **gm,
378 struct Library *BulletBase,
379 struct DiskfontBase *DiskfontBase)
381 UWORD i;
383 for(i = 0; i < 257; i++)
385 if (gm[i])
387 struct TagItem releasetags[] =
389 {OT_GlyphMap, (IPTR)gm[i]},
390 {TAG_DONE }
393 ReleaseInfoA(ge, releasetags);
395 gm[i] = NULL;
400 /****************************************************************************************/
402 static BOOL OTAG_GetGlyphMaps(struct GlyphEngine *ge,
403 struct GlyphMap **gm,
404 UWORD fontheight,
405 WORD *lochar,
406 WORD *hichar,
407 WORD *baseline,
408 LONG *gfxwidth,
409 struct Library *BulletBase,
410 struct DiskfontBase *DiskfontBase)
412 UWORD i;
414 *lochar = -1;
415 *hichar = 0;
416 *baseline = 0;
417 *gfxwidth = 0;
419 for(i = 0; i < 257; i++)
421 struct TagItem settags[] =
423 {OT_GlyphCode, (i < 256) ? i : 0x25A1},
424 {TAG_DONE }
426 struct TagItem obtaintags[] =
428 {OT_GlyphMap, (IPTR)&gm[i] },
429 {TAG_DONE }
432 SetInfoA(ge, settags);
433 ObtainInfoA(ge, obtaintags);
435 if (gm[i])
437 if (i < 256)
439 if (*lochar == -1) *lochar = i;
440 *hichar = i;
443 if (gm[i]->glm_Y0/* - (WORD)gm[i]->glm_BlackTop*/ > *baseline)
445 *baseline = gm[i]->glm_Y0/* - (WORD)gm[i]->glm_BlackTop*/;
448 *gfxwidth += gm[i]->glm_BlackWidth;
452 if (*baseline >= fontheight) *baseline = fontheight;
453 if (*lochar > 32) *lochar = 32;
455 return (*lochar == -1) ? FALSE : TRUE;
458 /****************************************************************************************/
460 static BOOL OTAG_GetAAGlyphMaps(struct GlyphEngine *ge,
461 struct GlyphMap **gm,
462 struct Library *BulletBase,
463 struct DiskfontBase *DiskfontBase)
465 UWORD i;
467 for(i = 0; i < 257; i++)
469 LONG rc;
471 struct TagItem settags[] =
473 {OT_GlyphCode, (i < 256) ? i : 0x25A1},
474 {TAG_DONE }
476 struct TagItem obtaintags[] =
478 {OT_GlyphMap8Bits, (IPTR)&gm[i] },
479 {TAG_DONE }
482 SetInfoA(ge, settags);
483 rc = ObtainInfoA(ge, obtaintags);
485 if (i == 0 && rc == OTERR_UnknownTag)
486 return FALSE;
489 return TRUE;
492 /****************************************************************************************/
494 struct AADiskFontHeader *OTAG_AllocFontStruct(STRPTR name, UWORD numchars, LONG gfxwidth,
495 LONG fontheight, struct DiskfontBase *DiskfontBase)
497 struct AADiskFontHeader *dfh;
498 APTR charkern;
499 APTR charspace;
500 APTR charloc;
501 APTR chardata;
502 APTR prevsegment = NULL;
503 BOOL ok = FALSE;
505 dfh = prevsegment = AllocSegment(prevsegment,
506 sizeof(*dfh) + sizeof(struct TagItem) * 5,
507 MEMF_ANY | MEMF_CLEAR,
508 DiskfontBase);
510 if (dfh)
512 charkern = prevsegment = AllocSegment(prevsegment,
513 numchars * sizeof(WORD),
514 MEMF_ANY | MEMF_CLEAR,
515 DiskfontBase);
516 if (charkern)
518 charspace = prevsegment = AllocSegment(prevsegment,
519 numchars * sizeof(WORD),
520 MEMF_ANY | MEMF_CLEAR,
521 DiskfontBase);
523 if (charspace)
525 charloc = prevsegment = AllocSegment(prevsegment,
526 numchars * sizeof(LONG),
527 MEMF_ANY | MEMF_CLEAR,
528 DiskfontBase);
530 if (charloc)
532 gfxwidth = (gfxwidth + 15) & ~15;
534 chardata = prevsegment = AllocSegment(prevsegment,
535 gfxwidth / 8 * fontheight,
536 MEMF_ANY | MEMF_CLEAR,
537 DiskfontBase);
539 if (chardata)
541 WORD i;
543 dfh->dfh_FileID = DFH_ID;
544 dfh->dfh_DF.ln_Name = dfh->dfh_Name;
545 dfh->dfh_Segment = MAKE_REAL_SEGMENT(dfh);
547 i = strlen(FilePart(name)) + 1;
548 if (i >= sizeof(dfh->dfh_Name)) i = sizeof(dfh->dfh_Name) - 1;
549 CopyMem(FilePart(name), dfh->dfh_Name, i);
551 dfh->dfh_TF.ctf_TF.tf_Message.mn_Node.ln_Name = dfh->dfh_Name;
552 dfh->dfh_TF.ctf_TF.tf_Message.mn_Node.ln_Type = NT_FONT;
554 dfh->dfh_TF.ctf_TF.tf_YSize = fontheight;
555 dfh->dfh_TF.ctf_TF.tf_CharKern = charkern;
556 dfh->dfh_TF.ctf_TF.tf_CharSpace = charspace;
557 dfh->dfh_TF.ctf_TF.tf_CharLoc = charloc;
558 dfh->dfh_TF.ctf_TF.tf_CharData = chardata;
559 dfh->dfh_TF.ctf_TF.tf_Modulo = gfxwidth / 8;
560 dfh->dfh_TF.ctf_TF.tf_BoldSmear = 1;
562 ok = TRUE;
565 } /* if (charloc) */
567 } /* if (charspace) */
569 } /* if (charkern) */
571 } /* if (dfh) */
573 if (!ok)
575 if (dfh) UnLoadSeg(MAKE_REAL_SEGMENT(dfh));
576 dfh = NULL;
579 return dfh;
582 /****************************************************************************************/
584 static LONG OTAG_AllocAAData(struct ColorTextFont *ctf,
585 struct DiskfontBase *DiskfontBase)
587 UBYTE *aadata;
588 int k;
589 int gfxwidth, fontheight;
591 gfxwidth = ctf->ctf_TF.tf_Modulo * 8;
592 fontheight = ctf->ctf_TF.tf_YSize;
594 aadata = AllocSegment(ctf->ctf_TF.tf_CharData,
595 gfxwidth * fontheight,
596 MEMF_ANY | MEMF_CLEAR,
597 DiskfontBase);
598 if (!aadata)
599 return FALSE;
601 ctf->ctf_TF.tf_Style |= FSF_COLORFONT;
602 ctf->ctf_Flags = CT_ANTIALIAS;
603 ctf->ctf_Depth = 8;
604 ctf->ctf_High = 0xff;
606 for (k = 0; k < 8; ++k)
607 ctf->ctf_CharData[k] = aadata;
609 return TRUE;
612 /****************************************************************************************/
614 static VOID OTAG_CalcMetrics(struct GlyphMap **gm, struct TextFont *tf)
616 WORD *charspace = (UWORD *)tf->tf_CharSpace;
617 WORD *charkern = (UWORD *)tf->tf_CharKern;
618 UWORD lochar = tf->tf_LoChar;
619 UWORD hichar = tf->tf_HiChar;
620 UWORD i;
622 for(i = lochar; i <= hichar + 1; i++)
624 struct GlyphMap *g;
625 WORD index;
627 index = (i <= hichar) ? i : 256;
629 g = gm[index];
630 if (!g && (i != 32)) g = gm[256];
632 if (g)
634 charkern [i - lochar] = ((WORD)g->glm_BlackLeft) - g->glm_X0;
635 charspace[i - lochar] = g->glm_X1 - (WORD)g->glm_BlackLeft;
637 if ((tf->tf_Flags & FPF_PROPORTIONAL) == 0)
640 In a fixed font (charkern + charspace) must always equal
641 calculated fontwidth.
643 x = propspace - propkern
644 fixedkern = (fontwidth - x + 1) / 2
645 fixedspace = fontwidth - fixedkern
648 LONG w = charspace[i - lochar] - charkern[i - lochar];
650 charkern[i - lochar] = ((LONG)tf->tf_XSize - w + 1) / 2;
651 charspace[i - lochar] = (LONG)tf->tf_XSize - charkern[i - lochar];
656 else if ((i == 32) || ((tf->tf_Flags & FPF_PROPORTIONAL) == 0))
658 charkern[i - lochar] = 0;
659 charspace[i - lochar] = tf->tf_XSize;
662 } /* for(i = lochar; i <= hichar + 1; i++) */
665 /****************************************************************************************/
667 static VOID OTAG_BlitGlyph(struct GlyphMap *gm, struct TextFont *tf, LONG xpos,
668 LONG ypos, struct DiskfontBase *DiskfontBase)
670 UBYTE *src, *dest;
671 LONG x, y, width, height;
672 LONG srcx, destx, srcy;
674 srcx = gm->glm_BlackLeft & 7;
675 srcy = gm->glm_BlackTop;
676 destx = xpos & 7;
677 width = gm->glm_BlackWidth;
678 height = gm->glm_BlackHeight;
680 if ((width < 1) || (height < 1)) return;
682 /* FIXME: whats the best thing to do here? */
684 /* Check if glyph is bigger/elsewhere than expected,
685 ie. extends outside the bounding box vertically:
687 possible cases:
690 ****
691 ** **
692 ** **
693 ** **
694 ***** ***** ** **
695 ** ** ** ** ****
696 +--**---**--+ +-----------+ +--**---**--+ +----------+ +----------+
697 | ** ** | | | | ** ** | | | | |
698 | ** ** | | | | ** ** | | | | |
699 | ***** | | | | ** ** | | | | |
700 | | | | | ** ** | | | | |
701 | | | ***** | | ** ** | | | | |
702 | | | ** ** | | ** ** | | | | |
703 | | | ** ** | | ** ** | | | | |
704 +-----------+ +--**---**--+ +--**---**--+ +----------+ +----------+
705 ** ** ** ** ****
706 ***** ***** ** **
707 ** **
708 ** **
709 ** **
710 ****
714 if (ypos < 0)
716 if (height <= tf->tf_YSize)
718 ypos = 0;
720 else
722 srcy += (height - tf->tf_YSize) / 2;
723 height = tf->tf_YSize;
724 ypos = 0;
727 else if (ypos + height > tf->tf_YSize)
729 if (height <= tf->tf_YSize)
731 ypos = tf->tf_YSize - height;
733 else
735 srcy += (height - tf->tf_YSize) / 2;
736 height = tf->tf_YSize;
737 ypos = 0;
741 src = gm->glm_BitMap +
742 gm->glm_BMModulo * srcy +
743 gm->glm_BlackLeft / 8 +
744 srcx / 8;
746 dest = (UBYTE *)tf->tf_CharData +
747 ypos * tf->tf_Modulo +
748 xpos / 8 +
749 destx / 8;
751 for(y = 0; y < height; y++)
753 LONG smask = 0x80 >> (srcx & 7);
754 LONG dmask = 0x80 >> (destx & 7);
755 UBYTE *srcxp = src;
756 UBYTE *destxp = dest;
758 for(x = 0; x < width; x++)
760 if (*srcxp & smask)
762 *destxp |= dmask;
765 smask >>= 1;
766 if (!smask)
768 smask = 0x80;
769 srcxp++;
772 dmask >>= 1;
773 if (!dmask)
775 dmask = 0x80;
776 destxp++;
779 src += gm->glm_BMModulo;
780 dest += tf->tf_Modulo;
784 /****************************************************************************************/
786 static VOID OTAG_MakeCharData(struct GlyphMap **gm, struct TextFont *tf,
787 struct DiskfontBase *DiskfontBase)
789 ULONG *charloc = (ULONG *)tf->tf_CharLoc;
790 LONG xpos = 0;
791 UWORD lochar = tf->tf_LoChar;
792 UWORD hichar = tf->tf_HiChar;
793 UWORD i;
795 for(i = lochar; i <= hichar + 1; i++)
797 struct GlyphMap *g;
798 WORD index;
800 index = (i <= hichar) ? i : 256;
801 g = gm[index];
802 if (g)
804 LONG ypos;
806 ypos = (LONG)tf->tf_Baseline + 1 - (g->glm_Y0/* - (WORD)g->glm_BlackTop*/);
808 OTAG_BlitGlyph(g, tf, xpos, ypos, DiskfontBase);
810 charloc[i - lochar] = (xpos << 16) + g->glm_BlackWidth;
811 xpos += g->glm_BlackWidth;
817 /****************************************************************************************/
819 static VOID OTAG_BlitAAGlyph(struct GlyphMap *gm, struct ColorTextFont *tf, LONG xpos,
820 LONG ypos, struct DiskfontBase *DiskfontBase)
822 UBYTE *src, *dest;
823 LONG x, y, width, height;
824 LONG srcx, srcy;
826 srcx = gm->glm_BlackLeft;
827 srcy = gm->glm_BlackTop;
828 width = gm->glm_BlackWidth;
829 height = gm->glm_BlackHeight;
831 if ((width < 1) || (height < 1)) return;
833 if (ypos < 0)
835 srcy -= ypos;
836 height += ypos;
837 ypos = 0;
839 if (ypos + height > tf->ctf_TF.tf_YSize)
840 height = tf->ctf_TF.tf_YSize - ypos;
842 src = gm->glm_BitMap +
843 gm->glm_BMModulo * srcy +
844 srcx;
846 dest = (UBYTE *)tf->ctf_CharData[0] +
847 ypos * tf->ctf_TF.tf_Modulo * 8 +
848 xpos;
850 for(y = 0; y < height; y++)
852 UBYTE *srcxp = src;
853 UBYTE *destxp = dest;
855 for(x = 0; x < width; x++)
857 *destxp++ = *srcxp++;
860 src += gm->glm_BMModulo;
861 dest += tf->ctf_TF.tf_Modulo * 8;
865 /****************************************************************************************/
867 static VOID OTAG_MakeAAData(struct GlyphMap **gm, struct ColorTextFont *tf,
868 struct DiskfontBase *DiskfontBase)
870 //ULONG *charloc = (ULONG *)tf->ctf_TF.tf_CharLoc;
871 LONG xpos = 0;
872 UWORD lochar = tf->ctf_TF.tf_LoChar;
873 UWORD hichar = tf->ctf_TF.tf_HiChar;
874 UWORD i;
876 for(i = lochar; i <= hichar + 1; i++)
878 struct GlyphMap *g;
879 WORD index;
881 index = (i <= hichar) ? i : 256;
882 g = gm[index];
883 if (g)
885 LONG ypos;
887 ypos = (LONG)tf->ctf_TF.tf_Baseline + 1 - (g->glm_Y0/* - (WORD)g->glm_BlackTop*/);
889 OTAG_BlitAAGlyph(g, tf, xpos, ypos, DiskfontBase);
891 xpos += g->glm_BlackWidth;
897 /****************************************************************************************/
899 struct TextFont *OTAG_ReadOutlineFont(struct TTextAttr *attr, struct TTextAttr *reqattr,
900 struct OTagList *otag, struct DiskfontBase *DiskfontBase)
902 struct Library *BulletBase;
903 struct GlyphEngine *ge;
904 struct GlyphMap **gm;
905 struct AADiskFontHeader *dfh = NULL;
906 STRPTR enginename, enginenamebuf;
908 LONG gfxwidth, spacewidth, xdpi, ydpi;
909 WORD lochar, hichar, baseline;
910 UBYTE fontstyle, supportedstyle;
912 enginename = (STRPTR)GetTagData(OT_Engine, (IPTR) NULL, otag->tags);
913 if (!enginename) return NULL;
915 enginenamebuf = AllocVec(strlen(enginename) + sizeof(".library") + 1, MEMF_ANY);
916 if (!enginenamebuf) return NULL;
918 strcpy(enginenamebuf, enginename);
919 strcat(enginenamebuf, ".library");
921 BulletBase = OpenLibrary(enginenamebuf, 0);
922 FreeVec(enginenamebuf);
924 if (!BulletBase) return NULL;
926 ge = OpenEngine();
927 if (!ge)
929 D(bug("Error opening engine %s\n", enginename));
930 CloseLibrary(BulletBase);
931 return NULL;
934 if (!OTAG_SetupFontEngine(attr, reqattr, otag, ge, &xdpi, &ydpi, BulletBase, DiskfontBase))
936 D(bug("Error calling SetupFontengine %s\n", enginename));
937 CloseEngine(ge);
938 CloseLibrary(BulletBase);
939 return NULL;
942 fontstyle = OTAG_GetFontStyle(otag, DiskfontBase);
943 supportedstyle = OTAG_GetSupportedStyles(otag, DiskfontBase);
945 if ((reqattr->tta_Style & FSF_BOLD) && !(fontstyle & FSF_BOLD) && (supportedstyle & FSF_BOLD))
947 struct TagItem bold_tags[] =
949 {OT_EmboldenX, 0xE75},
950 {OT_EmboldenY, 0x99E},
951 {TAG_DONE }
954 if (SetInfoA(ge, bold_tags) == OTERR_Success)
956 fontstyle |= FSF_BOLD;
960 if ((reqattr->tta_Style & FSF_ITALIC) && !(fontstyle & FSF_ITALIC) && (supportedstyle & FSF_ITALIC))
962 struct TagItem italic_tags[] =
964 {OT_ShearSin, 0x4690},
965 {OT_ShearCos, 0xF615},
966 {TAG_DONE }
969 if (SetInfoA(ge, italic_tags) == OTERR_Success)
971 fontstyle |= FSF_ITALIC;
975 gm = (struct GlyphMap **)AllocVec(sizeof(struct GlyhpMap *) * 257, MEMF_ANY | MEMF_CLEAR);
976 if (!gm)
978 CloseEngine(ge);
979 CloseLibrary(BulletBase);
980 return NULL;
983 if (!OTAG_GetGlyphMaps(ge,
985 reqattr->tta_YSize,
986 &lochar,
987 &hichar,
988 &baseline,
989 &gfxwidth,
990 BulletBase,
991 DiskfontBase))
993 D(bug("Error getting GlyphMaps\n"));
994 FreeVec(gm);
995 CloseEngine(ge);
996 CloseLibrary(BulletBase);
997 return NULL;
1000 dfh = OTAG_AllocFontStruct(reqattr->tta_Name,
1001 hichar - lochar + 2,
1002 gfxwidth,
1003 reqattr->tta_YSize,
1004 DiskfontBase);
1005 if (!dfh)
1007 OTAG_FreeGlyphMaps(ge, gm, BulletBase, DiskfontBase);
1008 FreeVec(gm);
1009 CloseEngine(ge);
1010 CloseLibrary(BulletBase);
1011 return NULL;
1014 spacewidth = GetTagData(OT_SpaceWidth, 3000, otag->tags);
1018 OT_SpaceWidth pointsize
1019 -------------- * --------- * xdpi
1020 2540 250
1023 /* FIXME: maybe should do 64 bit calculations (long long)? */
1024 spacewidth = spacewidth * reqattr->tta_YSize / 250 * xdpi / 2540;
1026 dfh->dfh_TF.ctf_TF.tf_Style = fontstyle;
1027 dfh->dfh_TF.ctf_TF.tf_Flags = OTAG_GetFontFlags(otag, DiskfontBase) & ~FPF_ROMFONT;
1028 dfh->dfh_TF.ctf_TF.tf_LoChar = lochar;
1029 dfh->dfh_TF.ctf_TF.tf_HiChar = hichar;
1030 dfh->dfh_TF.ctf_TF.tf_Baseline = baseline - 1; /* CHECKME */
1031 dfh->dfh_TF.ctf_TF.tf_XSize = spacewidth;
1033 OTAG_CalcMetrics(gm, &dfh->dfh_TF.ctf_TF);
1034 OTAG_MakeCharData(gm, &dfh->dfh_TF.ctf_TF, DiskfontBase);
1036 OTAG_FreeGlyphMaps(ge, gm, BulletBase, DiskfontBase);
1038 if (OTAG_GetAAGlyphMaps(ge,
1040 BulletBase,
1041 DiskfontBase))
1043 if (OTAG_AllocAAData(&dfh->dfh_TF, DiskfontBase))
1044 OTAG_MakeAAData(gm, &dfh->dfh_TF, DiskfontBase);
1045 OTAG_FreeAAGlyphMaps(ge, gm, BulletBase, DiskfontBase);
1048 FreeVec(gm);
1049 CloseEngine(ge);
1050 CloseLibrary(BulletBase);
1053 /* TagItems were allocated in OTAG_AllocFontStruct */
1055 struct TagItem *tags = (struct TagItem *)(dfh + 1);
1057 tags[0].ti_Tag = OT_PointHeight;
1058 tags[0].ti_Data = reqattr->tta_YSize << 16;
1059 tags[1].ti_Tag = OT_DeviceDPI;
1060 tags[1].ti_Data = (xdpi << 16) | ydpi;
1061 tags[2].ti_Tag = OT_DotSize;
1062 tags[2].ti_Data = (100 << 16) | 100;
1063 tags[3].ti_Tag = TAG_DONE;
1064 tags[3].ti_Data = 0;
1066 ExtendFont(&dfh->dfh_TF.ctf_TF, tags);
1069 return &dfh->dfh_TF.ctf_TF;
1073 /****************************************************************************************/