⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gdip_font.cpp

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 CPP
字号:
/* *			GPAC - Multimedia Framework C SDK * *			Copyright (c) Jean Le Feuvre 2000-2005 *					All rights reserved * *  This file is part of GPAC / GDIplus rasterizer module * *  GPAC is free software; you can redistribute it and/or modify *  it under the terms of the GNU Lesser General Public License as published by *  the Free Software Foundation; either version 2, or (at your option) *  any later version. *    *  GPAC is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU Lesser General Public License for more details. *    *  You should have received a copy of the GNU Lesser General Public *  License along with this library; see the file COPYING.  If not, write to *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  * */#include "gdip_priv.h"#include <gpac/utf.h>#ifndef GDIP_MAX_STRING_SIZE#define GDIP_MAX_STRING_SIZE	5000#endifGF_Err gdip_init_font_engine(GF_FontRaster *dr){	const char *sOpt;	FontPriv *ctx = (FontPriv *)dr->priv;	sOpt = gf_modules_get_option((GF_BaseInterface *)dr, "FontEngine", "FontSerif");	strcpy(ctx->font_serif, sOpt ? sOpt : "Times New Roman");	sOpt = gf_modules_get_option((GF_BaseInterface *)dr, "FontEngine", "FontSans");	strcpy(ctx->font_sans, sOpt ? sOpt : "Arial");	sOpt = gf_modules_get_option((GF_BaseInterface *)dr, "FontEngine", "FontFixed");	strcpy(ctx->font_fixed, sOpt ? sOpt : "Courier New");	return GF_OK;}GF_Err gdip_shutdown_font_engine(GF_FontRaster *dr){	FontPriv *ctx = (FontPriv *)dr->priv;	if (ctx->font) GdipDeleteFontFamily(ctx->font);	ctx->font = NULL;		/*nothing to do*/	return GF_OK;}static void adjust_white_space(const unsigned short *string, Float *width, Float whiteSpaceWidth){	u32 len , i=0;	while (string[i] == (unsigned short) ' ') {		*width += whiteSpaceWidth;		i++;	}	if (whiteSpaceWidth<0) return;	len = gf_utf8_wcslen(string);	if (i != len) {		i = len - 1;		while (string[i] == (unsigned short) ' ') {			*width += whiteSpaceWidth;			i--;		}	}}static GF_Err gdip_get_font_metrics(GF_FontRaster *dr, Fixed *ascent, Fixed *descent, Fixed *lineSpacing){	UINT16 val, em;	FontPriv *ctx = (FontPriv *)dr->priv;	*ascent = *descent = *lineSpacing = 0;	if (!ctx->font) return GF_BAD_PARAM;	GdipGetEmHeight(ctx->font, ctx->font_style, &em);	GdipGetCellAscent(ctx->font, ctx->font_style, &val);	*ascent = FLT2FIX( ctx->font_size * val / em );	GdipGetCellDescent(ctx->font, ctx->font_style, &val);	*descent = FLT2FIX( ctx->font_size * val / em);	GdipGetLineSpacing(ctx->font, ctx->font_style, &val);	*lineSpacing = FLT2FIX( ctx->font_size * val / em);	return GF_OK;}static GF_Err gdip_get_text_size(GF_FontRaster *dr, const unsigned short *string, Fixed *width, Fixed *height){	GpPath *path_tmp;	GpStringFormat *fmt;	FontPriv *ctx = (FontPriv *)dr->priv;	*width = *height = 0;	if (!ctx->font) return GF_BAD_PARAM;	GdipCreateStringFormat(StringFormatFlagsNoWrap, LANG_NEUTRAL, &fmt);	GdipCreatePath(FillModeAlternate, &path_tmp);	RectF rc;	rc.X = rc.Y = 0;	rc.Width = rc.Height = 0;	GdipAddPathString(path_tmp, string, -1, ctx->font, ctx->font_style, FIX2FLT(ctx->font_size), &rc, fmt);	GdipGetPathWorldBounds(path_tmp, &rc, NULL, NULL);	adjust_white_space(string, &rc.Width, ctx->whitespace_width);	*width = FLT2FIX(rc.Width);	*height = FLT2FIX(rc.Height);	GdipDeleteStringFormat(fmt);	GdipDeletePath(path_tmp);		return GF_OK;}static GF_Err gdip_add_text_to_path(GF_FontRaster *dr, GF_Path *path, Bool flipText,					const unsigned short* string, Fixed _left, Fixed _top, Fixed _x_scaling, Fixed _y_scaling, 					Fixed _ascent, GF_Rect *bounds){	GpPath *path_tmp;	GpMatrix *mat;	GpStringFormat *fmt;	Float real_start;	unsigned short str[4];	Float left, top, x_scaling, y_scaling, ascent;	FontPriv *ctx = (FontPriv *)dr->priv;	if (!ctx->font) return GF_BAD_PARAM;	left = FIX2FLT(_left);	top = FIX2FLT(_top);	x_scaling = FIX2FLT(_x_scaling);	y_scaling = FIX2FLT(_y_scaling);	ascent = FIX2FLT(_ascent);		RectF rc;	rc.X = rc.Y = 0;	rc.Width = rc.Height = 0;	/*find first non-space char and estimate its glyph pos since GDIplus doesn't give this info*/	s32 len = gf_utf8_wcslen(string);	s32 i=0;	for (; i<len; i++) {		if (string[i] != (unsigned short) ' ') break;	}	if (i>=len) return GF_OK;	GdipCreateStringFormat(StringFormatFlagsNoWrap | StringFormatFlagsNoFitBlackBox | StringFormatFlagsMeasureTrailingSpaces, LANG_NEUTRAL, &fmt);	GdipSetStringFormatAlign(fmt, StringAlignmentNear);	GdipCreatePath(FillModeAlternate, &path_tmp);	/*to compute first glyph alignment (say 'x', we figure out its bounding full box by using the '_' char as wrapper (eg, "_x_")	then the bounding box starting from xMin of the glyph ('x_'). The difference between both will give us a good approx 	of the glyph alignment*/	str[0] = (unsigned short) '_';	str[1] = string[i];	str[2] = (unsigned short) '_';	str[3] = (unsigned short) 0;	GdipAddPathString(path_tmp, str, -1, ctx->font, ctx->font_style, FIX2FLT(ctx->font_size), &rc, fmt);	GdipGetPathWorldBounds(path_tmp, &rc, NULL, NULL);	Float w1 = rc.Width - 2 * ctx->underscore_width;		GdipResetPath(path_tmp);	str[0] = string[i];	str[1] = (unsigned short) '_';	str[2] = (unsigned short) 0;	rc.X = rc.Y = 0;	rc.Width = rc.Height = 0;	GdipAddPathString(path_tmp, str, -1, ctx->font, ctx->font_style, FIX2FLT(ctx->font_size), &rc, fmt);	GdipGetPathWorldBounds(path_tmp, &rc, NULL, NULL);	real_start = w1 - (rc.Width - ctx->underscore_width);	GdipResetPath(path_tmp);	rc.X = rc.Y = 0;	rc.Width = rc.Height = 0;	GdipAddPathString(path_tmp, string, -1, ctx->font, ctx->font_style, FIX2FLT(ctx->font_size), &rc, fmt);	GdipGetPathWorldBounds(path_tmp, &rc, NULL, NULL);	GdipCreateMatrix(&mat);	Float off_left = rc.X;	Float off_left_real = rc.X;	/*adjust all white space at begin*/	adjust_white_space(string, &off_left, -1*ctx->whitespace_width);	if (flipText) {		/*first translate in local system*/		GdipTranslateMatrix(mat, left - off_left + real_start, -top, MatrixOrderAppend);		/*then scale as specified*/		GdipScaleMatrix(mat, x_scaling, -y_scaling, MatrixOrderAppend);	} else {		/*first translate in local system*/		GdipTranslateMatrix(mat, left - off_left + real_start, top-ascent, MatrixOrderAppend);		/*then scale as specified*/		GdipScaleMatrix(mat, x_scaling, y_scaling, MatrixOrderAppend);	}	GdipTransformPath(path_tmp, mat);	/*start enum*/	s32 count;	GdipGetPointCount(path_tmp, &count);	GpPointF *pts = new GpPointF[count];	BYTE *types = new BYTE[count];	GdipGetPathTypes(path_tmp, types, count);	GdipGetPathPoints(path_tmp, pts, count);	for (i=0; i<count; ) {		BOOL closed = 0;		s32 sub_type;				sub_type = types[i] & PathPointTypePathTypeMask;		if (sub_type == PathPointTypeStart) {			gf_path_add_move_to(path, FLT2FIX(pts[i].X), FLT2FIX(pts[i].Y));			i++;		}		else if (sub_type == PathPointTypeLine) {			gf_path_add_line_to(path, FLT2FIX(pts[i].X), FLT2FIX(pts[i].Y));					if (types[i] & PathPointTypeCloseSubpath) gf_path_close(path);			i++;		}		else if (sub_type == PathPointTypeBezier) {			assert(i+2<=count);			gf_path_add_cubic_to(path, FLT2FIX(pts[i].X), FLT2FIX(pts[i].Y), FLT2FIX(pts[i+1].X), FLT2FIX(pts[i+1].Y), FLT2FIX(pts[i+2].X), FLT2FIX(pts[i+2].Y));			if (types[i+2] & PathPointTypeCloseSubpath) gf_path_close(path);			i += 3;		} else {			assert(0);			break;		}	}		delete [] pts;	delete [] types;		GdipResetPath(path_tmp);	adjust_white_space(string, &rc.Width, ctx->whitespace_width);	rc.X = off_left_real;	rc.X = off_left;	/*special case where string is just space*/	if (!rc.Height) rc.Height = 1;	GdipAddPathRectangles(path_tmp, &rc, 1);	GdipGetPathWorldBounds(path_tmp, &rc, mat, NULL);	bounds->x = FLT2FIX(rc.X);	bounds->y = FLT2FIX(rc.Y);	bounds->width = FLT2FIX(rc.Width);	bounds->height = FLT2FIX(rc.Height);	GdipDeleteStringFormat(fmt);	GdipDeletePath(path_tmp);	GdipDeleteMatrix(mat);	return GF_OK;}static GF_Err gdip_set_font(GF_FontRaster *dr, const char *fontName, const char *styles){	WCHAR wcFontName[GDIP_MAX_STRING_SIZE];	FontPriv *ctx = (FontPriv *)dr->priv;	if (ctx->font) GdipDeleteFontFamily(ctx->font);	ctx->font = NULL;	if (fontName && strlen(fontName) >= GDIP_MAX_STRING_SIZE) fontName = NULL;	if (!fontName || !strlen(fontName) ) fontName = ctx->font_serif;	else if (!stricmp(fontName, "SANS") || !stricmp(fontName, "sans-serif")) fontName = ctx->font_sans;	else if (!stricmp(fontName, "SERIF")) fontName = ctx->font_serif;	else if (!stricmp(fontName, "TYPEWRITER") || !stricmp(fontName, "monospace")) fontName = ctx->font_fixed;	MultiByteToWideChar(CP_ACP, 0, fontName, strlen(fontName)+1, 						wcFontName, sizeof(wcFontName)/sizeof(wcFontName[0]) );	GdipCreateFontFamilyFromName(wcFontName, NULL, &ctx->font);	if (!ctx->font) return GF_NOT_SUPPORTED;	//setup styles	ctx->font_style = 0;	if (styles) {		char *upr_styles = strdup(styles);		strupr(upr_styles);		if (strstr(upr_styles, "BOLDITALIC")) ctx->font_style |= FontStyleBoldItalic;		else if (strstr(upr_styles, "BOLD")) ctx->font_style |= FontStyleBold;		else if (strstr(upr_styles, "ITALIC")) ctx->font_style |= FontStyleItalic;				if (strstr(upr_styles, "UNDERLINED")) {			ctx->font_style |= FontStyleUnderline;		}		if (strstr(upr_styles, "STRIKEOUT")) {			ctx->font_style |= FontStyleStrikeout;		}		free(upr_styles);	}		return GF_OK;}static GF_Err gdip_set_font_size(GF_FontRaster *dr, Fixed pixel_size){	unsigned short test_str[4];	FontPriv *ctx = (FontPriv *)dr->priv;	if (!ctx->font) return GF_BAD_PARAM;	ctx->font_size = FIX2FLT(pixel_size);	/*GDI+ won't return begin/end whitespace info through GetBoundingRect, so compute a default value for space...*/	ctx->whitespace_width = 0;	Fixed w, h, w2;	test_str[0] = (unsigned short) '_';	test_str[1] = (unsigned short) '\0';	gdip_get_text_size(dr, test_str, &w, &h);	ctx->underscore_width = FIX2FLT(w);	test_str[0] = (unsigned short) '_';	test_str[1] = (unsigned short) ' ';	test_str[2] = (unsigned short) '_';	test_str[3] = (unsigned short) '\0';	gdip_get_text_size(dr, test_str, &w2, &h);	ctx->whitespace_width = FIX2FLT(w2 - 2*w);	return GF_OK;}GF_FontRaster *gdip_new_font_driver(){	GdiplusStartupInput startupInput;	GF_FontRaster *dr;	FontPriv *ctx;	SAFEALLOC(ctx, FontPriv);	SAFEALLOC(dr, GF_FontRaster);	GdiplusStartup(&ctx->gdiToken, &startupInput, NULL);	GF_REGISTER_MODULE_INTERFACE(dr, GF_FONT_RASTER_INTERFACE, "GDIplus Font Engine", "gpac distribution")	dr->add_text_to_path = gdip_add_text_to_path;	dr->get_font_metrics = gdip_get_font_metrics;	dr->get_text_size = gdip_get_text_size;	dr->init_font_engine = gdip_init_font_engine;	dr->set_font = gdip_set_font;	dr->set_font_size = gdip_set_font_size;	dr->shutdown_font_engine = gdip_shutdown_font_engine;	dr->priv = ctx;	return dr;}void gdip_delete_font_driver(GF_FontRaster *dr){	FontPriv *ctx = (FontPriv *)dr->priv;	GdiplusShutdown(ctx->gdiToken);	if (ctx->font) GdipDeleteFontFamily(ctx->font);	ctx->font = NULL;	free(dr->priv);	free(dr);}Bool QueryInterface(u32 InterfaceType){	if (InterfaceType == GF_FONT_RASTER_INTERFACE) return 1;	if (InterfaceType == GF_RASTER_2D_INTERFACE) return 1;	return 0;}GF_Raster2D *gdip_LoadRenderer();void gdip_ShutdownRenderer(GF_Raster2D *driver);GF_BaseInterface *LoadInterface(u32 InterfaceType){	if (InterfaceType==GF_FONT_RASTER_INTERFACE) return (GF_BaseInterface *)gdip_new_font_driver();	if (InterfaceType==GF_RASTER_2D_INTERFACE) return (GF_BaseInterface *)gdip_LoadRenderer();	return NULL;}void ShutdownInterface(GF_BaseInterface *ifce){	switch (ifce->InterfaceType) {	case GF_FONT_RASTER_INTERFACE:		gdip_delete_font_driver((GF_FontRaster *)ifce);		break;	case GF_RASTER_2D_INTERFACE:		gdip_ShutdownRenderer((GF_Raster2D *)ifce);		break;	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -