Navbar for the Aros wikibook
Aros User
Aros User Docs
Aros User FAQs
Aros User Applications
Aros User DOS Shell
Aros Dev Docs
Aros Developer Docs
Porting Software from AmigaOS/SDL
For Zune Beginners
Zune .MUI Classes
For SDL Beginners
Aros Developer BuildSystem
Specific platforms
Aros x86 Complete System HCL
Aros x86 Audio/Video Support
Aros x86 Network Support
Aros Intel AMD x86 Installing
Aros Storage Support IDE SATA etc
Aros Poseidon USB Support
x86-64 Support
Motorola 68k Amiga Support
Linux and FreeBSD Support
Windows Mingw and MacOSX Support
Android Support
Arm Raspberry Pi Support
PPC Power Architecture
Aros Public License


Provides TrueType, OpenType and Type 1 font and glyphs support for AROS.


link with -lfreetype2

#include <diskfont/glyph.h>
#include <utility/tagitem.h>
#include <aros/debug.h>
#include <libraries/mui.h>
#include <graphics/gfx.h>
#include <diskfont/diskfonttag.h>

#include <proto/alib.h>
#include <proto/exec.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
#include <proto/utility.h>
#include <proto/muimaster.h>
#include <proto/freetype2.h>

#include <string.h>

#include "fontbitmap_class.h"
#include "globals.h"

struct FontBitmapData
	int Width, Height;
	struct BitMap BitMap;
	struct BitMap *GrayBitMap;

typedef struct FontBitmapData FontBitmapData;

