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

📄 text.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *			GPAC - Multimedia Framework C SDK * *			Copyright (c) Jean Le Feuvre 2000-2005 *					All rights reserved * *  This file is part of GPAC / 2D rendering 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 "stacks2d.h"#include "visualsurface2d.h"#include <gpac/utf.h>#include <gpac/options.h>/*default value when no fontStyle*/#define FSFAMILY	(fs && fs->family.count) ? (const char *)fs->family.vals[0]	: ""/*here it's tricky since it depends on our metric system...*/#define FSSIZE		(fs ? fs->size : -1)#define FSSTYLE		(fs && fs->style.buffer) ? (const char *)fs->style.buffer : ""#define FSMAJOR		( (fs && fs->justify.count && fs->justify.vals[0]) ? (const char *)fs->justify.vals[0] : "FIRST")#define FSMINOR		( (fs && (fs->justify.count>1) && fs->justify.vals[1]) ? (const char *)fs->justify.vals[1] : "FIRST")#define FSHORIZ		(fs ? fs->horizontal : 1)#define FSLTR		(fs ? fs->leftToRight : 1)#define FSTTB		(fs ? fs->topToBottom : 1)#define FSLANG		(fs ? fs->language : "")#define FSSPACE		(fs ? fs->spacing : 1)void text2D_get_ascent_descent(DrawableContext *ctx, Fixed *a, Fixed *d){	TextStack2D *stack = (TextStack2D *) gf_node_get_private(ctx->drawable->node);	*a = stack->ascent;	*d = stack->descent;}typedef struct{	/*regular drawing*/	GF_Path *path;	GF_Rect bounds;	/*texture drawing*/		GF_HWTEXTURE hwtx;	Render2D *sr;	GF_Path *tx_path;	Bool tx_ready;	/*take only into account the window-scaling zoom, not any navigation one (would be too big)*/	SFVec2f last_scale;	GF_Rect tx_bounds;	Bool failed;} TextLineEntry2D;TextLineEntry2D *NewTextLine2D(Render2D *sr){	TextLineEntry2D *tl;	GF_SAFEALLOC(tl, TextLineEntry2D);	tl->path = gf_path_new();	/*text texturing enabled*/	tl->sr = sr;	tl->last_scale.x = sr->scale_x;	tl->last_scale.y = sr->scale_y;	return tl;}void TextLine_StoreBounds(TextLineEntry2D *tl){	gf_path_get_bounds(tl->path, &tl->bounds);}Bool TextLine2D_TextureIsReady(TextLineEntry2D *tl){	GF_Matrix2D mx;	GF_STENCIL stenc;	GF_SURFACE surf;	Fixed cx, cy;	u32 width, height;	Fixed scale, max;	GF_Err e;	GF_Raster2D *r2d = tl->sr->compositor->r2d;	/*something failed*/	if (tl->failed) return 0;	if (!tl->hwtx) tl->hwtx = r2d->stencil_new(r2d, GF_STENCIL_TEXTURE);	if (tl->tx_ready) {		if ((tl->last_scale.x == tl->sr->scale_x)			&& (tl->last_scale.y == tl->sr->scale_y)			) return 1;		if (tl->hwtx) r2d->stencil_delete(tl->hwtx);		if (tl->tx_path) gf_path_del(tl->tx_path);		tl->tx_path = NULL;		tl->hwtx = r2d->stencil_new(r2d, GF_STENCIL_TEXTURE);		tl->last_scale.x = tl->sr->scale_x;		tl->last_scale.y = tl->sr->scale_y;	}	max = INT2FIX(512);	scale = MAX(tl->last_scale.x, tl->last_scale.y);	if ((gf_mulfix(scale, tl->bounds.width)>max)	|| (gf_mulfix(scale, tl->bounds.height)>max)) {		scale = MIN(gf_divfix(max, tl->bounds.width), gf_divfix(max, tl->bounds.height));	}	if (scale<FIX_ONE) scale = FIX_ONE;	width = FIX2INT(gf_ceil(gf_mulfix(scale, tl->bounds.width)));	height = FIX2INT(gf_ceil(gf_mulfix(scale, tl->bounds.height)));	width += 1; 	height += 1;	surf = r2d->surface_new(r2d, 1);	if (!surf) {		r2d->stencil_delete(tl->hwtx);		tl->hwtx = NULL;		tl->failed = 1;		return 0;	}	/*FIXME - make it work with alphagrey...*/	e = r2d->stencil_create_texture(tl->hwtx, width, height, GF_PIXEL_ARGB);	if (!e) e = r2d->surface_attach_to_texture(surf, tl->hwtx);	r2d->surface_clear(surf, NULL, 0);	stenc = r2d->stencil_new(r2d, GF_STENCIL_SOLID);	r2d->stencil_set_brush_color(stenc, 0xFF000000);//	cx = (tl->path->max_x + tl->path->min_x) / 2; //	cy = (tl->path->max_y + tl->path->min_y) / 2;	cx = tl->bounds.x + tl->bounds.width/2; 	cy = tl->bounds.y - tl->bounds.height/2;	gf_mx2d_init(mx);	gf_mx2d_add_translation(&mx, -cx, -cy);	gf_mx2d_add_scale(&mx, scale, scale);	gf_mx2d_add_translation(&mx, FIX_ONE/3, FIX_ONE/3);	r2d->surface_set_matrix(surf, &mx);	r2d->surface_set_raster_level(surf, GF_RASTER_HIGH_QUALITY);	r2d->surface_set_path(surf, tl->path);	r2d->surface_fill(surf, stenc);	r2d->stencil_delete(stenc);	r2d->surface_delete(surf);	tl->tx_path = gf_path_new();	gf_path_add_move_to(tl->tx_path, tl->bounds.x, tl->bounds.y-tl->bounds.height);	gf_path_add_line_to(tl->tx_path, tl->bounds.x+tl->bounds.width, tl->bounds.y-tl->bounds.height);	gf_path_add_line_to(tl->tx_path, tl->bounds.x+tl->bounds.width, tl->bounds.y);	gf_path_add_line_to(tl->tx_path, tl->bounds.x, tl->bounds.y);	gf_path_close(tl->tx_path);	tl->tx_bounds.x = tl->tx_bounds.y = 0;	tl->tx_bounds.width = INT2FIX(width);	tl->tx_bounds.height = INT2FIX(height);	if (e) {		r2d->stencil_delete(tl->hwtx);		tl->hwtx = NULL;		tl->failed = 1;		return 0;	}	tl->tx_ready = 1;	return 1;}void TextStack2D_clean_paths(TextStack2D *stack){	TextLineEntry2D *tl;	/*delete all path objects*/	while (gf_list_count(stack->text_lines)) {		tl = (TextLineEntry2D *) gf_list_get(stack->text_lines, 0);		gf_list_rem(stack->text_lines, 0);		if (tl->path) gf_path_del(tl->path);		if (tl->hwtx) tl->sr->compositor->r2d->stencil_delete(tl->hwtx);		if (tl->tx_path) gf_path_del(tl->tx_path);		free(tl);	}	gf_rect_reset(&stack->bounds);	drawable_reset_path(stack->graph);}static void split_text_letters(TextStack2D *st, M_Text *txt, RenderEffect2D *eff){	unsigned short wcTemp[5000];	unsigned short letter[2];	DrawableContext *ctx;	TextLineEntry2D *tl;	u32 i, j, len;	Fixed fontSize, start_y, font_height, line_spacing;	GF_Rect rc, bounds;	GF_FontRaster *ft_dr = eff->surface->render->compositor->font_engine;	M_FontStyle *fs = (M_FontStyle *)txt->fontStyle;	fontSize = FSSIZE;	if (fontSize <= 0) {		fontSize = INT2FIX(12);		if (!R2D_IsPixelMetrics((GF_Node *)txt)) fontSize = gf_divfix(fontSize, eff->surface->render->cur_width);    }	line_spacing = gf_mulfix(FSSPACE, fontSize);	if (ft_dr->set_font(ft_dr, FSFAMILY, FSSTYLE) != GF_OK) {		if (ft_dr->set_font(ft_dr, NULL, NULL) != GF_OK) {			return;		}	}	ft_dr->set_font_size(ft_dr, fontSize);	ft_dr->get_font_metrics(ft_dr, &st->ascent, &st->descent, &font_height);				if (!strcmp(FSMINOR, "MIDDLE")) {		start_y = (st->descent + st->ascent)/2;	}	else if (!strcmp(FSMINOR, "BEGIN")) {		start_y = st->descent;	}	else if (!strcmp(FSMINOR, "END")) {		start_y = st->descent + st->ascent;	}	else {		start_y = st->ascent;	}		gf_rect_reset(&st->bounds);	for (i=0; i < txt->string.count; i++) {		char *str = txt->string.vals[i];		if (!str) continue;		len = gf_utf8_mbstowcs(wcTemp, 5000, (const char **) &str);		if (len == (size_t) (-1)) continue;		letter[1] = (unsigned short) 0;		for (j=0; j<len; j++) {			if (FSLTR) {				letter[0] = wcTemp[j];			} else {				letter[0] = wcTemp[len - j - 1];			}			/*request a context (first one is always valid when entering render)*/			if (j) group2d_start_child(eff->parent);			ctx = drawable_init_context(st->graph, eff);			if (!ctx) return;			ctx->flags |= CTX_IS_TEXT;			tl = NewTextLine2D(eff->surface->render);			gf_list_add(st->text_lines, tl);			ctx->sub_path_index = gf_list_count(st->text_lines);			ft_dr->add_text_to_path(ft_dr, tl->path, 1, letter, 0, start_y, FIX_ONE, FIX_ONE, st->ascent, &rc);			bounds.width = rc.width;			bounds.x = rc.x;			bounds.height = MAX(st->ascent + st->descent, rc.height);			bounds.y = start_y;			TextLine_StoreBounds(tl);			drawable_finalize_render(ctx, eff, &bounds);			group2d_end_child(eff->parent);		}	}}static void split_text_words(TextStack2D *st, M_Text *txt, RenderEffect2D *eff){	unsigned short wcTemp[5000];	unsigned short letter[5000];	DrawableContext *ctx;	TextLineEntry2D *tl;	u32 i, j, len, k, first_char;	Fixed fontSize, font_height, line_spacing;	GF_Rect rc, bounds;	GF_FontRaster *ft_dr = eff->surface->render->compositor->font_engine;	M_FontStyle *fs = (M_FontStyle *)txt->fontStyle;	fontSize = FSSIZE;	if (fontSize <= 0) {		fontSize = INT2FIX(12);		if (!R2D_IsPixelMetrics((GF_Node *)txt)) fontSize = gf_divfix(fontSize, eff->surface->render->cur_width);    }	line_spacing = gf_mulfix(FSSPACE, fontSize);	if (ft_dr->set_font(ft_dr, FSFAMILY, FSSTYLE) != GF_OK) {		if (ft_dr->set_font(ft_dr, NULL, NULL) != GF_OK) {			return;		}	}	ft_dr->set_font_size(ft_dr, fontSize);	ft_dr->get_font_metrics(ft_dr, &st->ascent, &st->descent, &font_height);	gf_rect_reset(&st->bounds);	for (i=0; i < txt->string.count; i++) {		char *str = txt->string.vals[i];		if (!str) continue;		len = gf_utf8_mbstowcs(wcTemp, 5000, (const char **) &str);		if (len == (size_t) (-1)) continue;		first_char = 0;		for (j=0; j<len; j++) {			/*we currently only split sentences at spaces*/			if ((j+1!=len) && (wcTemp[j] != (unsigned short) ' ')) continue;			if (FSLTR) {				for (k=0; k<=j - first_char; k++) letter[k] = wcTemp[first_char+k];			} else {				for (k=0; k<=j - first_char; k++) letter[k] = wcTemp[len - first_char - k - 1];			}			letter[k] = (unsigned short) 0;			/*request a context (first one is always valid when entering render)*/			if (first_char) group2d_start_child(eff->parent);						ctx = drawable_init_context(st->graph, eff);			if (!ctx) return;			ctx->flags |= CTX_IS_TEXT;			tl = NewTextLine2D(eff->surface->render);			gf_list_add(st->text_lines, tl);			ctx->sub_path_index = gf_list_count(st->text_lines);			/*word splitting only happen in layout, so we don't need top/left anchors*/			ft_dr->add_text_to_path(ft_dr, tl->path, 1, letter, 0, 0, FIX_ONE, FIX_ONE, st->ascent, &rc);			bounds.width = rc.width;			bounds.height = st->ascent + st->descent;			bounds.x = bounds.y = 0;			tl->bounds = bounds;			drawable_finalize_render(ctx, eff, &bounds);			group2d_end_child(eff->parent);			first_char = j+1;		}	}}/*for vert and horiz text*/typedef struct{	unsigned short *wcText;	u32 length;	Fixed width, height;	Fixed x_scaling, y_scaling;} TextLine2D;static void BuildVerticalTextGraph(TextStack2D *st, M_Text *txt, RenderEffect2D *eff){	TextLine2D *lines;	unsigned short wcTemp[5000];	u32 i, int_major, len, k;	Fixed fontSize, start_x, start_y, space, line_spacing, tot_width, tot_height, max_scale, tmp;	GF_Rect rc, final;	Fixed lw, lh, max_lw;	unsigned short letter[2];	GF_FontRaster *ft_dr = eff->surface->render->compositor->font_engine;	M_FontStyle *fs = (M_FontStyle *)txt->fontStyle;	fontSize = FSSIZE;	if (fontSize <= 0) {		fontSize = INT2FIX(12);		if (!R2D_IsPixelMetrics((GF_Node *)txt)) fontSize = gf_divfix(fontSize, eff->surface->render->cur_width);    }	line_spacing = gf_mulfix(FSSPACE, fontSize);	if (ft_dr->set_font(ft_dr, FSFAMILY, FSSTYLE) != GF_OK) {		if (ft_dr->set_font(ft_dr, NULL, NULL) != GF_OK) {			return;		}	}	ft_dr->set_font_size(ft_dr, fontSize);	ft_dr->get_font_metrics(ft_dr, &st->ascent, &st->descent, &space);	/*compute overall bounding box size*/	tot_width = 0;	tot_height = 0;	lines = (TextLine2D *) malloc(sizeof(TextLine2D)*txt->string.count);	memset(lines, 0, sizeof(TextLine2D)*txt->string.count);			letter[1] = (unsigned short) '\0';/*	space = st->ascent + st->descent;	space = fontSize - st->ascent + st->descent;*/	for (i=0; i < txt->string.count; i++) {		char *str = txt->string.vals[i];		if (!str) continue;		lines[i].length = 0;		len = gf_utf8_mbstowcs(wcTemp, 5000, (const char **) &str);		if (len == (size_t) (-1)) continue;		lines[i].wcText = (u16*)malloc(sizeof(unsigned short) * len);		memcpy(lines[i].wcText, wcTemp, sizeof(unsigned short) * len);		lines[i].length = len;				lines[i].y_scaling = lines[i].x_scaling = FIX_ONE;		lines[i].height = len * space;		if (!lines[i].height) continue;		if ((txt->length.count>i) && (txt->length.vals[i]>0) ) 			lines[i].y_scaling = gf_divfix(txt->length.vals[i], lines[i].height);			tmp = gf_mulfix(lines[i].height, lines[i].y_scaling);		if (tot_height < tmp) tot_height = tmp;	}	tot_width = txt->string.count * line_spacing;	st->bounds.width = tot_width;	max_scale = FIX_ONE;	if ((txt->maxExtent>0) && (tot_height>txt->maxExtent)) {		max_scale = gf_divfix(txt->maxExtent, tot_height);		tot_height = txt->maxExtent;	}	if (!strcmp(FSMINOR, "MIDDLE")) {		if (FSLTR) {			start_x = -tot_width/2;			st->bounds.x = start_x;		} else {			start_x = tot_width/2 - line_spacing;			st->bounds.x = - tot_width + line_spacing;		}	}	else if (!strcmp(FSMINOR, "END")) {		if (FSLTR) {			start_x = -tot_width;			st->bounds.x = start_x;		} else {			start_x = tot_width-line_spacing;			st->bounds.x = 0;		}	}	else {		if (FSLTR) {			start_x = 0;			st->bounds.x = start_x;		} else {			start_x = -line_spacing;			st->bounds.x = -tot_width;		}	}	if (!strcmp(FSMAJOR, "MIDDLE")) {		int_major = 0;

⌨️ 快捷键说明

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