Aros/Developer/Docs/Libraries/FreeType2

< Aros‎ | Developer/Docs

IntroductionEdit

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



ExamplesEdit

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
	{
		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);

	SetInfo(engine,
			OT_OTagList, (IPTR) otags,
			OT_DeviceDPI, 72 | (72 << 16),
			OT_PointHeight, size << 16,
			TAG_END);

	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;

			SetInfo(engine,
					OT_GlyphCode, previous,
					OT_GlyphCode2, code,
					TAG_END);
			ObtainInfo(engine,
					OT_TextKernPair, (IPTR)&kerning,
					TAG_END);

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

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

		SetInfo(engine,
				OT_GlyphCode, code,
				TAG_END);
		ObtainInfo(engine,
				tag, (IPTR)&info[k].glyph,
				TAG_END);

		g = info[k].glyph;

		if (!g)
		{
			x += space_width;
			continue;
		}

		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;
						continue;
					}

					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)
						continue;

					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;
						++y1;
					}
				}

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

					InitRastPort(&rp);
					InitRastPort(&tmp_rp);

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

					if (tmp_rp.BitMap)
					{
						WritePixelArray8(&rp,
								0,
								0,
								width - 1,
								height - 1,
								array,
								&tmp_rp);
						FreeBitMap(tmp_rp.BitMap);
					}
				}

				FreeVec(array);
			}
		}
		else
		{
			InitBitMap(&bitmap, 1, width, height);
			bitmap.Planes[0] = AllocRaster(width, height);

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

				InitRastPort(&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)
						continue;

					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 *
								g->glm_BlackTop),
							g->glm_BlackLeft,
							g->glm_BMModulo,
							&rp,
							x, y,
							g->glm_BlackWidth,
							g->glm_BlackHeight);
				}
			}
		}

		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;
				}

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

	for (k = 0; k < length; ++k)
	{
		if (info[k].glyph)
		{
			ReleaseInfo(engine,
					tag, (IPTR)info[k].glyph,
					TAG_END);
		}
	}

	FreeVec(info);

	CloseEngine(engine);

	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)
	{
		FreeBitMap(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))
{
	AROS_USERFUNC_INIT

	ULONG ret;

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

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

		default:
			ret = DoSuperMethodA(cl, o, msg);
			break;
	}

	return ret;

	AROS_USERFUNC_EXIT
}


void CleanupFontBitmapClass(void)
{
	if (FontBitmapClass)
	{
		MUI_DeleteCustomClass(FontBitmapClass);
		FontBitmapClass = NULL;
	}
}

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




ReferenceEdit

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)