/** 更新数据 */ void TextLayer_Update( LCUI_TextLayer layer, LinkedList *rect_list ) { if( layer->task.update_bitmap ) { TextLayer_InvalidateRowsRect( layer, 0, -1 ); TextLayer_ReloadCharBitmap( layer ); TextLayer_InvalidateRowsRect( layer, 0, -1 ); layer->task.update_bitmap = FALSE; layer->task.redraw_all = TRUE; } if( layer->task.update_typeset ) { TextLayer_TextTypeset( layer, layer->task.typeset_start_row ); layer->task.update_typeset = FALSE; layer->task.typeset_start_row = 0; } layer->width = TextLayer_GetWidth( layer ); /* 如果坐标偏移量有变化,记录各个文本行区域 */ if( layer->new_offset_x != layer->offset_x || layer->new_offset_y != layer->offset_y ) { TextLayer_InvalidateRowsRect( layer, 0, -1 ); layer->offset_x = layer->new_offset_x; layer->offset_y = layer->new_offset_y; TextLayer_InvalidateRowsRect( layer, 0, -1 ); layer->task.redraw_all = TRUE; } if( rect_list ) { LinkedList_Concat( rect_list, &layer->dirty_rect ); } }
/** 从指定行开始,对文本进行排版 */ static void TextLayer_TextTypeset( LCUI_TextLayer *layer, int start_row ) { int row; /* 记录排版前各个文本行的矩形区域 */ TextLayer_InvalidateRowsRect( layer, start_row, -1 ); for( row=start_row; row<layer->row_list.rows; ++row ) { TextLayer_TextRowTypeset( layer, row ); } /* 记录排版后各个文本行的矩形区域 */ TextLayer_InvalidateRowsRect( layer, start_row, -1 ); }
/** 清空文本 */ void TextLayer_ClearText( LCUI_TextLayer layer ) { layer->length = 0; layer->insert_x = 0; layer->insert_y = 0; layer->width = 0; TextLayer_InvalidateRowsRect( layer, 0, -1 ); TextRowList_Destroy( &layer->rowlist ); LinkedList_Clear( &layer->style_cache, (FuncPtr)TextStyle_Destroy ); TextRowList_InsertNewRow( &layer->rowlist, 0 ); layer->task.redraw_all = TRUE; }
/** 对文本进行预处理 */ 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_DeleteText( LCUI_TextLayer* layer, int char_y, int char_x, int n_char ) { int end_x, end_y, i, j, len; TextRowData *p_row, *p_end_row, *p_prev_row; if( char_x < 0 ) { char_x = 0; } if( char_y < 0 ) { char_y = 0; } if( n_char <= 0 ) { return -1; } if( char_y >= layer->row_list.rows ) { return -2; } p_row = layer->row_list.rowdata[char_y]; if( char_x > p_row->string_len ) { char_x = p_row->string_len; } end_x = char_x; end_y = char_y; --n_char; /* 计算结束点的位置 */ for( end_y=char_y; end_y<layer->row_list.rows && n_char>0; ++end_y ) { p_row = layer->row_list.rowdata[end_y]; if( p_row->eol == EOL_NONE ) { if( end_x + n_char < p_row->string_len ) { end_x += n_char; n_char = 0; break; } } else { if( end_x + n_char <= p_row->string_len ) { end_x += n_char; n_char = 0; break; } } n_char -= (p_row->string_len - end_x); end_x = 0; } if( end_y >= layer->row_list.rows ) { end_y = layer->row_list.rows-1; } p_end_row = layer->row_list.rowdata[end_y]; if( end_x > p_end_row->string_len ) { end_x = p_end_row->string_len; } /* 获取上一行文本 */ p_prev_row = layer->row_list.rowdata[char_y-1]; // 计算起始行与结束行拼接后的长度 // 起始行:0 1 2 3 4 5,起点位置:2 // 结束行:0 1 2 3 4 5,终点位置:4 // 拼接后的长度:2 + 6 - 4 - 1 = 3 len = char_x + p_end_row->string_len - end_x - 1; if( len < 0 ) { return -3; } /* 如果是同一行 */ if( p_row == p_end_row ) { if( end_x >= p_end_row->string_len ) { return -4; } TextLayer_InvalidateRowRectEx( layer, char_y, char_x, -1 ); TaskData_AddUpdateTypeset( &layer->task, char_y ); for( i=char_x, j=end_x+1; j<p_row->string_len; ++i,++j ) { p_row->string[i] = p_row->string[j]; } /* 如果当前行为空,也不是第一行,并且上一行没有结束符 */ if( len <= 0 && end_y > 0 && p_prev_row->eol != EOL_NONE ) { TextRowList_RemoveRow( &layer->row_list, end_y ); } /* 调整起始行的容量 */ TextRow_SetLength( p_row, len ); /* 更新文本行的尺寸 */ TextRow_UpdateSize( p_row, layer->text_style.pixel_size ); return 0; } /* 如果结束点在行尾,并且该行不是最后一行 */ if( end_x == p_end_row->string_len && end_y < layer->row_list.rows-1 ) { ++end_y; p_end_row = TextRowList_GetRow( &layer->row_list, end_y ); end_x = -1; len = char_x + p_end_row->string_len; } TextRow_SetLength( p_row, len ); /* 标记当前行后面的所有行的矩形需区域需要刷新 */ TextLayer_InvalidateRowsRect( layer, char_y+1, -1 ); /* 移除起始行与结束行之间的文本行 */ for( i=char_y+1, j=i; j<end_y; ++j ) { TextLayer_InvalidateRowRect( layer, i ); TextRowList_RemoveRow( &layer->row_list, i ); } end_y = char_y + 1; /* 将结束行的内容拼接至起始行 */ for( i=char_x, j=end_x+1; i<len && j<p_end_row->string_len; ++i,++j ) { p_row->string[i] = p_end_row->string[j]; } TextRow_UpdateSize( p_row, layer->text_style.pixel_size ); TextLayer_InvalidateRowRect( layer, end_y ); /* 移除结束行 */ TextRowList_RemoveRow( &layer->row_list, end_y ); /* 如果起始行无内容,并且上一行没有结束符(换行符),则 * 说明需要删除起始行 */ if( len <= 0 && char_y > 0 && p_prev_row->eol != EOL_NONE ) { TextLayer_InvalidateRowRect( layer, char_y ); TextRowList_RemoveRow( &layer->row_list, char_y ); } TaskData_AddUpdateTypeset( &layer->task, char_y );; return 0; }
/** 删除指定行列的文字及其右边的文本 */ static int TextLayer_TextDeleteEx( LCUI_TextLayer layer, int char_y, int char_x, int n_char ) { int end_x, end_y, i, j, len; TextRow txtrow, end_txtrow, prev_txtrow; if( char_x < 0 ) { char_x = 0; } if( char_y < 0 ) { char_y = 0; } if( n_char <= 0 ) { return -1; } if( char_y >= layer->rowlist.length ) { return -2; } txtrow = layer->rowlist.rows[char_y]; if( char_x > txtrow->length ) { char_x = txtrow->length; } i = n_char; end_x = char_x; end_y = char_y; /* 计算结束点的位置 */ for( ; end_y < layer->rowlist.length && n_char > 0; ++end_y ) { txtrow = layer->rowlist.rows[end_y]; if( end_x + n_char <= txtrow->length ) { end_x += n_char; n_char = 0; break; } n_char -= (txtrow->length - end_x); if( txtrow->eol == EOL_NONE ) { end_x = 0; } else { n_char -= 1; end_x = 0; } } if( n_char >= 0 ) { layer->length -= i - n_char; } else { layer->length -= n_char; } if( end_y >= layer->rowlist.length ) { end_y = layer->rowlist.length - 1; end_txtrow = layer->rowlist.rows[end_y]; end_x = end_txtrow->length; } else { end_txtrow = layer->rowlist.rows[end_y]; } if( end_x > end_txtrow->length ) { end_x = end_txtrow->length; } if( end_x == char_x && end_y == char_y ) { return 0; } /* 获取上一行文本 */ prev_txtrow = layer->rowlist.rows[char_y - 1]; // 计算起始行与结束行拼接后的长度 // 起始行:0 1 2 3 4 5,起点位置:2 // 结束行:0 1 2 3 4 5,终点位置:4 // 拼接后的长度:2 + 6 - 4 = 4 len = char_x + end_txtrow->length - end_x; if( len < 0 ) { return -3; } /* 如果是同一行 */ if( txtrow == end_txtrow ) { if( end_x > end_txtrow->length ) { return -4; } TextLayer_InvalidateRowRect( layer, char_y, char_x, -1 ); TextLayer_AddUpdateTypeset( layer, char_y ); for( i = char_x, j = end_x; j < txtrow->length; ++i, ++j ) { txtrow->string[i] = txtrow->string[j]; } /* 如果当前行为空,也不是第一行,并且上一行没有结束符 */ if( len <= 0 && end_y > 0 && prev_txtrow->eol != EOL_NONE ) { TextRowList_RemoveRow( &layer->rowlist, end_y ); } /* 调整起始行的容量 */ TextRow_SetLength( txtrow, len ); /* 更新文本行的尺寸 */ TextLayer_UpdateRowSize( layer, txtrow ); return 0; } /* 如果结束点在行尾,并且该行不是最后一行 */ if( end_x == end_txtrow->length && end_y < layer->rowlist.length - 1 ) { ++end_y; end_txtrow = TextLayer_GetRow( layer, end_y ); end_x = -1; len = char_x + end_txtrow->length; } TextRow_SetLength( txtrow, len ); /* 标记当前行后面的所有行的矩形需区域需要刷新 */ TextLayer_InvalidateRowsRect( layer, char_y + 1, -1 ); /* 移除起始行与结束行之间的文本行 */ for( i = char_y + 1, j = i; j < end_y; ++j ) { TextLayer_InvalidateRowRect( layer, i, 0, -1 ); TextRowList_RemoveRow( &layer->rowlist, i ); } i = char_x; j = end_x + 1; end_y = char_y + 1; /* 将结束行的内容拼接至起始行 */ for( ; i < len && j < end_txtrow->length; ++i, ++j ) { txtrow->string[i] = end_txtrow->string[j]; } TextLayer_UpdateRowSize( layer, txtrow ); TextLayer_InvalidateRowRect( layer, end_y, 0, -1 ); /* 移除结束行 */ TextRowList_RemoveRow( &layer->rowlist, end_y ); /* 如果起始行无内容,并且上一行没有结束符(换行符),则 * 说明需要删除起始行 */ if( len <= 0 && char_y > 0 && prev_txtrow->eol != EOL_NONE ) { TextLayer_InvalidateRowRect( layer, char_y, 0, -1 ); TextRowList_RemoveRow( &layer->rowlist, char_y ); } TextLayer_AddUpdateTypeset( layer, char_y );; 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; }