Esempio n. 1
0
/**
 * Tells whether a line break can occur between two Unicode characters.
 * This is a wrapper function to expose a simple interface.  Generally
 * speaking, it is better to use #set_linebreaks_utf32 instead, since
 * complicated cases involving combining marks, spaces, etc. cannot be
 * correctly processed.
 *
 * @param char1 the first Unicode character
 * @param char2 the second Unicode character
 * @param lang  language of the input
 * @return      one of #LINEBREAK_MUSTBREAK, #LINEBREAK_ALLOWBREAK,
 *				#LINEBREAK_NOBREAK, or #LINEBREAK_INSIDEACHAR
 */
int is_line_breakable(
		utf32_t char1,
		utf32_t char2,
		const char* lang)
{
	utf32_t s[2];
	char brks[2];
	s[0] = char1;
	s[1] = char2;
	set_linebreaks_utf32(s, 2, lang, brks);
	return brks[0];
}
Esempio n. 2
0
/*
*func:计算给定字符串text 在给定宽度内以自动断行的方式
*       能输出多少行,并返回每一行的指针
*gc[IN]:字符输出的系统环境
*width[IN]:给定宽度
*lang[IN]:文本本地化代码标志
*text[IN]:给定字符串
*len[IN]:给定字符串的字节长
*max_line[IN]:给定的最大可输出行数,即line_len的数组大小,防止越界,请注意不能小于2
*line_from[IN,OUT]:需要外部分配内存后传入,用于返回各行的字符串在  给定字符串text
				:中的索引,若为NULL,表示 不需要返回字节长度
*line_len[IN,OUT]:需要外部分配内存后传入,用于返回各行的字符串字节长度
                         :若为NULL,表示 不需要返回字节长度
*line_width[IN,OUT]:用于返回各行的字符串输出的实际宽度,
  需要外部分配提供,大小同line_len,如果为NULL,表示不需要返回宽度
*返回:能输出的行数,-1为出错

*常用用法:1 . 获取字符串能输出的行数
                             lines = utf32GetTextExWordBreakLines(gc,screenwidth,lang,pStr,strlen(pStr),100,NULL,NULL,NULL);
                       2 . 获取字符串能输出的行数及各行的信息(长度、位置)
                             int *line_from = malloc(100);
                             int *line_len = malloc(100);
                             lines = utf32GetTextExWordBreakLines(gc,screenwidth,lang,pStr,strlen(pStr),100,line_from,line_len,NULL);   
                             for(i=0;i<lines;i++)
                             	drawText(gc,pStr+line_from[i],line_len[i]); 
                             
*/
int
utf32GetTextExWordBreakLines(GR_GC_ID gc, GR_SIZE width,const char* lang,
		const char *text, size_t len, int max_line,int line_from[],int line_len[],int line_width[])
{
	GR_SIZE w, h, b;
	GR_SIZE last_w;//当前字符宽度超过给定宽度时,用于回退到上一次小于给定宽度时的宽度
	char *brks;//保存各字节能否break的信息
	int i;
	int line_start;//每行行首所在(相对于整个字符串)
	int last_word;//上一次字符串宽度小于给定宽度时的那个字符所在
	int line_count = 0;//可输出行数
	int word_locate;
	int wordcount = len/4;//字符个数
	const char *text_lang;
	
	NxGetGCTextSize(gc, text, len, MWTF_UC32, &w, &h, &b);
	if (w <= width) {//不够输出一行
		if(line_len){
			line_len[line_count] = len;
		}
		if(line_from){
			line_from[line_count] = 0;
		}
		
		if(line_width){
			line_width[line_count] = w;
		}
		line_count = 1;
		
		return line_count;
	}

	brks = app_malloc(wordcount);
	if (brks == NULL)
		return -1;

	text_lang = get_text_lang(UTF32LE, text, len);
	/* Show the breaking points */
    set_linebreaks_utf32(text, wordcount, text_lang, brks);

	line_start = 0;
	last_word = 0;
	for (i = 1; i <= wordcount; i++) {
		switch (brks[i-1]) {
		case LINEBREAK_MUSTBREAK:
		case LINEBREAK_ALLOWBREAK:
			NxGetGCTextSize(gc, text + 4*line_start, 4*(i - line_start), MWTF_UC32, &w, &h, &b);
			if (w > width) {
				if (last_word > line_start) {
					if (w - last_w > width) {
						int partial_len;
						GR_SIZE partial_w;
						partial_len = locate_word_to_fit(gc, width - last_w,
									text + 4*last_word, 4*(i - last_word), &partial_w);
						partial_len /= 4;
						last_word += partial_len;
						last_w += partial_w;
					}
					if(line_len){
						line_len[line_count] = 4*(last_word - line_start);
					}
					if(line_from){
						line_from[line_count] = 4*(line_start);
					}
					if(line_width){
						line_width[line_count] = last_w;
					}
					line_count++;
					line_start = last_word;
					w = w - last_w;
					if(line_count>=max_line){
						app_free(brks);
						return line_count;
					}
				}

				/* too long word */
				while (w > width) {
					word_locate = locate_word_to_fit(gc, width, text + 4*line_start, 4*(i - line_start), &last_w);
					word_locate /= 4;
					if(line_len){
						line_len[line_count] = 4*word_locate;//locate_word_to_fit(gc, width, text + line_start, i - line_start, &last_w);
					}
					if(line_from){
						line_from[line_count] = 4*line_start;
					}
					if(line_width){
						line_width[line_count] = last_w;
					}

					line_start += word_locate;

					line_count++;
					w = w - last_w;
					if(line_count>=max_line){
						app_free(brks);
						return line_count;
					}
				}
			}
			if (brks[i-1] == LINEBREAK_MUSTBREAK || w == width) {
				if(line_len){
					line_len[line_count] = 4*(i - line_start);
				}
				if(line_from){
					line_from[line_count] = 4*(line_start);
				}
				if(line_width){
					line_width[line_count] = w;
				}
				
				line_count++;

				line_start = i;
				last_word = line_start;
				last_w = 0;
				if(line_count>=max_line){
					app_free(brks);
					return line_count;
				}
			} else {
				last_word = i;
				last_w = w;
			}
			break;
		}
	}

	if (line_start < wordcount) {

		if(line_count>=max_line){
			app_free(brks);
			return line_count;
		}
		if(line_len){
			line_len[line_count] = 4*(wordcount - line_start);
		}
		if(line_from){
			line_from[line_count] = 4*line_start;
		}
		if(line_width){
			line_width[line_count] = w;
		}
		
		line_count++;
	}

	app_free(brks);
	return line_count;
}
Esempio n. 3
0
int dsShow_parse_lines(DaisyShow *thiz, utf32_t *text, int size)
{
	char *brks;
	int skip = MAX_SHOW_LEN / thiz->font_size;
	int  width, byte_len,ch_len;
	int brk_index;
	//int count;
	int cal_width;
//	size_t in_ret, out_ret;
//	gchar *p, *q;
//	char dbg_info[1024];
	int line_idx = 0;
	size_t i, start;
	utf32_t *line_start;
	size_t line_len;
	
    enum _State
    {
        STAT_INIT,
        STAT_IN_LINE,
        STAT_OUT_LINE,
    }state = STAT_INIT;

	DBGMSG("size=%d\n", size);
	thiz->total_line = 0;
	thiz->show_line = 0;
	if(size <=0){
		return -1;
	}
	
	brks = (char *)malloc(size);
	set_linebreaks_utf32((const utf32_t *)text, 
		size, "zh", brks);

	start = 0;
	brk_index = -1;
	
	i = 0;
	
	while(i < size){
		if(brks[i] != LINEBREAK_NOBREAK){
			brk_index = i;
		}
		switch(state){
		case STAT_INIT:
		{
			if(text[i] == 0xA){
				state = STAT_OUT_LINE;
			}
			else{
				state = STAT_IN_LINE;
			}
		}
		break;
		case STAT_IN_LINE:
		{
			if(text[i] == 0xA){
				state = STAT_OUT_LINE;
				thiz->show_text[line_idx] = (char*)text+start;
				thiz->show_txtlen[line_idx] = (i - start)*4;
				line_idx++;

				start = i+1; /*skip 0xA*/
				brk_index = -1;
				break;
			}
			
			//ch_len = count;
			ch_len = (i - start+1);
			if(ch_len <= skip){
				break;
			}
			
			
			byte_len = (i - start+1)*4;

			//info_err("byte_len=%d\n", byte_len);
			width = cal_text_len(thiz,(char*)(text+start), byte_len);
			cal_width = MAX_SHOW_LEN;
			
			//info_err("width=%d, cal with=%d\n", width, cal_width);
			if(width <= cal_width){
				break;
			}

			state = STAT_OUT_LINE;
			line_start = text+start;
			if(brk_index > 0){
				line_len = brk_index - start;
				start = brk_index;
				brk_index = -1;
				//DBGMSG("i =%d, start=%d\n", i, start);
			}
			else{
				DBGMSG("force line break\n");
				line_len = i - start;
				start = i;
			}
			if(brks[i] != LINEBREAK_NOBREAK){
				brk_index = i;
			}

			thiz->show_text[line_idx] = (char*)line_start;
			thiz->show_txtlen[line_idx] = line_len*4;
			line_idx++;
			state = STAT_IN_LINE; /*because i*/
		}
		break;
		case STAT_OUT_LINE:
		{
			if(text[i] == 0xA){
				state = STAT_OUT_LINE;
				/*empty new line*/
				line_start = text+start;
				line_len = 0;
				start = i+1; /*skip 0xA*/
				brk_index = -1;
				
				thiz->show_text[line_idx] = (char*)line_start;
				thiz->show_txtlen[line_idx] = line_len*4;
				line_idx++;
			}
			else{
				state = STAT_IN_LINE;
				
			}
		}
		break;
		default:break;
		}

		i++;
		if(line_idx>=MAX_SHOW_LINE){
			info_err("so much lines\n");
			break;
		}
	}
	free(brks);

	if((start < size) && (line_idx<MAX_SHOW_LINE)){
		line_start = text+start;
		line_len = size - start;
		brk_index = -1;
	
		thiz->show_text[line_idx] = (char*)line_start;
		thiz->show_txtlen[line_idx] = line_len*4;
		line_idx++;
	}

	thiz->total_line = line_idx;
	thiz->start_line = 0;
	if(thiz->screen_line < thiz->total_line){
		thiz->show_line = thiz->screen_line;
	}
	else{
		thiz->show_line = thiz->total_line;
	}
	/*fill show lines*/
	DBGMSG("parse end\n");
	return 0;
}