IPTR fbNew(Class *cl, Object *o, struct opSet *msg)
	struct opSet method;
	struct TagItem tags[5];
	STRPTR filename = (STRPTR)GetTagData(MUIA_FontBitmap_Filename, (IPTR) NULL, msg->ops_AttrList);
	STRPTR string = (STRPTR)GetTagData(MUIA_FontBitmap_String, (IPTR) "?", msg->ops_AttrList);
	struct TagItem *otags = (struct TagItem *)GetTagData(MUIA_FontBitmap_OTags,
			(IPTR) NULL, msg->ops_AttrList);
		struct GlyphMap *glyph;
		int x;
		int y;
	} *info;
	APTR engine;
	struct BitMap bitmap;
	struct BitMap *gray_bitmap = NULL;
	int width, height;
	int length = strlen(string);
	int x, y, k;
	int xmin, xmax, ymin, ymax;
	int space_width, size, gray;
	int previous;
	Tag tag;

	if (filename == NULL)
		DEBUG_FONTBITMAP(dprintf("FontBitmap: no filename.\n"));
		return 0;

	engine = OpenEngine();
	if (engine == NULL)
		DEBUG_FONTBITMAP(dprintf("FontBitmap: no engine.\n"));
		return 0;

	size = GetTagData(MUIA_FontBitmap_Size, 30, msg->ops_AttrList);
	gray = GetTagData(MUIA_FontBitmap_Gray, FALSE, msg->ops_AttrList);

			OT_OTagList, (IPTR) otags,
			OT_DeviceDPI, 72 | (72 << 16),
			OT_PointHeight, size << 16,

	space_width = (int)(GetTagData(OT_SpaceWidth, 0, otags) / 65536.0 * size) ;

	info = AllocVec(length * sizeof(*info), MEMF_CLEAR);
	if (info == NULL)
		DEBUG_FONTBITMAP(dprintf("FontBitmap: can't alloc glyphs.\n"));
		length = 0;

	x = 0;
	y = 0;
	previous = 0;
	xmin = ymin = 0x7fffffff;
	xmax = ymax = -0x80000000;
	tag = gray ? OT_GlyphMap8Bit : OT_GlyphMap;

	for (k = 0; k < length; ++k)
		int code = string[k];
		int x1, y1, x2, y2;
		struct GlyphMap *g;

		if (previous)
			ULONG kerning;

					OT_GlyphCode, previous,
					OT_GlyphCode2, code,
					OT_TextKernPair, (IPTR)&kerning,

			x -= (int)(kerning / 65536.0 * size);

		info[k].x = x;
		info[k].y = y;

				OT_GlyphCode, code,
				tag, (IPTR)&info[k].glyph,

		g = info[k].glyph;

		if (!g)
			x += space_width;

		x1 = x - g->glm_X0 + g->glm_BlackLeft;
		y1 = y - g->glm_Y0 + g->glm_BlackTop;
		x2 = x1 + g->glm_BlackWidth;
		y2 = y1 + g->glm_BlackHeight;

		if (x1 < xmin)
			xmin = x1;
		if (y1 < ymin)
			ymin = y1;
		if (x2 > xmax)
			xmax = x2;
		if (y2 > ymax)
			ymax = y2;

		x += g->glm_X1 - g->glm_X0;
		y += g->glm_Y1 - g->glm_Y0;

		previous = code;

	width = xmax - xmin + 1;
	height = ymax - ymin + 1;

	DEBUG_FONTBITMAP(dprintf("FontBitmap: bbox %d %d %d %d\n", xmin, ymin, xmax, ymax));
	DEBUG_FONTBITMAP(dprintf("FontBitmap: width %d height %d\n", width, height));

	if (width > 0 && height > 0 && width < 32000 && height < 32000)
		if (gray)
			UBYTE *array;
			int width1 = (width + 15) & ~15;

			array = AllocVec(width1 * height, MEMF_CLEAR);
			if (array)
				for (k = 0; k < length; ++k)
					struct GlyphMap *g = info[k].glyph;
					int x1, x2, y1, y2;
					UBYTE *p;

					if (!g)
						x += space_width;

					x = info[k].x - xmin;
					y = info[k].y - ymin;
					x -= g->glm_X0;
					y -= g->glm_Y0;
					x += g->glm_BlackLeft;
					y += g->glm_BlackTop;

					p = g->glm_BitMap;
					x1 = x;
					y1 = y;
					x2 = x + g->glm_BlackWidth;
					y2 = y + g->glm_BlackHeight;

					if (x1 > width || x2 < 0 || y1 > height || y2 < 0)

					if (x1 < 0)
						p -= x1;
						x1 = 0;
					if (y1 < 0)
						p -= y1 * g->glm_BMModulo;
						y1 = 0;
					if (x2 > width)
						x2 = width;
					if (y2 > height)
						y2 = height;

					while (y1 < y2)
						int x;

						for (x = x1; x < x2; ++x)
							int t = array[width1 * y1 + x] + p[x - x1];
							if (t > 255)
								t = 255;
							array[width1 * y1 + x] = t;
						p += g->glm_BMModulo;

				gray_bitmap = AllocBitMap(width, height, 8, 0, NULL);
				if (gray_bitmap)
					struct RastPort rp, tmp_rp;


					rp.BitMap = gray_bitmap;
					tmp_rp.BitMap = AllocBitMap(width, 1, 8, 0, NULL);

					if (tmp_rp.BitMap)
								width - 1,
								height - 1,

			InitBitMap(&bitmap, 1, width, height);
			bitmap.Planes[0] = AllocRaster(width, height);

			if (bitmap.Planes[0])
				struct RastPort rp;

				rp.BitMap = &bitmap;
				SetRast(&rp, 0);
				SetAPen(&rp, 1);
				SetDrMd(&rp, JAM1);

				for (k = 0; k < length; ++k)
					struct GlyphMap *g = info[k].glyph;

					if (!g)

					x = info[k].x - xmin;
					y = info[k].y - ymin;
					x -= g->glm_X0;
					y -= g->glm_Y0;
					x += g->glm_BlackLeft;
					y += g->glm_BlackTop;

					/* glm_BitMap is not in chip mem.
					 * Oh well.
					BltTemplate((const PLANEPTR)(g->glm_BitMap +
								g->glm_BMModulo *
							x, y,

		tags[0].ti_Tag = MUIA_Bitmap_Width;
		tags[0].ti_Data = width;
		tags[1].ti_Tag = MUIA_Bitmap_Height;
		tags[1].ti_Data = height;
		tags[2].ti_Tag = MUIA_FixWidth;
		tags[2].ti_Data = width;
		tags[3].ti_Tag = MUIA_FixHeight;
		tags[3].ti_Data = height;
		tags[4].ti_Tag = TAG_MORE;
		tags[4].ti_Data = (IPTR)msg->ops_AttrList;

		method.MethodID = OM_NEW;
		method.ops_AttrList = tags;
		method.ops_GInfo = NULL;

		o = (Object *)DoSuperMethodA(cl, o, (Msg)&method);

		if (o)
			FontBitmapData *dat = INST_DATA(cl, o);

			dat->Width = width;
			dat->Height = height;
			dat->GrayBitMap = gray_bitmap;

			if (gray)
				static ULONG colors[256 * 3];
				static BOOL init;

				if (!init)
					int k;
					ULONG *p = colors;
					for (k = 256; --k >= 0; p += 3)
						p[0] = p[1] = p[2] = k * 0x01010101;
					init = TRUE;

						MUIA_Bitmap_Bitmap, gray_bitmap,
						MUIA_Bitmap_SourceColors, colors,
				dat->BitMap = bitmap;
				set(o, MUIA_Bitmap_Bitmap, &dat->BitMap);
			if (gray)
			else if (bitmap.Planes[0])
				FreeRaster(bitmap.Planes[0], width, height);
		o = NULL;

	for (k = 0; k < length; ++k)
		if (info[k].glyph)
					tag, (IPTR)info[k].glyph,



	DEBUG_FONTBITMAP(dprintf("FontBitmap: created object 0x%lx.\n", o));

	return (IPTR)o;

IPTR fbDispose(Class *cl, Object *o)
	FontBitmapData *dat = INST_DATA(cl, o);

	DEBUG_FONTBITMAP(dprintf("FontBitmap: destroy object 0x%lx.\n", o));

	if (dat->GrayBitMap)
	else if (dat->BitMap.Planes[0])
		FreeRaster(dat->BitMap.Planes[0], dat->Width, dat->Height);

	return DoSuperMethod(cl, o, OM_DISPOSE);

AROS_UFH3(ULONG, FontBitmapDispatch,
		AROS_UFHA(Class *, cl, A0),
		AROS_UFHA(Object *, o, A2),
		AROS_UFHA(Msg, msg, A1))

	ULONG ret;

	switch (msg->MethodID)
		case OM_NEW:
			ret = fbNew(cl, o, (struct opSet *)msg);

		case OM_DISPOSE:
			ret = fbDispose(cl, o);

			ret = DoSuperMethodA(cl, o, msg);

	return ret;


void CleanupFontBitmapClass(void)
	if (FontBitmapClass)
		FontBitmapClass = NULL;

int InitFontBitmapClass(void)
	FontBitmapClass = MUI_CreateCustomClass(NULL, MUIC_Bitmap, NULL,
			sizeof(FontBitmapData), UFHN(FontBitmapDispatch));
	return FontBitmapClass != NULL;


struct GlyphEngine * OpenEngine() ()
void CloseEngine(struct GlyphEngine *ge) (A0)
ULONG SetInfoA(struct GlyphEngine *ge, struct TagItem *tags) (A0,A1)
ULONG ObtainInfoA(struct GlyphEngine *ge, struct TagItem *tags) (A0,A1)
ULONG ReleaseInfoA(struct GlyphEngine *ge, struct TagItem *tags) (A0,A1)

FT_Error FT_Init_FreeType(FT_Library *alibrary)
FT_Error FT_Done_FreeType(FT_Library library)
void FT_Library_Version(FT_Library library, FT_Int *amajor, FT_Int *aminor, FT_Int *apatch)
FT_Error FT_New_Face(FT_Library library, const char *pathname, FT_Long face_index, FT_Face *aface)
FT_Error FT_Done_Face(FT_Face face)
FT_Error FT_New_Memory_Face(FT_Library library, const FT_Byte *file_base, FT_Long file_size, FT_Long face_index, FT_Face *aface)
FT_Error FT_Open_Face(FT_Library library, const FT_Open_Args *args, FT_Long face_index, FT_Face *aface)
FT_Error FT_Attach_File(FT_Face face, const char *filepathname)
FT_Error FT_Attach_Stream(FT_Face face, FT_Open_Args *parameters)
FT_Error FT_Set_Char_Size(FT_Face face, FT_F26Dot6 char_width, FT_F26Dot6 char_height, FT_UInt horz_resolution, FT_UInt vert_resolution)
FT_Error FT_Set_Pixel_Sizes(FT_Face face, FT_UInt pixel_width, FT_UInt pixel_height)

void FT_Set_Transform(FT_Face face, FT_Matrix *matrix, FT_Vector *delta)
FT_Error FT_Load_Glyph(FT_Face face, FT_UInt glyph_index, FT_Int32 load_flags)
FT_UInt FT_Get_Char_Index(FT_Face face, FT_ULong charcode)
FT_UInt FT_Get_Name_Index(FT_Face face, FT_String *glyph_name)
FT_Error FT_Load_Char(FT_Face face, FT_ULong char_code, FT_Int32 load_flags)
FT_Error FT_Render_Glyph(FT_GlyphSlot slot, FT_Render_Mode render_mode)
FT_Error FT_Get_Kerning(FT_Face face, FT_UInt left_glyph, FT_UInt right_glyph, FT_UInt kern_mode, FT_Vector *akerning)
FT_Error FT_Get_Glyph_Name(FT_Face face, FT_UInt glyph_index, FT_Pointer buffer, FT_UInt buffer_max)

const char *FT_Get_Postscript_Name(FT_Face face)
FT_Error FT_Select_Charmap(FT_Face face, FT_Encoding encoding)
FT_Error FT_Set_Charmap(FT_Face face, FT_CharMap charmap)
FT_ULong FT_Get_First_Char(FT_Face face, FT_UInt *agindex)
FT_ULong FT_Get_Next_Char(FT_Face face, FT_ULong charcode, FT_UInt *agindex)
FT_Error FT_Get_Glyph(FT_GlyphSlot slot, FT_Glyph *aglyph)
FT_Error FT_Glyph_Copy(FT_Glyph source, FT_Glyph *target)
FT_Error FT_Glyph_Transform(FT_Glyph glyph, FT_Matrix *matrix, FT_Vector *delta)
void FT_Glyph_Get_CBox(FT_Glyph glyph, FT_UInt bbox_mode, FT_BBox *acbox)
FT_Error FT_Glyph_To_Bitmap(FT_Glyph *the_glyph, FT_Render_Mode render_mode, FT_Vector *origin, FT_Bool destroy)

void FT_Done_Glyph(FT_Glyph glyph)
FT_Error FT_New_Size(FT_Face face, FT_Size *asize)
FT_Error FT_Done_Size(FT_Size size)
FT_Error FT_Activate_Size(FT_Size size)
FT_Error FTC_Manager_New(FT_Library library, FT_UInt max_faces, FT_UInt max_sizes, FT_ULong max_bytes, FTC_Face_Requester requester, FT_Pointer req_data, FTC_Manager *amanager)
FT_Error FTC_Manager_Lookup_Face(FTC_Manager manager, FTC_FaceID face_id, FT_Face *aface)
FT_Error FTC_Manager_Lookup_Size(FTC_Manager manager, FTC_Font font, FT_Face *aface, FT_Size *asize)
void FTC_Node_Unref(FTC_Node node, FTC_Manager manager)
FT_Error FTC_ImageCache_New(FTC_Manager manager, FTC_ImageCache *acache)
FT_Error FTC_ImageCache_Lookup(FTC_ImageCache cache, FTC_ImageType type, FT_UInt gindex, FT_Glyph *aglyph, FTC_Node *anode)
FT_Error FTC_SBitCache_New(FTC_Manager manager, FTC_SBitCache *acache)
FT_Error FTC_SBitCache_Lookup(FTC_SBitCache cache, FTC_ImageType type, FT_UInt gindex, FTC_SBit *ansbit, FTC_Node *anode)

void FTC_Manager_Done(FTC_Manager manager)
void FTC_Manager_Reset(FTC_Manager manager)
FT_Error FTC_CMapCache_New(FTC_Manager manager, FTC_CMapCache *acache)
FT_UInt FTC_CMapCache_Lookup(FTC_CMapCache cache, FTC_FaceID face_id, FT_Int cmap_index, FT_UInt32 char_code)

FT_Long FT_MulDiv(FT_Long a, FT_Long b, FT_Long c)
FT_Long FT_MulFix(FT_Long a, FT_Long b)
FT_Long FT_DivFix(FT_Long a, FT_Long b)
FT_Fixed FT_RoundFix(FT_Fixed a)
FT_Fixed FT_CeilFix(FT_Fixed a)
FT_Fixed FT_FloorFix(FT_Fixed a)
void FT_Vector_Transform(FT_Vector *vector, const FT_Matrix *matrix)
void FT_Matrix_Multiply(const FT_Matrix *a, FT_Matrix *b)
FT_Error FT_Matrix_Invert(FT_Matrix *matrix)
FT_Fixed FT_Sin(FT_Angle angle)
FT_Fixed FT_Cos(FT_Angle angle)
FT_Fixed FT_Tan(FT_Angle angle)
FT_Angle FT_Atan2(FT_Fixed dx, FT_Fixed dy)
FT_Angle FT_Angle_Diff(FT_Angle angle1, FT_Angle angle2)
void FT_Vector_Unit(FT_Vector *vec, FT_Angle angle)
void FT_Vector_Rotate(FT_Vector *vec, FT_Angle angle)
FT_Fixed FT_Vector_Length(FT_Vector *vec)

# #FT_Vector_Normalize
void FT_Vector_Polarize(FT_Vector *vec, FT_Fixed *length, FT_Angle *angle)
void FT_Vector_From_Polar(FT_Vector *vec, FT_Fixed length, FT_Angle angle)
void FT_List_Add(FT_List list, FT_ListNode node)
void FT_List_Insert(FT_List list, FT_ListNode node)
FT_ListNode FT_List_Find(FT_List list, void *data)
void FT_List_Remove(FT_List list, FT_ListNode node)
void FT_List_Up(FT_List list, FT_ListNode node)
FT_Error FT_List_Iterate(FT_List list, FT_List_Iterator iterator, void *user)
void FT_List_Finalize(FT_List list, FT_List_Destructor destroy, FT_Memory memory, void *user)

FT_Error FT_Outline_New(FT_Library library, FT_UInt numPoints, FT_Int numContours, FT_Outline *anoutline)
FT_Error FT_Outline_New_Internal(FT_Memory memory, FT_UInt numPoints, FT_Int numContours, FT_Outline *anoutline)
FT_Error FT_Outline_Done(FT_Library library, FT_Outline *outline)
FT_Error FT_Outline_Done_Internal(FT_Memory memory, FT_Outline *outline)
FT_Error FT_Outline_Copy(FT_Outline *source, FT_Outline *target)
void FT_Outline_Translate(FT_Outline *outline, FT_Pos xOffset, FT_Pos yOffset)
void FT_Outline_Transform(FT_Outline *outline, FT_Matrix *matrix)
void FT_Outline_Reverse(FT_Outline *outline)
FT_Error FT_Outline_Check(FT_Outline *outline)
void FT_Outline_Get_CBox(FT_Outline *outline, FT_BBox *acbox)
FT_Error FT_Outline_Get_BBox(FT_Outline *outline, FT_BBox *abbox)
FT_Error FT_Outline_Get_Bitmap(FT_Library library, FT_Outline *outline, FT_Bitmap *abitmap)
FT_Error FT_Outline_Render(FT_Library library, FT_Outline *outline, FT_Raster_Params *params)
FT_Error FT_Outline_Decompose(FT_Outline *outline, const FT_Outline_Funcs *func_interface, void *user)

FT_Error FT_Add_Module(FT_Library library, const FT_Module_Class *clazz)
FT_Module FT_Get_Module(FT_Library library, const char *module_name)
FT_Error FT_Remove_Module(FT_Library library, FT_Module module)
FT_Error FT_New_Library(FT_Memory memory, FT_Library *alibrary)
FT_Error FT_Done_Library(FT_Library library)
void FT_Set_Debug_Hook(FT_Library library, FT_UInt hook_index, FT_DebugHook_Func debug_hook)
void FT_Add_Default_Modules(FT_Library library)
FT_Renderer FT_Get_Renderer(FT_Library library, FT_Glyph_Format format)
FT_Error FT_Set_Renderer(FT_Library library, FT_Renderer renderer, FT_UInt num_params, FT_Parameter *parameters)
FT_Error FT_Stream_OpenGzip(FT_Stream stream, FT_Stream source)
void *FT_Get_Sfnt_Table(FT_Face face, FT_Sfnt_Tag tag)