mirror of
https://github.com/VincentWei/MiniGUI.git
synced 2026-09-24 00:54:18 +08:00
normal, word break and alignment
This commit is contained in:
@@ -111,7 +111,7 @@ BOOL DrawShapedGlyph(HDC hdc, Glyph32 gv,
|
||||
|
||||
int DrawLayoutLine(HDC hdc, const LAYOUTLINE* line, int x, int y)
|
||||
{
|
||||
int n, line_adv = 0;
|
||||
int n, line_offset, line_adv = 0;
|
||||
struct list_head* i;
|
||||
const TEXTRUNSINFO* truninfo;
|
||||
const LAYOUTINFO* layout;
|
||||
@@ -147,6 +147,8 @@ int DrawLayoutLine(HDC hdc, const LAYOUTLINE* line, int x, int y)
|
||||
break;
|
||||
}
|
||||
|
||||
line_offset = __mg_layout_get_line_offset(layout, line);
|
||||
|
||||
old_lf = GetCurFont(hdc);
|
||||
list_for_each(i, &line->gruns) {
|
||||
GlyphRun* run = (GlyphRun*)i;
|
||||
@@ -175,11 +177,13 @@ int DrawLayoutLine(HDC hdc, const LAYOUTLINE* line, int x, int y)
|
||||
}
|
||||
|
||||
if (layout->rf & GRF_WRITING_MODE_VERTICAL_FLAG) {
|
||||
log_y = line_adv;
|
||||
log_x = 0;
|
||||
log_y = line_adv;
|
||||
log_y += line_offset;
|
||||
}
|
||||
else {
|
||||
log_x = line_adv;
|
||||
log_x += line_offset;
|
||||
log_y = 0;
|
||||
}
|
||||
|
||||
|
||||
+177
-23
@@ -219,8 +219,6 @@ struct _LayoutState {
|
||||
/* maintained per paragraph */
|
||||
// Current resolved base direction
|
||||
ParagraphDir base_dir;
|
||||
// Line of the paragraph, starting at 1 for first line
|
||||
int line_of_par;
|
||||
// Glyphs for the current glyph run
|
||||
GlyphString* glyphs;
|
||||
// Logical widths for the current text run */
|
||||
@@ -462,6 +460,8 @@ static void shape_space(const LAYOUTINFO* layout, const LayoutRun* lrun,
|
||||
gstr->glyphs[i].width = 0;
|
||||
}
|
||||
|
||||
gstr->glyphs[i].height = lrun->lf->size;
|
||||
|
||||
gstr->glyphs[i].is_cluster_start = 1;
|
||||
gstr->log_clusters[i] = i;
|
||||
|
||||
@@ -606,7 +606,7 @@ static inline void print_line_runs(const LAYOUTLINE* line, const char* func)
|
||||
_DBG_PRINTF(" LENGHT: %d\n", run->lrun->len);
|
||||
_DBG_PRINTF(" EMBEDDING LEVEL:%d\n", run->lrun->el);
|
||||
_DBG_PRINTF(" NO SHAPING :%s\n",
|
||||
(run->lrun->noshape) ? "YES" : "NO");
|
||||
(run->lrun->flags & LAYOUTRUN_FLAG_NO_SHAPING) ? "YES" : "NO");
|
||||
_DBG_PRINTF(" NR GLYPHS: %d\n", run->gstr->nr_glyphs);
|
||||
j++;
|
||||
}
|
||||
@@ -669,8 +669,6 @@ static void uninsert_run(LAYOUTLINE *line)
|
||||
line->len -= grun->lrun->len;
|
||||
line->nr_runs--;
|
||||
free_glyph_run(grun);
|
||||
|
||||
print_line_runs(line, __FUNCTION__);
|
||||
}
|
||||
|
||||
static GlyphRun* insert_run(LAYOUTLINE *line, LayoutState *state,
|
||||
@@ -696,8 +694,6 @@ static GlyphRun* insert_run(LAYOUTLINE *line, LayoutState *state,
|
||||
line->len += layout_run->len;
|
||||
line->nr_runs++;
|
||||
|
||||
print_line_runs(line, __FUNCTION__);
|
||||
|
||||
return glyph_run;
|
||||
}
|
||||
|
||||
@@ -709,12 +705,14 @@ static inline BOOL can_break_at (LAYOUTINFO *layout,
|
||||
if (offset == layout->truninfo->nr_ucs)
|
||||
return TRUE;
|
||||
|
||||
if (wrap == GRF_OVERFLOW_WRAP_NORMAL)
|
||||
wrap = always_wrap_char ? GRF_OVERFLOW_WRAP_ANYWHERE :
|
||||
GRF_OVERFLOW_WRAP_BREAK_WORD;
|
||||
if (always_wrap_char)
|
||||
wrap = GRF_OVERFLOW_WRAP_ANYWHERE;
|
||||
|
||||
if (wrap == GRF_OVERFLOW_WRAP_NORMAL)
|
||||
return (layout->bos[offset] & BOV_LB_MASK) == BOV_LB_ALLOWED;
|
||||
else if (wrap == GRF_OVERFLOW_WRAP_BREAK_WORD)
|
||||
return layout->bos[offset] & BOV_LB_BREAK_FLAG;
|
||||
return (offset > 0 &&
|
||||
(layout->bos[offset - 1] & BOV_WB_WORD_BOUNDARY));
|
||||
else if (wrap == GRF_OVERFLOW_WRAP_ANYWHERE)
|
||||
return layout->bos[offset] & BOV_GB_CHAR_BREAK;
|
||||
else {
|
||||
@@ -725,11 +723,12 @@ static inline BOOL can_break_at (LAYOUTINFO *layout,
|
||||
}
|
||||
|
||||
static inline BOOL can_break_in (LAYOUTINFO *layout,
|
||||
int start_offset, int num_chars, BOOL allow_break_at_start)
|
||||
int start_offset, int num_chars, BOOL allow_break_at_start)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = allow_break_at_start ? 0 : 1; i < num_chars; i++)
|
||||
// VincentWei: we must ignore allow_break_at_start here.
|
||||
for (i = /* allow_break_at_start ? 0 : */0; i < num_chars; i++)
|
||||
if (can_break_at (layout, start_offset + i, FALSE))
|
||||
return TRUE;
|
||||
|
||||
@@ -804,7 +803,6 @@ BreakResult process_layout_run(LAYOUTINFO *layout,
|
||||
state->remaining_width -= width;
|
||||
state->remaining_width = MAX (state->remaining_width, 0);
|
||||
insert_run (line, state, lrun, TRUE);
|
||||
|
||||
return BREAK_ALL_FIT;
|
||||
}
|
||||
else {
|
||||
@@ -858,7 +856,7 @@ retry_break:
|
||||
break_num_chars - 1];
|
||||
}
|
||||
|
||||
if ((layout->rf & GRF_OVERFLOW_WRAP_MASK) == GRF_OVERFLOW_WRAP_NORMAL
|
||||
if ((layout->rf & GRF_OVERFLOW_WRAP_MASK) == GRF_OVERFLOW_WRAP_ANYWHERE
|
||||
&& force_fit
|
||||
&& break_width > state->remaining_width
|
||||
&& !retrying_with_char_breaks) {
|
||||
@@ -905,6 +903,8 @@ retry_break:
|
||||
/* Shaped lruns should never be broken */
|
||||
assert (!shape_set);
|
||||
|
||||
print_line_runs(line, __FUNCTION__);
|
||||
|
||||
return BREAK_SOME_FIT;
|
||||
}
|
||||
}
|
||||
@@ -1121,9 +1121,9 @@ static void layout_line_reorder(LAYOUTLINE *line)
|
||||
reverse_runs(&line->gruns, runs, length);
|
||||
}
|
||||
|
||||
#if 0 /* test code for list_reverse and reverse_runs */
|
||||
print_line_runs(line, __FUNCTION__);
|
||||
|
||||
#if 0 /* test code for list_reverse and reverse_runs */
|
||||
list_reverse(&line->gruns);
|
||||
print_line_runs(line, "list_reverse");
|
||||
|
||||
@@ -1563,8 +1563,10 @@ static void layout_line_postprocess (LAYOUTLINE *line,
|
||||
|
||||
}
|
||||
|
||||
#if 0
|
||||
_DBG_PRINTF("%s: ellipsized: %s\n",
|
||||
__FUNCTION__, ellipsized ? "TRUE" : "FALSE");
|
||||
#endif
|
||||
|
||||
/* Now convert logical to visual order
|
||||
*/
|
||||
@@ -1602,7 +1604,6 @@ static LAYOUTLINE* check_next_line(LAYOUTINFO* layout, LayoutState* state)
|
||||
|
||||
line = layout_line_new (layout);
|
||||
line->si = state->line_start_index;
|
||||
line->is_paragraph_start = state->line_of_par == 1;
|
||||
line_set_resolved_dir(line, state->base_dir);
|
||||
|
||||
line->width = -1;
|
||||
@@ -1640,7 +1641,7 @@ static LAYOUTLINE* check_next_line(LAYOUTINFO* layout, LayoutState* state)
|
||||
have_break = TRUE;
|
||||
break_remaining_width = old_remaining_width;
|
||||
break_start_offset = state->start_offset;
|
||||
break_link = line->gruns.next;
|
||||
break_link = line->gruns.prev;
|
||||
}
|
||||
|
||||
state->trun = (const TextRun*)state->trun->list.next;
|
||||
@@ -1659,6 +1660,8 @@ static LAYOUTLINE* check_next_line(LAYOUTINFO* layout, LayoutState* state)
|
||||
case BREAK_SOME_FIT:
|
||||
state->start_offset += old_num_chars - state->lrun->len;
|
||||
wrapped = TRUE;
|
||||
|
||||
print_line_runs(line, __FUNCTION__);
|
||||
goto done;
|
||||
|
||||
case BREAK_NONE_FIT:
|
||||
@@ -1666,13 +1669,15 @@ static LAYOUTLINE* check_next_line(LAYOUTINFO* layout, LayoutState* state)
|
||||
|
||||
/* Back up over unused runs to run where there is a break */
|
||||
while (!list_empty(&line->gruns) &&
|
||||
line->gruns.next != break_link) {
|
||||
line->gruns.prev != break_link) {
|
||||
uninsert_run(line);
|
||||
}
|
||||
|
||||
state->start_offset = break_start_offset;
|
||||
state->remaining_width = break_remaining_width;
|
||||
|
||||
print_line_runs(line, __FUNCTION__);
|
||||
|
||||
/* determine start text run again */
|
||||
state->trun = __mg_text_run_get_by_offset_const(layout->truninfo,
|
||||
state->start_offset, &state->start_index_in_trun);
|
||||
@@ -1709,11 +1714,148 @@ static LAYOUTLINE* check_next_line(LAYOUTINFO* layout, LayoutState* state)
|
||||
|
||||
done:
|
||||
layout_line_postprocess(line, state, wrapped);
|
||||
state->line_of_par++;
|
||||
state->line_start_index += line->len;
|
||||
return line;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static inline int paragraph_dir_to_simple(ParagraphDir d)
|
||||
{
|
||||
switch (d) {
|
||||
default:
|
||||
case BIDI_PGDIR_LTR:
|
||||
case BIDI_PGDIR_WLTR:
|
||||
return 1;
|
||||
case BIDI_PGDIR_RTL:
|
||||
case BIDI_PGDIR_WRTL:
|
||||
return -1;
|
||||
case BIDI_PGDIR_ON:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int line_dir_to_simple(LineDirection d)
|
||||
{
|
||||
switch (d) {
|
||||
default:
|
||||
case LINE_DIRECTION_LTR:
|
||||
case LINE_DIRECTION_WEAK_LTR:
|
||||
return 1;
|
||||
case LINE_DIRECTION_RTL:
|
||||
case LINE_DIRECTION_WEAK_RTL:
|
||||
return -1;
|
||||
case LINE_DIRECTION_NEUTRAL:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* call this when layout has auto_dir property */
|
||||
static Uint32 get_line_alignment(const LAYOUTINFO *layout,
|
||||
const LAYOUTLINE *line)
|
||||
{
|
||||
Uint32 alignment = layout->rf & GRF_ALIGN_MASK;
|
||||
|
||||
if (alignment != GRF_ALIGN_CENTER && layout->auto_dir &&
|
||||
line_dir_to_simple (line->resolved_dir) ==
|
||||
-paragraph_dir_to_simple (layout->trunsinfo->base_dir)) {
|
||||
if (alignment == GRF_ALIGN_LEFT)
|
||||
alignment = GRF_ALIGN_RIGHT;
|
||||
else if (alignment == GRF_ALIGN_RIGHT)
|
||||
alignment = GRF_ALIGN_LEFT;
|
||||
}
|
||||
|
||||
return alignment;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static Uint32 get_line_alignment(const LAYOUTINFO *layout,
|
||||
const LAYOUTLINE *line)
|
||||
{
|
||||
Uint32 alignment = layout->rf & GRF_ALIGN_MASK;
|
||||
|
||||
switch (alignment) {
|
||||
case GRF_ALIGN_START:
|
||||
if ((layout->rf & GRF_TEXT_ORIENTATION_MASK) ==
|
||||
GRF_TEXT_ORIENTATION_SIDEWAYS_LEFT)
|
||||
alignment = GRF_ALIGN_RIGHT;
|
||||
else
|
||||
alignment = GRF_ALIGN_LEFT;
|
||||
break;
|
||||
|
||||
case GRF_ALIGN_END:
|
||||
if ((layout->rf & GRF_TEXT_ORIENTATION_MASK) ==
|
||||
GRF_TEXT_ORIENTATION_SIDEWAYS_LEFT)
|
||||
alignment = GRF_ALIGN_LEFT;
|
||||
else
|
||||
alignment = GRF_ALIGN_RIGHT;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return alignment;
|
||||
}
|
||||
#endif
|
||||
|
||||
int __mg_layout_get_line_offset(const LAYOUTINFO *layout,
|
||||
const LAYOUTLINE *line)
|
||||
{
|
||||
int x_offset;
|
||||
int layout_width;
|
||||
Uint32 alignment = get_line_alignment(layout, line);
|
||||
|
||||
x_offset = 0;
|
||||
if (alignment == GRF_ALIGN_JUSTIFY)
|
||||
goto done;
|
||||
|
||||
layout_width = line->max_extent;
|
||||
if (layout_width < 0)
|
||||
goto done;
|
||||
|
||||
/* Alignment */
|
||||
if (alignment == GRF_ALIGN_RIGHT) {
|
||||
x_offset = layout_width - line->width;
|
||||
}
|
||||
else if (alignment == GRF_ALIGN_CENTER) {
|
||||
x_offset = (layout_width - line->width) / 2;
|
||||
/* hinting */
|
||||
if ((layout_width | line->width) & 1) {
|
||||
x_offset += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Indentation */
|
||||
if ((layout->rf & GRF_INDENT_MASK) == GRF_INDENT_FIRST_LINE &&
|
||||
line->is_paragraph_start) {
|
||||
if (alignment == GRF_ALIGN_LEFT)
|
||||
x_offset += layout->indent;
|
||||
else if (alignment == GRF_ALIGN_RIGHT)
|
||||
x_offset -= layout->indent;
|
||||
else
|
||||
x_offset -= layout->indent / 2;
|
||||
}
|
||||
else if ((layout->rf & GRF_INDENT_MASK) == GRF_INDENT_HANGING &&
|
||||
!line->is_paragraph_start) {
|
||||
if (alignment == GRF_ALIGN_LEFT)
|
||||
x_offset += layout->indent;
|
||||
else if (alignment == GRF_ALIGN_RIGHT)
|
||||
x_offset -= layout->indent;
|
||||
else
|
||||
x_offset -= layout->indent / 2;
|
||||
}
|
||||
|
||||
done:
|
||||
return x_offset;
|
||||
}
|
||||
|
||||
static int traverse_line_glyphs(const LAYOUTINFO* layout,
|
||||
const LAYOUTLINE* line,
|
||||
CB_GLYPH_LAID_OUT cb_laid_out, GHANDLE ctxt)
|
||||
@@ -1723,6 +1865,7 @@ static int traverse_line_glyphs(const LAYOUTINFO* layout,
|
||||
int line_adv = 0;
|
||||
RENDERDATA extra;
|
||||
Uint32 def_ta, up_ta;
|
||||
int line_offset;
|
||||
|
||||
extra.truninfo = layout->truninfo;
|
||||
extra.layout = layout;
|
||||
@@ -1751,6 +1894,8 @@ static int traverse_line_glyphs(const LAYOUTINFO* layout,
|
||||
break;
|
||||
}
|
||||
|
||||
line_offset = __mg_layout_get_line_offset(layout, line);
|
||||
|
||||
list_for_each(i, &line->gruns) {
|
||||
GlyphRun* run = (GlyphRun*)i;
|
||||
for (j = 0; j < run->gstr->nr_glyphs; j++) {
|
||||
@@ -1770,12 +1915,13 @@ static int traverse_line_glyphs(const LAYOUTINFO* layout,
|
||||
gi = run->gstr->glyphs + j;
|
||||
|
||||
if (layout->rf & GRF_WRITING_MODE_VERTICAL_FLAG) {
|
||||
pos.y = line_adv;
|
||||
pos.x = 0;
|
||||
|
||||
pos.y = line_adv;
|
||||
pos.y += line_offset;
|
||||
}
|
||||
else {
|
||||
pos.x = line_adv;
|
||||
pos.x += line_offset;
|
||||
pos.y = 0;
|
||||
}
|
||||
|
||||
@@ -1847,9 +1993,11 @@ static int traverse_line_glyphs(const LAYOUTINFO* layout,
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
_DBG_PRINTF("%s: uc: %c, width: %d, pos (%d, %d), off (%d, %d)\n",
|
||||
__FUNCTION__, extra.uc, gi->width,
|
||||
pos.x, pos.y, pos.x_off, pos.y_off);
|
||||
#endif
|
||||
|
||||
if (!cb_laid_out(ctxt, gi->gv, &pos, &extra))
|
||||
return j;
|
||||
@@ -1902,7 +2050,6 @@ LAYOUTLINE* GUIAPI LayoutNextLine(
|
||||
//state.shape_logical_rect;
|
||||
|
||||
state.base_dir = layout->truninfo->base_dir;
|
||||
state.line_of_par = 1;
|
||||
state.glyphs = NULL;
|
||||
state.log_widths = NULL;
|
||||
state.log_widths_offset = 0;
|
||||
@@ -1926,9 +2073,11 @@ LAYOUTLINE* GUIAPI LayoutNextLine(
|
||||
state.trun = __mg_text_run_get_by_offset_const(layout->truninfo,
|
||||
state.line_start_index, &state.start_index_in_trun);
|
||||
|
||||
#if 0
|
||||
_DBG_PRINTF("%s: line_start_index: %d, start_index_in_trun: %d(%p)\n",
|
||||
__FUNCTION__, state.line_start_index, state.start_index_in_trun,
|
||||
state.trun);
|
||||
#endif
|
||||
|
||||
if (state.trun == NULL) {
|
||||
next_line = NULL;
|
||||
@@ -1973,6 +2122,11 @@ LAYOUTLINE* GUIAPI LayoutNextLine(
|
||||
next_line->width = calc_line_width(next_line);
|
||||
next_line->height = calc_line_height(next_line);
|
||||
|
||||
if (layout->nr_lines == 0)
|
||||
next_line->is_paragraph_start = 1;
|
||||
else
|
||||
next_line->is_paragraph_start = 0;
|
||||
|
||||
if (layout->persist) {
|
||||
list_add_tail(&next_line->list, &layout->lines);
|
||||
}
|
||||
|
||||
@@ -214,6 +214,9 @@ int __mg_shape_layout_run(const TEXTRUNSINFO* info, const LayoutRun* run,
|
||||
void __mg_reverse_shaped_glyphs(ShapedGlyph* glyphs, int len);
|
||||
void __mg_reverse_log_clusters(int* clusters, int len);
|
||||
|
||||
int __mg_layout_get_line_offset(const LAYOUTINFO *layout,
|
||||
const LAYOUTLINE *line);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
Reference in New Issue
Block a user