/** 对文本进行预处理 */ static int TextLayer_ProcessText( LCUI_TextLayer *layer, const wchar_t *wstr, TextAddType add_type, LCUI_StyleTagStack *tag_stack ) { EOLChar eol; int cur_col, cur_row, start_row, ins_x, ins_y; const wchar_t *p_end, *p, *pp; TextRowData *p_row; TextCharData char_data; LCUI_StyleTagStack tmp_tag_stack; LCUI_BOOL is_tmp_tag_stack, need_typeset, rect_has_added; if( !wstr ) { return -1; } is_tmp_tag_stack = FALSE; need_typeset = FALSE; rect_has_added = FALSE; /* 如果是将文本追加至文本末尾 */ if( add_type == TEXT_ADD_TYPE_APPEND ) { if( layer->row_list.rows > 0 ) { cur_row = layer->row_list.rows - 1; } else { cur_row = 0; } p_row = TextRowList_GetRow( &layer->row_list, cur_row ); if( !p_row ) { p_row = TextRowList_AddNewRow( &layer->row_list ); } cur_col = p_row->string_len; } else { /* 否则,是将文本插入至当前插入点 */ cur_row = layer->insert_y; cur_col = layer->insert_x; p_row = TextRowList_GetRow( &layer->row_list, cur_row ); if( !p_row ) { p_row = TextRowList_AddNewRow( &layer->row_list ); } } start_row = cur_row; ins_x = cur_col; ins_y = cur_row; /* 如果没有可用的标签栈,则使用临时的标签栈 */ if( !tag_stack ) { is_tmp_tag_stack = TRUE; StyleTagStack_Init( &tmp_tag_stack ); tag_stack = &tmp_tag_stack; } p_end = wstr + wcslen(wstr); for( p=wstr; p<p_end; ++p ) { if( layer->is_using_style_tags ) { /* 处理样式的结束标签 */ pp = StyleTagStack_ScanEndingTag( tag_stack, p ); if( pp ) { p = pp; /* 抵消本次循环后的++p,以在下次循环时还能够在当前位置 */ --p; continue; } /* 处理样式标签 */ pp = StyleTagStack_ScanBeginTag( tag_stack, p ); if( pp ) { p = pp - 1; continue; } } if( *p == '\r' || *p == '\n' ) { /* 如果后面还有 \n,则说明是CR/LF换行模式 */ if( *p == 'r' ) { if( p+1 < p_end && *(p+1) == '\n' ) { eol = EOL_CR_LF; } else { /* 否则是CR换行模式 */ eol = EOL_CR; } } else { eol = EOL_LF; } /* 如果没有记录过文本行的矩形区域 */ if( !rect_has_added ) { TextLayer_InvalidateRowsRect( layer, ins_y, -1 ); rect_has_added = TRUE; start_row = ins_y; } /* 将当前行中的插入点为截点,进行断行 */ TextLayer_BreakTextRow( layer, ins_y, ins_x, eol ); need_typeset = TRUE; ins_x = 0; ++ins_y; p_row = TextRowList_GetRow( &layer->row_list, ins_y ); continue; } char_data.char_code = *p; /* 获取当前文本样式数据 */ char_data.style = StyleTagStack_GetTextStyle( tag_stack ); /* 更新字体位图 */ TextChar_UpdateBitmap( &char_data, &layer->text_style ); TextRow_InsertCopy( p_row, ins_x, &char_data ); ++ins_x; } /* 更新当前行的尺寸 */ TextRow_UpdateSize( p_row, layer->text_style.pixel_size ); if( add_type == TEXT_ADD_TYPE_INSERT ) { layer->insert_x = ins_x; layer->insert_y = ins_y; } /* 若启用了自动换行模式,则标记需要重新对文本进行排版 */ if( layer->is_autowrap_mode || need_typeset ) { TaskData_AddUpdateTypeset( &layer->task, cur_row ); } else { TextLayer_InvalidateRowRect( layer, cur_row ); } /* 如果已经记录过文本行矩形区域 */ if( rect_has_added ) { TextLayer_InvalidateRowsRect( layer, start_row, -1 ); rect_has_added = TRUE; } /* 如果使用的是临时标签栈,则销毁它 */ if( is_tmp_tag_stack ) { StyleTagStack_Destroy( tag_stack ); } return 0; }
/** 对文本进行预处理 */ static int TextLayer_ProcessText( LCUI_TextLayer layer, const wchar_t *wstr, int add_type, LinkedList *tags ) { EOLChar eol; TextRow txtrow; TextCharRec txtchar; LinkedList tmp_tags; LCUI_TextStyle *style = NULL; const wchar_t *p_end, *p, *pp; int cur_col, cur_row, start_row, ins_x, ins_y; LCUI_BOOL is_tmp_tag_stack, need_typeset, rect_has_added; if( !wstr ) { return -1; } need_typeset = FALSE; rect_has_added = FALSE; is_tmp_tag_stack = FALSE; /* 如果是将文本追加至文本末尾 */ if( add_type == TAT_APPEND ) { if( layer->rowlist.length > 0 ) { cur_row = layer->rowlist.length - 1; } else { cur_row = 0; } txtrow = TextLayer_GetRow( layer, cur_row ); if( !txtrow ) { txtrow = TextRowList_AddNewRow( &layer->rowlist ); } cur_col = txtrow->length; } else { /* 否则,是将文本插入至当前插入点 */ cur_row = layer->insert_y; cur_col = layer->insert_x; txtrow = TextLayer_GetRow( layer, cur_row ); if( !txtrow ) { txtrow = TextRowList_AddNewRow( &layer->rowlist ); } } start_row = cur_row; ins_x = cur_col; ins_y = cur_row; /* 如果没有可用的标签栈,则使用临时的标签栈 */ if( !tags ) { is_tmp_tag_stack = TRUE; StyleTags_Init( &tmp_tags ); tags = &tmp_tags; } p_end = wstr + wcslen( wstr ); for( p = wstr; p < p_end; ++p ) { /* 如果启用的样式标签支持,则处理样式的结束标签 */ if( layer->is_using_style_tags ) { pp = StyleTags_ScanEndingTag( tags, p ); if( pp ) { /* 抵消本次循环后的++p,以在下次循环时还能够在当前位置 */ p = pp - 1; style = StyleTags_GetTextStyle( tags ); LinkedList_Append( &layer->style_cache, style ); continue; } pp = StyleTags_ScanBeginTag( tags, p ); if( pp ) { p = pp - 1; style = StyleTags_GetTextStyle( tags ); LinkedList_Append( &layer->style_cache, style ); continue; } } if( *p == '\r' || *p == '\n' ) { /* 判断是哪一种换行模式 */ if( *p == '\r' ) { if( p + 1 < p_end && *(p + 1) == '\n' ) { eol = EOL_CR_LF; } else { eol = EOL_CR; } } else { eol = EOL_LF; } /* 如果没有记录过文本行的矩形区域 */ if( !rect_has_added ) { TextLayer_InvalidateRowsRect( layer, ins_y, -1 ); rect_has_added = TRUE; start_row = ins_y; } /* 将当前行中的插入点为截点,进行断行 */ TextLayer_BreakTextRow( layer, ins_y, ins_x, eol ); layer->width = max( layer->width, txtrow->width ); need_typeset = TRUE; ++layer->length; ins_x = 0; ++ins_y; txtrow = TextLayer_GetRow( layer, ins_y ); continue; } txtchar.style = style; txtchar.char_code = *p; TextChar_UpdateBitmap( &txtchar, &layer->text_style ); TextRow_InsertCopy( txtrow, ins_x, &txtchar ); ++layer->length; ++ins_x; } /* 更新当前行的尺寸 */ TextLayer_UpdateRowSize( layer, txtrow ); layer->width = max( layer->width, txtrow->width ); if( add_type == TAT_INSERT ) { layer->insert_x = ins_x; layer->insert_y = ins_y; } /* 若启用了自动换行模式,则标记需要重新对文本进行排版 */ if( layer->is_autowrap_mode || need_typeset ) { TextLayer_AddUpdateTypeset( layer, cur_row ); } else { TextLayer_InvalidateRowRect( layer, cur_row, 0, -1 ); } /* 如果已经记录过文本行矩形区域 */ if( rect_has_added ) { TextLayer_InvalidateRowsRect( layer, start_row, -1 ); rect_has_added = TRUE; } /* 如果使用的是临时标签栈,则销毁它 */ if( is_tmp_tag_stack ) { StyleTags_Clear( tags ); } return 0; }
/** 对指定行的文本进行排版 */ static void TextLayer_TextRowTypeset( LCUI_TextLayer* layer, int row ) { int col, row_width; TextRowData *p_row, *p_next_row; TextCharData *p_char; p_row = layer->row_list.rowdata[row]; row_width = 0; for( col=0; col<p_row->string_len; ++col ) { p_char = p_row->string[col]; if( !p_char->bitmap ) { continue; } /* 累加行宽度 */ row_width += p_char->bitmap->advance.x; /* 如果是当前行的第一个字符,或者行宽度没有超过宽度限制 */ if( layer->max_width <= 0 || !layer->is_autowrap_mode || (layer->is_autowrap_mode && !layer->is_mulitiline_mode) || col < 1 || p_row->max_width <= layer->max_width ) { continue; } TextLayer_BreakTextRow( layer, row, col, EOL_NONE ); return; } TextRow_UpdateSize( p_row, layer->text_style.pixel_size ); /* 如果本行有换行符,或者是最后一行 */ if( p_row->eol != EOL_NONE || row == layer->row_list.rows-1 ) { return; } row_width = p_row->max_width; /* 本行的文本宽度未达到限制宽度,需要将下行的文本转移至本行 */ while( p_row->eol != EOL_NONE ) { /* 获取下一行的指针 */ p_next_row = TextRowList_GetRow( &layer->row_list, row+1 ); if( !p_next_row ) { return; } for( col=0; col<p_next_row->string_len; ++col ) { p_char = p_next_row->string[col]; /* 忽略无字体位图的文字 */ if( !p_char->bitmap ) { TextRow_Insert( p_row, p_row->string_len, p_char ); p_next_row->string[col] = NULL; continue; } row_width += p_char->bitmap->advance.x; /* 如果没有超过宽度限制 */ if( !layer->is_autowrap_mode || layer->max_width <= 0 || (layer->is_autowrap_mode && !layer->is_mulitiline_mode) || p_row->max_width <= layer->max_width ) { TextRow_Insert( p_row, p_row->string_len, p_char ); p_next_row->string[col] = NULL; continue; } /* 如果插入点在下一行 */ if( layer->insert_y == row+1 ) { /* 如果插入点处于被转移的几个文字中 */ if( layer->insert_x < col ) { layer->insert_y = row; layer->insert_x += p_row->string_len; } else { /* 否则,减去被转移的文字数 */ layer->insert_x -= col; } } /* 将这一行剩余的文字向前移 */ TextRow_LeftMove( p_next_row, col ); TextRow_UpdateSize( p_row, layer->text_style.pixel_size ); return; } TextRow_UpdateSize( p_row, layer->text_style.pixel_size ); TextLayer_InvalidateRowRect( layer, row ); TextLayer_InvalidateRowRect( layer, row+1 ); _DEBUG_MSG("remove row %d\n", row+1); /* 删除这一行,因为这一行的内容已经转移至当前行 */ TextRowList_RemoveRow( &layer->row_list, row+1 ); /* 如果插入点当前行在后面 */ if( layer->insert_y > row ) { --layer->insert_y; } } }
/** 对指定行的文本进行排版 */ static void TextLayer_TextRowTypeset( LCUI_TextLayer layer, int row ) { TextRow txtrow; TextChar txtchar; LCUI_BOOL not_autowrap; int col, row_width = 0; int max_width; if( layer->fixed_width > 0 ) { max_width = layer->fixed_width; } else { max_width = layer->max_width; } if( max_width <= 0 || !layer->is_autowrap_mode || (layer->is_autowrap_mode && !layer->is_mulitiline_mode) ) { not_autowrap = TRUE; } else { not_autowrap = FALSE; } txtrow = layer->rowlist.rows[row]; for( col = 0; col < txtrow->length; ++col ) { txtchar = txtrow->string[col]; if( !txtchar->bitmap ) { continue; } /* 累加行宽度 */ row_width += txtchar->bitmap->advance.x; /* 如果是当前行的第一个字符,或者行宽度没有超过宽度限制 */ if( not_autowrap || col < 1 || row_width <= max_width ) { continue; } TextLayer_BreakTextRow( layer, row, col, EOL_NONE ); return; } TextLayer_UpdateRowSize( layer, txtrow ); /* 如果本行有换行符,或者是最后一行 */ if( txtrow->eol != EOL_NONE || row == layer->rowlist.length - 1 ) { return; } row_width = txtrow->width; /* 本行的文本宽度未达到限制宽度,需要将下行的文本转移至本行 */ while( txtrow->eol == EOL_NONE ) { /* 获取下一行的指针 */ TextRow next_txtrow = TextLayer_GetRow( layer, row + 1 ); if( !next_txtrow ) { break; } for( col = 0; col < next_txtrow->length; ++col ) { txtchar = next_txtrow->string[col]; /* 忽略无字体位图的文字 */ if( !txtchar->bitmap ) { TextRow_Insert( txtrow, -1, txtchar ); next_txtrow->string[col] = NULL; continue; } row_width += txtchar->bitmap->advance.x; /* 如果没有超过宽度限制 */ if( not_autowrap || row_width <= max_width ) { TextRow_Insert( txtrow, -1, txtchar ); next_txtrow->string[col] = NULL; continue; } /* 如果插入点在下一行 */ if( layer->insert_y == row + 1 ) { /* 如果插入点处于被转移的几个文字中 */ if( layer->insert_x < col ) { layer->insert_y = row; layer->insert_x += txtrow->length; } else { /* 否则,减去被转移的文字数 */ layer->insert_x -= col; } } /* 将这一行剩余的文字向前移 */ TextRow_LeftMove( next_txtrow, col ); TextLayer_UpdateRowSize( layer, txtrow ); return; } txtrow->eol = next_txtrow->eol; TextLayer_UpdateRowSize( layer, txtrow ); TextLayer_InvalidateRowRect( layer, row, 0, -1 ); TextLayer_InvalidateRowRect( layer, row + 1, 0, -1 ); /* 删除这一行,因为这一行的内容已经转移至当前行 */ TextRowList_RemoveRow( &layer->rowlist, row + 1 ); /* 如果插入点当前行在后面 */ if( layer->insert_y > row ) { --layer->insert_y; } } }