<commit_before>#include "fitz_base.h"
#include "fitz_tree.h"
#include "fitz_draw.h" /* FIXME -- for glyph rendering callbacks */

#include <ft2build.h>
#include FT_FREETYPE_H

static fz_font *
fz_newfont(void)
{
	fz_font *font;

	font = fz_malloc(sizeof(fz_font));
	if (!font)
		return nil;

	font->refs = 1;
	strcpy(font->name, "<unknown>");

	font->ftface = nil;
	font->ftsubstitute = 0;
	font->fthint = 0;

	font->t3matrix = fz_identity();
	font->t3procs = nil;

	font->bbox.x0 = 0;
	font->bbox.y0 = 0;
	font->bbox.x1 = 1000;
	font->bbox.y1 = 1000;

	return font;
}

fz_font *
fz_keepfont(fz_font *font)
{
	font->refs ++;
	return font;
}

void
fz_dropfont(fz_font *font)
{
	int i;

	if (font && --font->refs == 0)
	{
		if (font->t3procs)
		{
			for (i = 0; i < 256; i++)
				if (font->t3procs[i])
					fz_droptree(font->t3procs[i]);
			fz_free(font->t3procs);
		}

		if (font->ftface)
		{
			FT_Done_Face((FT_Face)font->ftface);
		}

		fz_free(font);
	}
}

void
fz_setfontbbox(fz_font *font, int xmin, int ymin, int xmax, int ymax)
{
	font->bbox.x0 = xmin;
	font->bbox.y0 = ymin;
	font->bbox.x1 = xmax;
	font->bbox.y1 = ymax;
}

/*
 * Freetype hooks
 */

static FT_Library fz_ftlib = nil;

#undef __FTERRORS_H__
#define FT_ERRORDEF(e, v, s)	{ (e), (s) },
#define FT_ERROR_START_LIST
#define FT_ERROR_END_LIST	{ 0, NULL }

struct ft_error
{
	int err;
	char *str;
};

const struct ft_error ft_errors[] =
{
#include FT_ERRORS_H
};

char *ft_errorstring(int err)
{
	const struct ft_error *e;

	for (e = ft_errors; e->str != NULL; e++)
		if (e->err == err)
			return e->str;

	return "Unknown error";
}

static fz_error
fz_initfreetype(void)
{
	int code;
	int maj, min, pat;

	if (fz_ftlib)
		return fz_okay;

	code = FT_Init_FreeType(&fz_ftlib);
	if (code)
		return fz_throw("cannot init freetype: %s", ft_errorstring(code));

	FT_Library_Version(fz_ftlib, &maj, &min, &pat);
	if (maj == 2 && min == 1 && pat < 7)
		return fz_throw("freetype version too old: %d.%d.%d", maj, min, pat);

	return fz_okay;
}

fz_error
fz_newfontfromfile(fz_font **fontp, char *path, int index)
{
	fz_error error;
	fz_font *font;
	int code;

	error = fz_initfreetype();
	if (error)
		return fz_rethrow(error, "cannot init freetype library");

	font = fz_newfont();
	if (!font)
		return fz_rethrow(-1, "out of memory: font struct");

	code = FT_New_Face(fz_ftlib, path, index, (FT_Face*)&font->ftface);
	if (code)
	{
		fz_free(font);
		return fz_throw("freetype: cannot load font: %s", ft_errorstring(code));<commit_msg>Finalize freetype when no fonts refers to it.<commit_after>#include "fitz_base.h"
#include "fitz_tree.h"
#include "fitz_draw.h" /* FIXME -- for glyph rendering callbacks */

#include <ft2build.h>
#include FT_FREETYPE_H

static void fz_finalizefreetype(void);

static fz_font *
fz_newfont(void)
{
	fz_font *font;

	font = fz_malloc(sizeof(fz_font));
	if (!font)
		return nil;

	font->refs = 1;
	strcpy(font->name, "<unknown>");

	font->ftface = nil;
	font->ftsubstitute = 0;
	font->fthint = 0;

	font->t3matrix = fz_identity();
	font->t3procs = nil;

	font->bbox.x0 = 0;
	font->bbox.y0 = 0;
	font->bbox.x1 = 1000;
	font->bbox.y1 = 1000;

	return font;
}

fz_font *
fz_keepfont(fz_font *font)
{
	font->refs ++;
	return font;
}

void
fz_dropfont(fz_font *font)
{
	int i;

	if (font && --font->refs == 0)
	{
		if (font->t3procs)
		{
			for (i = 0; i < 256; i++)
				if (font->t3procs[i])
					fz_droptree(font->t3procs[i]);
			fz_free(font->t3procs);
		}

		if (font->ftface)
		{
			FT_Done_Face((FT_Face)font->ftface);
			fz_finalizefreetype();
		}

		fz_free(font);
	}
}

void
fz_setfontbbox(fz_font *font, int xmin, int ymin, int xmax, int ymax)
{
	font->bbox.x0 = xmin;
	font->bbox.y0 = ymin;
	font->bbox.x1 = xmax;
	font->bbox.y1 = ymax;
}

/*
 * Freetype hooks
 */

static FT_Library fz_ftlib = nil;
static int fz_ftlib_refs = 0;

#undef __FTERRORS_H__
#define FT_ERRORDEF(e, v, s)	{ (e), (s) },
#define FT_ERROR_START_LIST
#define FT_ERROR_END_LIST	{ 0, NULL }

struct ft_error
{
	int err;
	char *str;
};

const struct ft_error ft_errors[] =
{
#include FT_ERRORS_H
};

char *ft_errorstring(int err)
{
	const struct ft_error *e;

	for (e = ft_errors; e->str != NULL; e++)
		if (e->err == err)
			return e->str;

	return "Unknown error";
}

static fz_error
fz_initfreetype(void)
{
	int code;
	int maj, min, pat;

	if (fz_ftlib)
	{
		fz_ftlib_refs++;
		return fz_okay;
	}

	code = FT_Init_FreeType(&fz_ftlib);
	if (code)
		return fz_throw("cannot init freetype: %s", ft_errorstring(code));

	FT_Library_Version(fz_ftlib, &maj, &min, &pat);
	if (maj == 2 && min == 1 && pat < 7)
	{
		FT_Done_FreeType(fz_ftlib);
		return fz_throw("freetype version too old: %d.%d.%d", maj, min, pat);
	}

	fz_ftlib_refs++;
	return fz_okay;
}

static void
fz_finalizefreetype(void)
{
        if (--fz_ftlib_refs == 0)
        {
                FT_Done_FreeType(fz_ftlib);
                fz_ftlib = nil;
        }
}

fz_error
fz_newfontfromfile(fz_font **fontp, char *path, int index)
{
	fz_error error;
	fz_font *font;
	int code;

	error = fz_initfreetype();
	if (error)
		return fz_rethrow(error, "cannot init freetype library");

	font = fz_newfont();
	if (!font)
		return fz_rethrow(-1, "out of memory: font struct");

	code = FT_New_Face(fz_ftlib, path, index, (FT_Face*)&font->ftface);
	if (code)
	{
		fz_free(font);
		return fz_throw("freetype: cannot load font: %s", ft_errorstring(code));
{'fraction_non_alphanumeric': 0.15904017857142858, 'fraction_numerical': 0.014508928571428572, 'mean_word_length': 3.835431654676259, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 61, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2077602', 'n_tokens_mistral': 2586, 'n_tokens_neox': 2416, 'n_words': 524}