Esempio n. 1
0
static fz_error *
ftrender(fz_glyph *glyph, fz_font *fzfont, int cid, fz_matrix trm)
{
	pdf_font *font = (pdf_font*)fzfont;
	FT_Face face = font->ftface;
	FT_Matrix m;
	FT_Vector v;
	FT_Error fterr;
	float scale;
	int gid;
	int x, y;
	int hint = font->hint;

	gid = ftcidtogid(font, cid);

	if (font->substitute && fzfont->wmode == 0)
	{
		fz_hmtx subw;
		int realw;

		FT_Set_Char_Size(face, 1000, 1000, 72, 72);

		fterr = FT_Load_Glyph(font->ftface, gid,
				FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM);
		if (fterr)
			return fz_throw("freetype failed to load glyph: %s", ft_errstr(fterr));

		realw = ((FT_Face)font->ftface)->glyph->advance.x;
		subw = fz_gethmtx(fzfont, cid);
		if (realw)
			scale = (float) subw.w / realw;
		else
			scale = 1.0;

		trm = fz_concat(fz_scale(scale, 1.0), trm);
	}

	glyph->w = 0;
	glyph->h = 0;
	glyph->x = 0;
	glyph->y = 0;
	glyph->samples = nil;

	/* freetype mutilates complex glyphs if they are loaded
	 * with FT_Set_Char_Size 1.0. it rounds the coordinates
	 * before applying transformation. to get more precision in
	 * freetype, we shift part of the scale in the matrix
	 * into FT_Set_Char_Size instead
	 */

#ifdef HINT
	hint = 1;
#endif

	if (hint)
	{
		scale = fz_matrixexpansion(trm);
		m.xx = trm.a * 65536 / scale;
		m.yx = trm.b * 65536 / scale;
		m.xy = trm.c * 65536 / scale;
		m.yy = trm.d * 65536 / scale;
		v.x = 0;
		v.y = 0;

		FT_Set_Char_Size(face, 64 * scale, 64 * scale, 72, 72);
		FT_Set_Transform(face, &m, &v);

		fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP);
		if (fterr)
			fz_warn("freetype load glyph: %s", ft_errstr(fterr));
	}
	else
	{
		m.xx = trm.a * 64;	/* should be 65536 */
		m.yx = trm.b * 64;
		m.xy = trm.c * 64;
		m.yy = trm.d * 64;
		v.x = trm.e * 64;
		v.y = trm.f * 64;

		FT_Set_Char_Size(face, 65536, 65536, 72, 72); /* should be 64, 64 */
		FT_Set_Transform(face, &m, &v);

		fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING);
		if (fterr)
			fz_warn("freetype load glyph: %s", ft_errstr(fterr));
	}

	fterr = FT_Render_Glyph(face->glyph, ft_render_mode_normal);
	if (fterr)
		fz_warn("freetype render glyph: %s", ft_errstr(fterr));

	glyph->w = face->glyph->bitmap.width;
	glyph->h = face->glyph->bitmap.rows;
	glyph->x = face->glyph->bitmap_left;
	glyph->y = face->glyph->bitmap_top - glyph->h;
	glyph->samples = face->glyph->bitmap.buffer;

	for (y = 0; y < glyph->h / 2; y++)
	{
		for (x = 0; x < glyph->w; x++)
		{
			unsigned char a = glyph->samples[y * glyph->w + x ];
			unsigned char b = glyph->samples[(glyph->h - y - 1) * glyph->w + x];
			glyph->samples[y * glyph->w + x ] = b;
			glyph->samples[(glyph->h - y - 1) * glyph->w + x] = a;
		}
	}

	return fz_okay;
}
Esempio n. 2
0
fz_error
fz_renderftglyph(fz_glyph *glyph, fz_font *font, int gid, fz_matrix trm)
{
	FT_Face face = font->ftface;
	FT_Matrix m;
	FT_Vector v;
	FT_Error fterr;
	int x, y;

#if 0
	/* We lost this feature in refactoring.
	 * We can't access pdf_fontdesc metrics from fz_font.
	 * The pdf_fontdesc metrics are character based (cid),
	 * where the glyph being rendered is given by glyph (gid).
	 */
	if (font->ftsubstitute && font->wmode == 0)
	{
		fz_hmtx subw;
		int realw;
		float scale;

		fterr = FT_Set_Char_Size(face, 1000, 1000, 72, 72);
		if (fterr)
			return fz_warn("freetype setting character size: %s", ft_errorstring(fterr));

		fterr = FT_Load_Glyph(font->ftface, gid,
			FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM);
		if (fterr)
			return fz_throw("freetype failed to load glyph: %s", ft_errorstring(fterr));

		realw = ((FT_Face)font->ftface)->glyph->advance.x;
		subw = fz_gethmtx(font, cid); // <-- this is the offender
		if (realw)
			scale = (float) subw.w / realw;
		else
			scale = 1.0;

		trm = fz_concat(fz_scale(scale, 1.0), trm);
	}
#endif

	glyph->w = 0;
	glyph->h = 0;
	glyph->x = 0;
	glyph->y = 0;
	glyph->samples = nil;

	/* freetype mutilates complex glyphs if they are loaded
	 * with FT_Set_Char_Size 1.0. it rounds the coordinates
	 * before applying transformation. to get more precision in
	 * freetype, we shift part of the scale in the matrix
	 * into FT_Set_Char_Size instead
	 */

	m.xx = trm.a * 64; /* should be 65536 */
	m.yx = trm.b * 64;
	m.xy = trm.c * 64;
	m.yy = trm.d * 64;
	v.x = trm.e * 64;
	v.y = trm.f * 64;

	fterr = FT_Set_Char_Size(face, 65536, 65536, 72, 72); /* should be 64, 64 */
	if (fterr)
		fz_warn("freetype setting character size: %s", ft_errorstring(fterr));
	FT_Set_Transform(face, &m, &v);

	if (font->fthint)
	{
		/* Enable hinting, but keep the huge char size so that
		 * it is hinted for a character. This will in effect nullify
		 * the effect of grid fitting. This form of hinting should
		 * only be used for DynaLab and similar tricky TrueType fonts,
		 * so that we get the correct outline shape.
		 */
#ifdef USE_HINTING
		/* If you really want grid fitting, enable this code. */
		float scale = fz_matrixexpansion(trm);
		m.xx = trm.a * 65536 / scale;
		m.xy = trm.b * 65536 / scale;
		m.yx = trm.c * 65536 / scale;
		m.yy = trm.d * 65536 / scale;
		v.x = 0;
		v.y = 0;

		fterr = FT_Set_Char_Size(face, 64 * scale, 64 * scale, 72, 72);
		if (fterr)
			fz_warn("freetype setting character size: %s", ft_errorstring(fterr));
		FT_Set_Transform(face, &m, &v);
#endif
		fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP);
		if (fterr)
			fz_warn("freetype load glyph (gid %d): %s", gid, ft_errorstring(fterr));
	}
	else
	{
		fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING);
		if (fterr)
			fz_warn("freetype load glyph (gid %d): %s", gid, ft_errorstring(fterr));
	}

	fterr = FT_Render_Glyph(face->glyph, ft_render_mode_normal);
	if (fterr)
		fz_warn("freetype render glyph (gid %d): %s", gid, ft_errorstring(fterr));

	glyph->w = face->glyph->bitmap.width;
	glyph->h = face->glyph->bitmap.rows;
	glyph->x = face->glyph->bitmap_left;
	glyph->y = face->glyph->bitmap_top - glyph->h;
	glyph->samples = face->glyph->bitmap.buffer;

	for (y = 0; y < glyph->h / 2; y++)
	{
		for (x = 0; x < glyph->w; x++)
		{
			unsigned char a = glyph->samples[y * glyph->w + x ];
			unsigned char b = glyph->samples[(glyph->h - y - 1) * glyph->w + x];
			glyph->samples[y * glyph->w + x ] = b;
			glyph->samples[(glyph->h - y - 1) * glyph->w + x] = a;
		}
	}

	return fz_okay;
}
Esempio n. 3
0
fz_error *
showglyph(pdf_csi *csi, int cid)
{
	pdf_gstate *gstate = csi->gstate + csi->gtop;
	pdf_font *font = gstate->font;
	fz_error *error;
	fz_matrix tsm, trm;
	float w0, w1, tx, ty;
	fz_hmtx h;
	fz_vmtx v;

	tsm.a = gstate->size * gstate->scale;
	tsm.b = 0;
	tsm.c = 0;
	tsm.d = gstate->size;
	tsm.e = 0;
	tsm.f = gstate->rise;

	if (font->super.wmode == 1)
	{
		v = fz_getvmtx((fz_font*)font, cid);
		tsm.e -= v.x * gstate->size / 1000.0;
		tsm.f -= v.y * gstate->size / 1000.0;
	}

	trm = fz_concat(tsm, csi->tm);

	/* flush buffered text if face or matrix or rendermode has changed */
	if (!csi->text ||
			((fz_font*)font) != csi->text->font ||
			fabs(trm.a - csi->text->trm.a) > FLT_EPSILON ||
			fabs(trm.b - csi->text->trm.b) > FLT_EPSILON ||
			fabs(trm.c - csi->text->trm.c) > FLT_EPSILON ||
			fabs(trm.d - csi->text->trm.d) > FLT_EPSILON ||
			gstate->render != csi->textmode)
	{
		error = pdf_flushtext(csi);
		if (error)
			return fz_rethrow(error, "cannot finish text node (face/matrix change)");

		error = fz_newtextnode(&csi->text, (fz_font*)font);
		if (error)
			return fz_rethrow(error, "cannot create text node");

		csi->text->trm = trm;
		csi->text->trm.e = 0;
		csi->text->trm.f = 0;
		csi->textmode = gstate->render;
	}

	/* add glyph to textobject */
	error = fz_addtext(csi->text, cid, trm.e, trm.f);
	if (error)
		return fz_rethrow(error, "cannot add glyph to text node");

	if (font->super.wmode == 0)
	{
		h = fz_gethmtx((fz_font*)font, cid);
		w0 = h.w / 1000.0;
		tx = (w0 * gstate->size + gstate->charspace) * gstate->scale;
		csi->tm = fz_concat(fz_translate(tx, 0), csi->tm);
	}
	else
	{
		w1 = v.w / 1000.0;
		ty = w1 * gstate->size + gstate->charspace;
		csi->tm = fz_concat(fz_translate(0, ty), csi->tm);
	}

	return fz_okay;
}