mirror of
https://github.com/VincentWei/MiniGUI.git
synced 2026-09-26 20:45:36 +08:00
go on
This commit is contained in:
+2
-1
@@ -12730,7 +12730,8 @@ typedef struct _LAYOUTLINE LAYOUTLINE;
|
||||
MG_EXPORT LAYOUTINFO* GUIAPI CreateLayoutInfo(
|
||||
const TEXTRUNSINFO* run_info, Uint32 render_flags,
|
||||
const BreakOppo* break_oppos, BOOL persist_lines,
|
||||
int letter_spacing, int word_spacing, int tab_size);
|
||||
int letter_spacing, int word_spacing, int tab_size,
|
||||
int* tabs, int nr_tabs);
|
||||
|
||||
/**
|
||||
* Destroy the specified layout information structure.
|
||||
|
||||
@@ -43,10 +43,11 @@
|
||||
#ifndef GUI_UNICODE_OPS_H
|
||||
#define GUI_UNICODE_OPS_H
|
||||
|
||||
#define UCHAR_SPACE 0x0020
|
||||
#define UCHAR_SHY 0x00AD
|
||||
#define UCHAR_IDSPACE 0x3000
|
||||
#define UCHAR_TAB 0x0009
|
||||
#define UCHAR_TAB 0x0009
|
||||
#define UCHAR_SPACE 0x0020
|
||||
#define UCHAR_SHY 0x00AD
|
||||
#define UCHAR_IDSPACE 0x3000
|
||||
#define UCHAR_LINE_SEPARATOR 0x2028
|
||||
|
||||
#define PAREN_STACK_DEPTH 128
|
||||
|
||||
|
||||
@@ -353,24 +353,6 @@ static void shape_ellipsis (EllipsizeState *state)
|
||||
state->ellipsis_width += glyphs->glyphs[i].width;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Helper function to advance a PangoAttrIterator to a particular
|
||||
* byte index.
|
||||
*/
|
||||
static void advance_iterator_to (PangoAttrIterator *iter, int new_index)
|
||||
{
|
||||
int start, end;
|
||||
|
||||
do
|
||||
{
|
||||
pango_attr_iterator_range (iter, &start, &end);
|
||||
if (end > new_index)
|
||||
break;
|
||||
}
|
||||
while (pango_attr_iterator_next (iter));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Updates the shaping of the ellipsis if necessary when we move the
|
||||
* position of the start of the gap.
|
||||
*
|
||||
@@ -609,7 +591,6 @@ static void get_run_list (EllipsizeState *state, LAYOUTLINE* line)
|
||||
if (run_iter->end_char != run_info->run->lrun->len) {
|
||||
partial_end_run = run_info->run;
|
||||
run_info->run = __mg_glyph_run_split (run_info->run,
|
||||
state->layout->truninfo->ucs,
|
||||
run_iter->end_index - run_info->run->lrun->si);
|
||||
}
|
||||
|
||||
@@ -617,7 +598,6 @@ static void get_run_list (EllipsizeState *state, LAYOUTLINE* line)
|
||||
run_iter = &state->gap_start_iter.run_iter;
|
||||
if (run_iter->start_char != 0) {
|
||||
partial_start_run = __mg_glyph_run_split (run_info->run,
|
||||
state->layout->truninfo->ucs,
|
||||
run_iter->start_index - run_info->run->lrun->si);
|
||||
}
|
||||
|
||||
|
||||
@@ -124,6 +124,15 @@ void __mg_release_logfont_for_layout(const LAYOUTINFO* layout,
|
||||
ReleaseRes(Str2Key(my_fontname));
|
||||
}
|
||||
|
||||
/*
|
||||
* Not like Pango, we simply use the properties of the referenced TextRun
|
||||
* for the new orphan LayoutRun, including the direction, the orientation,
|
||||
* the embedding level, and the language, except the script type.
|
||||
*
|
||||
* Therefore, we assume that the text of the new LayoutRun are all
|
||||
* in the same script, same direction, and same orientation. This is
|
||||
* enough for the ellipsis.
|
||||
*/
|
||||
LayoutRun* __mg_layout_run_new_orphan(const LAYOUTINFO* layout,
|
||||
const TextRun* trun, const Uchar32* ucs, int nr_ucs)
|
||||
{
|
||||
@@ -142,7 +151,7 @@ LayoutRun* __mg_layout_run_new_orphan(const LAYOUTINFO* layout,
|
||||
lrun->si = trun->si;
|
||||
lrun->len = trun->len;
|
||||
lrun->lc = trun->lc;
|
||||
lrun->st = trun->st;
|
||||
lrun->st = UCharGetScriptType(ucs[0]);
|
||||
lrun->el = trun->el;
|
||||
lrun->dir = trun->dir;
|
||||
lrun->ort = trun->ort;
|
||||
@@ -339,7 +348,6 @@ void __mg_glyph_run_free(GlyphRun* run)
|
||||
/**
|
||||
* __mg_glyph_run_split:
|
||||
* @orig: a #GlyphRun
|
||||
* @text: text to which positions in @orig apply
|
||||
* @split_index: byte index of position to split item, relative to the start of the item
|
||||
*
|
||||
* Modifies @orig to cover only the text after @split_index, and
|
||||
@@ -357,8 +365,7 @@ void __mg_glyph_run_free(GlyphRun* run)
|
||||
* @split_index, which should be freed
|
||||
* with pango_glyph_run_free().
|
||||
**/
|
||||
GlyphRun *__mg_glyph_run_split (GlyphRun *orig,
|
||||
const Uchar32 *text, int split_index)
|
||||
GlyphRun *__mg_glyph_run_split (GlyphRun *orig, int split_index)
|
||||
{
|
||||
GlyphRun *new_grun;
|
||||
int i;
|
||||
|
||||
+188
-69
@@ -56,7 +56,8 @@
|
||||
LAYOUTINFO* GUIAPI CreateLayoutInfo(
|
||||
const TEXTRUNSINFO* truninfo, Uint32 render_flags,
|
||||
const BreakOppo* break_oppos, BOOL persist_lines,
|
||||
int letter_spacing, int word_spacing, int tab_size)
|
||||
int letter_spacing, int word_spacing, int tab_size,
|
||||
int* tabs, int nr_tabs)
|
||||
{
|
||||
LAYOUTINFO* layout;
|
||||
|
||||
@@ -75,6 +76,8 @@ LAYOUTINFO* GUIAPI CreateLayoutInfo(
|
||||
layout->ls = letter_spacing;
|
||||
layout->ws = word_spacing;
|
||||
layout->ts = tab_size;
|
||||
layout->tabs = tabs;
|
||||
layout->nr_tabs = nr_tabs;
|
||||
|
||||
INIT_LIST_HEAD(&layout->lines);
|
||||
layout->nr_left_ucs = truninfo->nr_ucs;
|
||||
@@ -152,10 +155,8 @@ struct _LayoutState {
|
||||
const TextRun* trun;
|
||||
// Current layout run
|
||||
LayoutRun* lrun;
|
||||
// Start index of line in current lrun */
|
||||
int start_index_in_lrun;
|
||||
// the number of not fit uchars in current text run
|
||||
int left_ucs_in_lrun;
|
||||
// Start index of layout run in current text run */
|
||||
int start_index_in_trun;
|
||||
|
||||
// Goal width of line currently processing; < 0 is infinite
|
||||
int line_width;
|
||||
@@ -180,11 +181,134 @@ static BOOL should_ellipsize_current_line(LAYOUTINFO *layout,
|
||||
int __mg_shape_layout_run(const TEXTRUNSINFO* info, const LayoutRun* run,
|
||||
GlyphString* glyphs)
|
||||
{
|
||||
return 0;
|
||||
if (!info->sei.shape(info->sei.inst, info, run, glyphs))
|
||||
return 0;
|
||||
|
||||
return glyphs->nr_glyphs;
|
||||
}
|
||||
|
||||
static void ensure_tab_width(LAYOUTINFO *layout)
|
||||
{
|
||||
if (layout->ts == -1) {
|
||||
/* Find out how wide 8 spaces are in the context's default
|
||||
* font.
|
||||
*/
|
||||
|
||||
// TODO
|
||||
|
||||
/* We need to make sure the ts is > 0 so finding tab positions
|
||||
* terminates. This check should be necessary only under extreme
|
||||
* problems with the font.
|
||||
*/
|
||||
if (layout->ts <= 0)
|
||||
layout->ts = 50; /* pretty much arbitrary */
|
||||
}
|
||||
}
|
||||
|
||||
/* For now we only need the tab position, we assume
|
||||
* all tabs are left-aligned.
|
||||
*/
|
||||
static int get_tab_pos(LAYOUTINFO *layout, int index, BOOL *is_default)
|
||||
{
|
||||
int n_tabs;
|
||||
|
||||
if (layout->tabs) {
|
||||
n_tabs = layout->nr_tabs;
|
||||
if (is_default)
|
||||
*is_default = FALSE;
|
||||
}
|
||||
else {
|
||||
n_tabs = 0;
|
||||
if (is_default)
|
||||
*is_default = TRUE;
|
||||
}
|
||||
|
||||
if (index < n_tabs) {
|
||||
return layout->tabs[index];
|
||||
}
|
||||
|
||||
if (n_tabs > 0) {
|
||||
/* Extrapolate tab position, repeating the last tab gap to
|
||||
* infinity.
|
||||
*/
|
||||
int last_pos = 0;
|
||||
int next_to_last_pos = 0;
|
||||
int ts;
|
||||
|
||||
last_pos = layout->tabs[n_tabs - 1];
|
||||
|
||||
if (n_tabs > 1)
|
||||
next_to_last_pos = layout->tabs[n_tabs - 2];
|
||||
else
|
||||
next_to_last_pos = 0;
|
||||
|
||||
if (last_pos > next_to_last_pos) {
|
||||
ts = last_pos - next_to_last_pos;
|
||||
}
|
||||
else {
|
||||
ts = layout->ts;
|
||||
}
|
||||
|
||||
return last_pos + ts * (index - n_tabs + 1);
|
||||
}
|
||||
else {
|
||||
/* No tab array set, so use default tab width
|
||||
*/
|
||||
return layout->ts * index;
|
||||
}
|
||||
}
|
||||
|
||||
static int get_line_width(LAYOUTLINE *line)
|
||||
{
|
||||
struct list_head *l;
|
||||
int i;
|
||||
int width = 0;
|
||||
|
||||
/* Compute the width of the line currently - inefficient, but easier
|
||||
* than keeping the current width of the line up to date everywhere
|
||||
*/
|
||||
list_for_each(l, &line->gruns) {
|
||||
GlyphRun *run = (GlyphRun*)l;
|
||||
|
||||
for (i = 0; i < run->gs->nr_glyphs; i++)
|
||||
width += run->gs->glyphs[i].width;
|
||||
}
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
static void shape_tab(LAYOUTLINE *line, GlyphString *glyphs)
|
||||
{
|
||||
int i, space_width;
|
||||
|
||||
int current_width = get_line_width(line);
|
||||
|
||||
__mg_glyph_string_set_size (glyphs, 1);
|
||||
|
||||
glyphs->glyphs[0].gv = INV_GLYPH_VALUE;
|
||||
glyphs->glyphs[0].x_off = 0;
|
||||
glyphs->glyphs[0].y_off = 0;
|
||||
glyphs->glyphs[0].is_cluster_start = 1;
|
||||
|
||||
glyphs->log_clusters[0] = 0;
|
||||
|
||||
ensure_tab_width (line->layout);
|
||||
space_width = line->layout->ts / 8;
|
||||
|
||||
for (i=0; ; i++) {
|
||||
BOOL is_default;
|
||||
int tab_pos = get_tab_pos (line->layout, i, &is_default);
|
||||
/* Make sure there is at least a space-width of space between
|
||||
* tab-aligned text and the text before it. However, only do
|
||||
* this if no tab array is set on the layout, ie. using default
|
||||
* tab positions. If use has set tab positions, respect it to
|
||||
* the pixel.
|
||||
*/
|
||||
if (tab_pos >= current_width + (is_default ? space_width : 1)) {
|
||||
glyphs->glyphs[0].width = tab_pos - current_width;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void shape_shape(const Uchar32* ucs, int nr_ucs,
|
||||
@@ -207,9 +331,11 @@ static void shape_shape(const Uchar32* ucs, int nr_ucs,
|
||||
|
||||
static void shape_full(const Uchar32* lrun_ucs, int nr_lrun_ucs,
|
||||
const Uchar32* para_ucs, int nr_para_ucs,
|
||||
const TEXTRUNSINFO* truninfo, LayoutRun* textrun,
|
||||
const TEXTRUNSINFO* info, LayoutRun* lrun,
|
||||
GlyphString* glyphs)
|
||||
{
|
||||
// TODO
|
||||
info->sei.shape(info->sei.inst, info, lrun, glyphs);
|
||||
}
|
||||
|
||||
static void distribute_letter_spacing (int letter_spacing,
|
||||
@@ -230,7 +356,7 @@ static GlyphString* shape_run(LAYOUTLINE *line, LayoutState *state,
|
||||
LAYOUTINFO *layout = line->layout;
|
||||
GlyphString *glyphs = __mg_glyph_string_new ();
|
||||
|
||||
if (layout->truninfo->ucs[lrun->si] == '\t')
|
||||
if (layout->truninfo->ucs[lrun->si] == UCHAR_TAB)
|
||||
shape_tab(line, glyphs);
|
||||
else {
|
||||
if (state->shape_set)
|
||||
@@ -377,10 +503,6 @@ BreakResult process_text_run(LAYOUTINFO *layout,
|
||||
int i;
|
||||
BOOL processing_new_lrun = FALSE;
|
||||
|
||||
/* Only one character has type UCHAR_CATEGORY_LINE_SEPARATOR in
|
||||
* Unicode 12.0; update this if that changes. */
|
||||
#define LINE_SEPARATOR 0x2028
|
||||
|
||||
if (!state->glyphs) {
|
||||
state->glyphs = shape_run (line, state, lrun);
|
||||
|
||||
@@ -391,17 +513,16 @@ BreakResult process_text_run(LAYOUTINFO *layout,
|
||||
}
|
||||
|
||||
if (!layout->single_paragraph &&
|
||||
layout->truninfo->ucs[lrun->si] == LINE_SEPARATOR &&
|
||||
layout->truninfo->ucs[lrun->si] == UCHAR_LINE_SEPARATOR &&
|
||||
!should_ellipsize_current_line (layout, state)) {
|
||||
insert_run (line, state, lrun, TRUE);
|
||||
insert_run(line, state, lrun, TRUE);
|
||||
state->log_widths_offset += lrun->len;
|
||||
return BREAK_LINE_SEPARATOR;
|
||||
}
|
||||
|
||||
if (state->remaining_width < 0 && !no_break_at_end) /* Wrapping off */
|
||||
{
|
||||
if (state->remaining_width < 0 && !no_break_at_end) {
|
||||
/* Wrapping off */
|
||||
insert_run (line, state, lrun, TRUE);
|
||||
|
||||
return BREAK_ALL_FIT;
|
||||
}
|
||||
|
||||
@@ -449,7 +570,8 @@ retry_break:
|
||||
if (width > state->remaining_width && break_num_chars < lrun->len)
|
||||
break;
|
||||
|
||||
/* If there are no previous runs we have to take care to grab at least one char. */
|
||||
/* If there are no previous runs we have to take care to
|
||||
* grab at least one char. */
|
||||
if (can_break_at (layout, state->start_offset + num_chars,
|
||||
retrying_with_char_breaks) &&
|
||||
(num_chars > 0 || !list_empty(&line->gruns)))
|
||||
@@ -466,9 +588,11 @@ retry_break:
|
||||
* XXX Currently it doesn't quite match the logic there. We don't check
|
||||
* the cluster here. But should be fine in practice. */
|
||||
if (break_num_chars > 0 && break_num_chars < lrun->len &&
|
||||
layout->bos[state->start_offset + break_num_chars - 1] & BOV_WHITESPACE)
|
||||
layout->bos[state->start_offset + break_num_chars - 1] &
|
||||
BOV_WHITESPACE)
|
||||
{
|
||||
break_width -= state->log_widths[state->log_widths_offset + break_num_chars - 1];
|
||||
break_width -= state->log_widths[state->log_widths_offset +
|
||||
break_num_chars - 1];
|
||||
}
|
||||
|
||||
if ((layout->rf & GRF_OVERFLOW_WRAP_MASK) == GRF_OVERFLOW_WRAP_NORMAL
|
||||
@@ -483,8 +607,8 @@ retry_break:
|
||||
goto retry_break;
|
||||
}
|
||||
|
||||
if (force_fit || break_width <= state->remaining_width) /* Successfully broke the lrun */
|
||||
{
|
||||
if (force_fit || break_width <= state->remaining_width) {
|
||||
/* Successfully broke the lrun */
|
||||
if (state->remaining_width >= 0) {
|
||||
state->remaining_width -= break_width;
|
||||
state->remaining_width = MAX (state->remaining_width, 0);
|
||||
@@ -498,13 +622,16 @@ retry_break:
|
||||
return BREAK_EMPTY_FIT;
|
||||
}
|
||||
else {
|
||||
LayoutRun* new_lrun;
|
||||
GlyphRun *grun;
|
||||
|
||||
new_lrun = __mg_layout_run_split(lrun, break_num_chars);
|
||||
|
||||
/* Add the width back, to the line, reshape,
|
||||
subtract the new width */
|
||||
state->remaining_width += break_width;
|
||||
grun = insert_run (line, state, lrun, FALSE);
|
||||
break_width = __mg_glyph_string_get_width (grun->gs);
|
||||
grun = insert_run (line, state, new_lrun, FALSE);
|
||||
break_width = __mg_glyph_string_get_width(grun->gs);
|
||||
state->remaining_width -= break_width;
|
||||
|
||||
state->log_widths_offset += break_num_chars;
|
||||
@@ -1076,7 +1203,8 @@ static void layout_line_postprocess (LAYOUTLINE *line,
|
||||
(wrapped || ellipsized)) {
|
||||
/* if we ellipsized, we don't have remaining_width set */
|
||||
if (state->remaining_width < 0)
|
||||
state->remaining_width = state->line_width - layout_line_get_width (line);
|
||||
state->remaining_width = state->line_width -
|
||||
layout_line_get_width (line);
|
||||
|
||||
justify_words (line, state);
|
||||
}
|
||||
@@ -1085,32 +1213,13 @@ static void layout_line_postprocess (LAYOUTLINE *line,
|
||||
line->layout->is_ellipsized |= ellipsized;
|
||||
}
|
||||
|
||||
static void add_line (LAYOUTLINE *line, LayoutState *state)
|
||||
{
|
||||
#if 0
|
||||
LAYOUTINFO *layout = line->layout;
|
||||
|
||||
list_add_tail(&line->list, &layout->lines);
|
||||
layout->nr_lines++;
|
||||
|
||||
if (layout->height >= 0) {
|
||||
PangoRectangle logical_rect;
|
||||
pango_layout_line_get_extents (line, NULL, &logical_rect);
|
||||
state->remaining_height -= logical_rect.height;
|
||||
state->remaining_height -= layout->spacing;
|
||||
state->line_height = logical_rect.height;
|
||||
}
|
||||
#else
|
||||
// do nothing
|
||||
#endif
|
||||
}
|
||||
|
||||
static LAYOUTLINE* check_next_line(LAYOUTINFO* layout, LayoutState* state)
|
||||
{
|
||||
LAYOUTLINE *line;
|
||||
struct list_head* t;
|
||||
|
||||
BOOL have_break = FALSE; // If we've seen a possible break yet
|
||||
int break_remaining_width = 0;// Remaining width before adding run with break
|
||||
int break_remaining_width = 0;// Left width before adding run with break
|
||||
int break_start_offset = 0; // Start offset before adding run with break
|
||||
struct list_head *break_link = NULL; // Link holding run before break
|
||||
BOOL wrapped = FALSE; // If we had to wrap the line
|
||||
@@ -1125,21 +1234,32 @@ static LAYOUTLINE* check_next_line(LAYOUTINFO* layout, LayoutState* state)
|
||||
else
|
||||
state->remaining_width = state->line_width;
|
||||
|
||||
while (state->lrun) {
|
||||
LayoutRun *lrun = state->lrun;
|
||||
list_for_each_ex(t, &layout->truninfo->truns, &state->trun->list) {
|
||||
state->trun = (const TextRun*)t;
|
||||
LayoutRun *lrun;
|
||||
BreakResult result;
|
||||
int old_num_chars;
|
||||
int old_remaining_width;
|
||||
BOOL first_lrun_in_line;
|
||||
|
||||
if (state->start_index_in_trun > 0) {
|
||||
lrun = __mg_layout_run_new_from_offset(layout,
|
||||
state->trun, state->start_index_in_trun);
|
||||
}
|
||||
else {
|
||||
lrun = __mg_layout_run_new_from(layout, state->trun);
|
||||
}
|
||||
state->lrun = lrun;
|
||||
|
||||
old_num_chars = lrun->len;
|
||||
old_remaining_width = state->remaining_width;
|
||||
first_lrun_in_line = !list_empty(&line->gruns);
|
||||
first_lrun_in_line = list_empty(&line->gruns);
|
||||
|
||||
result = process_text_run(layout, line, state, !have_break, FALSE);
|
||||
switch (result) {
|
||||
case BREAK_ALL_FIT:
|
||||
if (can_break_in (layout, state->start_offset, old_num_chars, first_lrun_in_line))
|
||||
if (can_break_in (layout, state->start_offset,
|
||||
old_num_chars, first_lrun_in_line))
|
||||
{
|
||||
have_break = TRUE;
|
||||
break_remaining_width = old_remaining_width;
|
||||
@@ -1198,7 +1318,6 @@ static LAYOUTLINE* check_next_line(LAYOUTINFO* layout, LayoutState* state)
|
||||
|
||||
done:
|
||||
layout_line_postprocess (line, state, wrapped);
|
||||
add_line (line, state);
|
||||
state->line_of_par++;
|
||||
state->line_start_index += line->len;
|
||||
return line;
|
||||
@@ -1221,7 +1340,14 @@ LAYOUTLINE* GUIAPI LayoutNextLine(
|
||||
if (layout->persist && layout->nr_left_ucs == 0) {
|
||||
// already laid out
|
||||
|
||||
if (prev_line && &prev_line->list != &layout->lines) {
|
||||
if (list_empty(&layout->lines))
|
||||
return NULL;
|
||||
|
||||
if (prev_line == NULL) {
|
||||
next_line = (LAYOUTLINE*)layout->lines.next;
|
||||
goto out;
|
||||
}
|
||||
else if ((struct list_head*)prev_line != &layout->lines) {
|
||||
next_line = (LAYOUTLINE*)prev_line->list.next;
|
||||
goto out;
|
||||
}
|
||||
@@ -1243,30 +1369,24 @@ LAYOUTLINE* GUIAPI LayoutNextLine(
|
||||
state.log_widths_offset = 0;
|
||||
|
||||
if (prev_line == NULL) {
|
||||
state.line_start_index = 0;
|
||||
if (list_empty(&layout->truninfo->truns)) {
|
||||
next_line = layout_line_new(layout);
|
||||
next_line->si = state.line_start_index;
|
||||
next_line->is_paragraph_start = TRUE;
|
||||
line_set_resolved_dir(next_line, layout->truninfo->run_dir);
|
||||
goto next_line;
|
||||
// empty line
|
||||
next_line = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
state.line_start_index = 0;
|
||||
state.start_index_in_trun = 0;
|
||||
state.trun = (TextRun*)&layout->truninfo->truns.next;
|
||||
state.lrun = __mg_layout_run_new_from(layout, state.trun);
|
||||
state.start_index_in_lrun = 0;
|
||||
state.left_ucs_in_lrun = state.lrun->len;
|
||||
}
|
||||
else {
|
||||
state.start_offset = layout->truninfo->nr_ucs - layout->nr_left_ucs;
|
||||
state.line_start_index = layout->truninfo->nr_ucs - layout->nr_left_ucs;
|
||||
state.trun = __mg_textruns_get_by_offset(layout->truninfo,
|
||||
state.start_offset, &state.start_index_in_lrun);
|
||||
state.start_offset, &state.start_index_in_trun);
|
||||
if (state.trun == NULL) {
|
||||
return NULL;
|
||||
next_line = NULL;
|
||||
goto out;
|
||||
}
|
||||
state.lrun = __mg_layout_run_new_from_offset(layout,
|
||||
state.trun, state.start_index_in_lrun);
|
||||
state.left_ucs_in_lrun = state.lrun->len - state.start_index_in_lrun;
|
||||
}
|
||||
|
||||
state.line_width = max_extent;
|
||||
@@ -1274,7 +1394,6 @@ LAYOUTLINE* GUIAPI LayoutNextLine(
|
||||
|
||||
next_line = check_next_line(layout, &state);
|
||||
|
||||
next_line:
|
||||
if (next_line) {
|
||||
if (layout->persist) {
|
||||
list_add_tail(&next_line->list, &layout->lines);
|
||||
@@ -1283,7 +1402,7 @@ next_line:
|
||||
release_line(prev_line);
|
||||
}
|
||||
|
||||
layout->nr_lines ++;
|
||||
layout->nr_lines++;
|
||||
layout->nr_left_ucs -= next_line->len;
|
||||
}
|
||||
|
||||
|
||||
@@ -105,6 +105,7 @@ struct _LAYOUTLINE {
|
||||
struct _LAYOUTINFO {
|
||||
const TEXTRUNSINFO* truninfo;
|
||||
const BreakOppo* bos;
|
||||
const int* tabs; // tabstop array
|
||||
|
||||
Uint32 rf; // rendering flags
|
||||
int ls; // letter spacing
|
||||
@@ -113,6 +114,7 @@ struct _LAYOUTINFO {
|
||||
|
||||
struct list_head lines; // the list head of lines
|
||||
|
||||
int nr_tabs; // number of tabstops
|
||||
int nr_left_ucs;// the number of chars not laied out
|
||||
int nr_lines; // the number of lines
|
||||
|
||||
@@ -146,8 +148,7 @@ LOGFONT* __mg_create_logfont_for_layout(const LAYOUTINFO* layout,
|
||||
void __mg_release_logfont_for_layout(const LAYOUTINFO* layout,
|
||||
const char* fontname, GlyphOrient ort);
|
||||
|
||||
GlyphRun *__mg_glyph_run_split (GlyphRun *orig,
|
||||
const Uchar32 *text, int split_index);
|
||||
GlyphRun *__mg_glyph_run_split (GlyphRun *orig, int split_index);
|
||||
void __mg_glyph_run_free(GlyphRun* run);
|
||||
|
||||
LayoutRun* __mg_layout_run_new_orphan(const LAYOUTINFO* layout,
|
||||
|
||||
@@ -77,7 +77,7 @@ static void reverse_shaped_glyphs(ShapedGlyph* glyphs, int len)
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL shape_text_run(SEInstance* inst,
|
||||
static BOOL shape_layout_run(SEInstance* inst,
|
||||
const TEXTRUNSINFO* info, const LayoutRun* run,
|
||||
GlyphString* gs)
|
||||
{
|
||||
@@ -254,11 +254,44 @@ out:
|
||||
return ok;
|
||||
}
|
||||
|
||||
BOOL GUIAPI InitBasicShapingEngine(TEXTRUNSINFO* info)
|
||||
struct _SEInstance {
|
||||
const char* name;
|
||||
int ref_count;
|
||||
};
|
||||
|
||||
static struct _SEInstance shaping_engine_basic = {
|
||||
"Basic Shapping Engine", 0
|
||||
};
|
||||
|
||||
static BOOL destroy_instance(SEInstance* instance)
|
||||
{
|
||||
info->sei.shape = shape_text_run;
|
||||
if (instance == &shaping_engine_basic) {
|
||||
shaping_engine_basic.ref_count--;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
_ERR_PRINTF("%s: you are destroying a non-basic shaping engine instance.\n",
|
||||
__FUNCTION__);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL GUIAPI InitBasicShapingEngine(TEXTRUNSINFO* info)
|
||||
{
|
||||
shaping_engine_basic.ref_count++;
|
||||
|
||||
info->sei.inst = &shaping_engine_basic;
|
||||
info->sei.shape = shape_layout_run;
|
||||
info->sei.free = destroy_instance;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#ifdef _MGDEVEL_MODE
|
||||
int GetBasicShapingEngineRefCount(void)
|
||||
{
|
||||
return shaping_engine_basic.ref_count;
|
||||
}
|
||||
#endif /* _MGDEVEL_MODE */
|
||||
|
||||
#endif /* _MGCHARSET_UNICODE */
|
||||
|
||||
|
||||
@@ -236,11 +236,7 @@ static BOOL state_process_run (TextRunState *state)
|
||||
for (p = state->run_start; p < state->run_end; p++) {
|
||||
Uchar32 uc = *p;
|
||||
|
||||
/* Only one character has the category LINE_SEPARATOR in Unicode 12.0;
|
||||
* update this if that changes. */
|
||||
#define LINE_SEPARATOR 0x2028
|
||||
|
||||
BOOL is_forced_break = (uc == '\t' || uc == LINE_SEPARATOR);
|
||||
BOOL is_forced_break = (uc == UCHAR_TAB || uc == UCHAR_LINE_SEPARATOR);
|
||||
BOOL no_shaping;
|
||||
|
||||
no_shaping = is_uchar_no_shaping(uc);
|
||||
@@ -516,32 +512,6 @@ TEXTRUNSINFO* GUIAPI CreateTextRunsInfo(Uchar32* ucs, int nr_ucs,
|
||||
INIT_LIST_HEAD(&runinfo->truns);
|
||||
runinfo->nr_runs = 0;
|
||||
|
||||
#if 0
|
||||
int i, j;
|
||||
BidiLevel max_level = 0;
|
||||
BidiLevel level_or, level_and;
|
||||
|
||||
// make the embedding levels of the bidi marks to be -1.
|
||||
level_or = 0, level_and = 1;
|
||||
j = 0;
|
||||
for (i = 0; i < nr_ucs; i++) {
|
||||
if (BIDI_IS_EXPLICIT_OR_BN (bidi_ts[i])) {
|
||||
els[i] = -1;
|
||||
}
|
||||
else {
|
||||
level_or |= els[j];
|
||||
level_and &= els[j];
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
// check for all even or odd
|
||||
/* If none of the levels had the LSB set, all chars were even. */
|
||||
runinfo->all_even = (level_or & 0x1) == 0;
|
||||
/* If all of the levels had the LSB set, all chars were odd. */
|
||||
runinfo->all_odd = (level_and & 0x1) == 1;
|
||||
#endif
|
||||
|
||||
if (!create_text_runs(runinfo, els)) {
|
||||
_ERR_PRINTF("%s: failed to call create_text_runs.\n",
|
||||
__FUNCTION__);
|
||||
@@ -572,6 +542,7 @@ BOOL GUIAPI SetFontInTextRuns(TEXTRUNSINFO* runinfo,
|
||||
if (list_empty(&runinfo->truns))
|
||||
return FALSE;
|
||||
|
||||
// TODO
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ typedef struct _GlyphString GlyphString;
|
||||
typedef struct _SEInstance SEInstance;
|
||||
typedef struct _TextAttrMap TextAttrMap;
|
||||
|
||||
typedef BOOL (*CB_SHAPE_TEXT_RUN)(SEInstance* instance,
|
||||
typedef BOOL (*CB_SHAPE_LAYOUT_RUN)(SEInstance* instance,
|
||||
const TEXTRUNSINFO* info, const LayoutRun* run,
|
||||
GlyphString* gs);
|
||||
|
||||
@@ -62,7 +62,7 @@ struct _ShapingEngineInfo {
|
||||
SEInstance* inst;
|
||||
|
||||
/* callback to shap a text run */
|
||||
CB_SHAPE_TEXT_RUN shape;
|
||||
CB_SHAPE_LAYOUT_RUN shape;
|
||||
|
||||
/* callback to destroy the shaping engine instance */
|
||||
CB_DESTROY_INSTANCE free;
|
||||
|
||||
Reference in New Issue
Block a user