mirror of
https://github.com/VincentWei/MiniGUI.git
synced 2026-09-24 09:14:09 +08:00
go on
This commit is contained in:
+81
-123
@@ -125,30 +125,27 @@ struct _LineIter
|
||||
struct _EllipsizeState
|
||||
{
|
||||
LAYOUTINFO *layout; /* Layout being ellipsized */
|
||||
//PangoAttrList *attrs; /* Attributes used for itemization/shaping */
|
||||
|
||||
RunInfo *run_info; /* Array of information about each run */
|
||||
int nr_runs;
|
||||
|
||||
int total_width; /* Original width of line in Pango units */
|
||||
int total_width; /* Original width of line in pixels */
|
||||
int gap_center; /* Goal for center of gap */
|
||||
|
||||
TextRun *ellipsis_trun; /* Text run created to hold ellipsis */
|
||||
LayoutRun *ellipsis_lrun; /* Layout run created to hold ellipsis */
|
||||
GlyphRun *ellipsis_grun; /* Glyph run created to hold ellipsis */
|
||||
int ellipsis_width; /* Width of ellipsis, in Pango units */
|
||||
int ellipsis_width; /* Width of ellipsis, in pixels */
|
||||
int ellipsis_is_cjk; /* Whether the first character in the ellipsized
|
||||
* is wide; this triggers us to try to use a
|
||||
* mid-line ellipsis instead of a baseline
|
||||
*/
|
||||
|
||||
//PangoAttrIterator *line_start_attr; /* Cached PangoAttrIterator for the start of the run */
|
||||
const char* fontname; /* fontname of gap TextRun */
|
||||
|
||||
LineIter gap_start_iter; /* Iteratator pointing to the first cluster in gap */
|
||||
int gap_start_x; /* x position of start of gap, in Pango units */
|
||||
//PangoAttrIterator *gap_start_attr; /* Attribute iterator pointing to a range containing the first character in gap */
|
||||
int gap_start_x; /* x position of start of gap, in pixels */
|
||||
|
||||
LineIter gap_end_iter; /* Iterator pointing to last cluster in gap */
|
||||
int gap_end_x; /* x position of end of gap, in Pango units */
|
||||
int gap_end_x; /* x position of end of gap, in pixels */
|
||||
};
|
||||
|
||||
/* Compute global information needed for the itemization process
|
||||
@@ -176,25 +173,20 @@ static void init_state (EllipsizeState *state, LAYOUTLINE *line)
|
||||
state->run_info[i].start_offset = start_offset;
|
||||
state->total_width += width;
|
||||
|
||||
start_offset += run->trun->len;
|
||||
start_offset += run->lrun->len;
|
||||
i++;
|
||||
}
|
||||
|
||||
state->ellipsis_trun = NULL;
|
||||
state->ellipsis_lrun = NULL;
|
||||
state->ellipsis_grun = NULL;
|
||||
state->ellipsis_is_cjk = FALSE;
|
||||
state->fontname = NULL;
|
||||
}
|
||||
|
||||
/* Cleanup memory allocation
|
||||
*/
|
||||
static void free_state (EllipsizeState *state)
|
||||
{
|
||||
#if 0
|
||||
if (state->line_start_attr)
|
||||
pango_attr_iterator_destroy (state->line_start_attr);
|
||||
if (state->gap_start_attr)
|
||||
pango_attr_iterator_destroy (state->gap_start_attr);
|
||||
#endif
|
||||
free (state->run_info);
|
||||
}
|
||||
|
||||
@@ -207,13 +199,13 @@ static int get_cluster_width (LineIter *iter)
|
||||
int width = 0;
|
||||
int i;
|
||||
|
||||
if (run_iter->start_glyph < run_iter->end_glyph) /* LTR */
|
||||
{
|
||||
if (run_iter->start_glyph < run_iter->end_glyph) {
|
||||
/* LTR */
|
||||
for (i = run_iter->start_glyph; i < run_iter->end_glyph; i++)
|
||||
width += glyphs->glyphs[i].width;
|
||||
}
|
||||
else /* RTL */
|
||||
{
|
||||
else {
|
||||
/* RTL */
|
||||
for (i = run_iter->start_glyph; i > run_iter->end_glyph; i--)
|
||||
width += glyphs->glyphs[i].width;
|
||||
}
|
||||
@@ -287,7 +279,7 @@ static BOOL ends_at_ellipsization_boundary (EllipsizeState *state, LineIter *ite
|
||||
{
|
||||
RunInfo *run_info = &state->run_info[iter->run_index];
|
||||
|
||||
if (iter->run_iter.end_char == run_info->run->trun->len && iter->run_index == state->nr_runs - 1)
|
||||
if (iter->run_iter.end_char == run_info->run->lrun->len && iter->run_index == state->nr_runs - 1)
|
||||
return TRUE;
|
||||
|
||||
return state->layout->bos[run_info->start_offset + iter->run_iter.end_char + 1] & BOV_GB_CURSOR_POS;
|
||||
@@ -296,13 +288,20 @@ static BOOL ends_at_ellipsization_boundary (EllipsizeState *state, LineIter *ite
|
||||
/* Shapes the ellipsis using the font and is_cjk information computed by
|
||||
* update_ellipsis_shape() from the first character in the gap.
|
||||
*/
|
||||
|
||||
/* U+22EF: MIDLINE HORIZONTAL ELLIPSIS, used for CJK: "\342\213\257" */
|
||||
static const Uchar32 _ellipsis_midline[1] = {0x22EF};
|
||||
/* U+2026: HORIZONTAL ELLIPSIS: "\342\200\246" */
|
||||
static const Uchar32 _ellipsis_baseline[1] = {0x2026};
|
||||
static const Uchar32 _ellipsis_fallback[3] = {'.', '.', '.'};
|
||||
|
||||
static void shape_ellipsis (EllipsizeState *state)
|
||||
{
|
||||
Glyph32 ellipsis_gv;
|
||||
TextRun *text_run;
|
||||
const TextRun* text_run;
|
||||
LayoutRun *layout_run;
|
||||
GlyphString *glyphs;
|
||||
Uchar32 ellipsis_ucs[3];
|
||||
int nr_ucs = 0;
|
||||
const Uchar32* ellipsis_ucs;
|
||||
int i;
|
||||
|
||||
/* Create/reset state->ellipsis_grun
|
||||
@@ -310,55 +309,44 @@ static void shape_ellipsis (EllipsizeState *state)
|
||||
if (!state->ellipsis_grun) {
|
||||
state->ellipsis_grun = malloc (sizeof(GlyphRun));
|
||||
state->ellipsis_grun->gs = __mg_glyph_string_new ();
|
||||
state->ellipsis_grun->trun = NULL;
|
||||
state->ellipsis_grun->lrun = NULL;
|
||||
}
|
||||
|
||||
if (state->ellipsis_trun) {
|
||||
__mg_text_run_free (state->ellipsis_trun);
|
||||
state->ellipsis_trun = NULL;
|
||||
if (state->ellipsis_lrun) {
|
||||
__mg_layout_run_free (state->ellipsis_lrun);
|
||||
state->ellipsis_lrun = NULL;
|
||||
}
|
||||
|
||||
/* First try using a specific ellipsis character in the best matching font
|
||||
*/
|
||||
if (state->ellipsis_is_cjk) {
|
||||
/* U+22EF: MIDLINE HORIZONTAL ELLIPSIS, used for CJK */
|
||||
ellipsis_ucs[0] = 0x22EF; // "\342\213\257";
|
||||
nr_ucs = 1;
|
||||
ellipsis_ucs = _ellipsis_midline;
|
||||
}
|
||||
else {
|
||||
/* U+2026: HORIZONTAL ELLIPSIS */
|
||||
ellipsis_ucs[0] = 0x2026; // "\342\200\246";
|
||||
nr_ucs = 1;
|
||||
ellipsis_ucs = _ellipsis_baseline;
|
||||
}
|
||||
|
||||
text_run = __mg_textruns_get_by_offset(state->layout->truninfo,
|
||||
state->gap_start_iter.run_iter.start_index, NULL);
|
||||
|
||||
text_run = __mg_text_run_new_orphan (state->layout->truninfo,
|
||||
ellipsis_ucs, nr_ucs);
|
||||
// TODO: other attributes of the text run.
|
||||
|
||||
text_run->lf = __mg_create_logfont_for_run(state->layout->truninfo, text_run);
|
||||
ellipsis_gv = GetGlyphValue(text_run->lf, ellipsis_ucs[0]);
|
||||
layout_run = __mg_layout_run_new_orphan (state->layout, text_run,
|
||||
ellipsis_ucs, 1);
|
||||
|
||||
ellipsis_gv = GetGlyphValue(layout_run->lf, ellipsis_ucs[0]);
|
||||
/* If the devfont of the glyph value of the specific ellipsis character
|
||||
* is SBC devfont, we use "...".
|
||||
*/
|
||||
if (DFI_IN_GLYPH(ellipsis_gv) == 0) {
|
||||
__mg_text_run_free (text_run);
|
||||
ellipsis_ucs[0] = '.';
|
||||
ellipsis_ucs[1] = '.';
|
||||
ellipsis_ucs[2] = '.';
|
||||
nr_ucs = 3;
|
||||
text_run = __mg_text_run_new_orphan (state->layout->truninfo,
|
||||
ellipsis_ucs, nr_ucs);
|
||||
__mg_layout_run_free (layout_run);
|
||||
layout_run = __mg_layout_run_new_orphan (state->layout,
|
||||
text_run, ellipsis_ucs, 3);
|
||||
}
|
||||
|
||||
state->ellipsis_trun = text_run;
|
||||
state->ellipsis_lrun = layout_run;
|
||||
|
||||
/* Now shape
|
||||
*/
|
||||
/* Now shape */
|
||||
glyphs = state->ellipsis_grun->gs;
|
||||
|
||||
__mg_shape_text_run(state->layout->truninfo, text_run, 0, nr_ucs, glyphs);
|
||||
__mg_shape_layout_run(state->layout->truninfo, layout_run, glyphs);
|
||||
|
||||
state->ellipsis_width = 0;
|
||||
for (i = 0; i < glyphs->nr_glyphs; i++)
|
||||
@@ -399,42 +387,15 @@ static void update_ellipsis_shape (EllipsizeState *state)
|
||||
BOOL recompute = FALSE;
|
||||
Uchar32 start_wc;
|
||||
BOOL is_cjk;
|
||||
const TextRun* text_run;
|
||||
|
||||
#if 0
|
||||
/* Unfortunately, we can only advance PangoAttrIterator forward; so each
|
||||
* time we back up we need to go forward to find the new position. To make
|
||||
* this not utterly slow, we cache an iterator at the start of the line
|
||||
*/
|
||||
if (!state->line_start_attr) {
|
||||
state->line_start_attr = pango_attr_list_get_iterator (state->attrs);
|
||||
advance_iterator_to (state->line_start_attr, state->run_info[0].run->trun->offset);
|
||||
}
|
||||
|
||||
if (state->gap_start_attr) {
|
||||
/* See if the current attribute range contains the new start position
|
||||
*/
|
||||
int start, end;
|
||||
|
||||
pango_attr_iterator_range (state->gap_start_attr, &start, &end);
|
||||
|
||||
if (state->gap_start_iter.run_iter.start_index < start)
|
||||
{
|
||||
pango_attr_iterator_destroy (state->gap_start_attr);
|
||||
state->gap_start_attr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check whether we need to recompute the ellipsis because of new font attributes
|
||||
*/
|
||||
if (!state->gap_start_attr)
|
||||
{
|
||||
state->gap_start_attr = pango_attr_iterator_copy (state->line_start_attr);
|
||||
advance_iterator_to (state->gap_start_attr,
|
||||
state->run_info[state->gap_start_iter.run_index].run->trun->offset);
|
||||
text_run = __mg_textruns_get_by_offset(state->layout->truninfo,
|
||||
state->gap_start_iter.run_iter.start_index, NULL);
|
||||
|
||||
if (state->fontname != text_run->fontname) {
|
||||
state->fontname = text_run->fontname;
|
||||
recompute = TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Check whether we need to recompute the ellipsis because we switch
|
||||
* from CJK to not or vice-versa
|
||||
@@ -451,7 +412,8 @@ static void update_ellipsis_shape (EllipsizeState *state)
|
||||
shape_ellipsis (state);
|
||||
}
|
||||
|
||||
/* Computes the position of the gap center and finds the smallest span containing it
|
||||
/* Computes the position of the gap center and finds the smallest span
|
||||
* containing it
|
||||
*/
|
||||
static void find_initial_span (EllipsizeState *state)
|
||||
{
|
||||
@@ -571,7 +533,8 @@ static BOOL remove_one_span (EllipsizeState *state)
|
||||
while (!ends_at_ellipsization_boundary (state, &new_gap_end_iter) ||
|
||||
width == 0);
|
||||
|
||||
if (state->gap_end_x == new_gap_end_x && state->gap_start_x == new_gap_start_x)
|
||||
if (state->gap_end_x == new_gap_end_x &&
|
||||
state->gap_start_x == new_gap_start_x)
|
||||
return FALSE;
|
||||
|
||||
/* In the case where we could remove a span from either end of the
|
||||
@@ -580,8 +543,8 @@ static BOOL remove_one_span (EllipsizeState *state)
|
||||
*/
|
||||
if (state->gap_end_x == new_gap_end_x ||
|
||||
(state->gap_start_x != new_gap_start_x &&
|
||||
state->gap_center - new_gap_start_x < new_gap_end_x - state->gap_center))
|
||||
{
|
||||
state->gap_center - new_gap_start_x <
|
||||
new_gap_end_x - state->gap_center)) {
|
||||
state->gap_start_iter = new_gap_start_iter;
|
||||
state->gap_start_x = new_gap_start_x;
|
||||
|
||||
@@ -595,13 +558,13 @@ static BOOL remove_one_span (EllipsizeState *state)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Fixes up the properties of the ellipsis run once we've determined the final extents
|
||||
* of the gap
|
||||
/* Fixes up the properties of the ellipsis run once we've determined the
|
||||
* final extents of the gap
|
||||
*/
|
||||
static void fixup_ellipsis_grun (EllipsizeState *state)
|
||||
{
|
||||
GlyphString *glyphs = state->ellipsis_grun->gs;
|
||||
TextRun *text_run = state->ellipsis_trun;
|
||||
LayoutRun *layout_run = state->ellipsis_lrun;
|
||||
int level;
|
||||
int i;
|
||||
|
||||
@@ -613,28 +576,26 @@ static void fixup_ellipsis_grun (EllipsizeState *state)
|
||||
|
||||
glyphs->glyphs[0].is_cluster_start = TRUE;
|
||||
|
||||
/* Fix up the text_run to point to the entire elided text */
|
||||
text_run->si = state->gap_start_iter.run_iter.start_index;
|
||||
text_run->len = state->gap_end_iter.run_iter.end_index - text_run->si;
|
||||
/* Fix up the layout_run to point to the entire elided text */
|
||||
layout_run->si = state->gap_start_iter.run_iter.start_index;
|
||||
layout_run->len = state->gap_end_iter.run_iter.end_index - layout_run->si;
|
||||
|
||||
/* The level for the text_run is the minimum level of the elided text */
|
||||
/* The level for the layout_run is the minimum level of the elided text */
|
||||
level = INT_MAX;
|
||||
for (i = state->gap_start_iter.run_index; i <= state->gap_end_iter.run_index; i++)
|
||||
level = MIN (level, state->run_info[i].run->trun->el);
|
||||
level = MIN (level, state->run_info[i].run->lrun->el);
|
||||
|
||||
text_run->el = level;
|
||||
layout_run->el = level;
|
||||
|
||||
text_run->flags |= TextRun_FLAG_IS_ELLIPSIS;
|
||||
layout_run->flags |= LAYOUTRUN_FLAG_ORPHAN;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Computes the new list of runs for the line
|
||||
*/
|
||||
static GSList * get_run_list (EllipsizeState *state)
|
||||
static void get_run_list (EllipsizeState *state, LAYOUTLINE* line)
|
||||
{
|
||||
GlyphRun *partial_start_run = NULL;
|
||||
GlyphRun *partial_end_run = NULL;
|
||||
GSList *result = NULL;
|
||||
RunInfo *run_info;
|
||||
GlyphRunIter *run_iter;
|
||||
int i;
|
||||
@@ -645,45 +606,43 @@ static GSList * get_run_list (EllipsizeState *state)
|
||||
*/
|
||||
run_info = &state->run_info[state->gap_end_iter.run_index];
|
||||
run_iter = &state->gap_end_iter.run_iter;
|
||||
if (run_iter->end_char != run_info->run->trun->len)
|
||||
{
|
||||
if (run_iter->end_char != run_info->run->lrun->len) {
|
||||
partial_end_run = run_info->run;
|
||||
run_info->run = pango_glyph_run_split (run_info->run, state->layout->truninfo->ucs,
|
||||
run_iter->end_index - run_info->run->trun->offset);
|
||||
run_info->run = __mg_glyph_run_split (run_info->run,
|
||||
state->layout->truninfo->ucs,
|
||||
run_iter->end_index - run_info->run->lrun->si);
|
||||
}
|
||||
|
||||
run_info = &state->run_info[state->gap_start_iter.run_index];
|
||||
run_iter = &state->gap_start_iter.run_iter;
|
||||
if (run_iter->start_char != 0)
|
||||
{
|
||||
partial_start_run = pango_glyph_run_split (run_info->run, state->layout->truninfo->ucs,
|
||||
run_iter->start_index - run_info->run->trun->offset);
|
||||
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);
|
||||
}
|
||||
|
||||
/* Now assemble the new list of runs
|
||||
*/
|
||||
for (i = 0; i < state->gap_start_iter.run_index; i++)
|
||||
result = g_slist_prepend (result, state->run_info[i].run);
|
||||
list_add_tail(&state->run_info[i].run->list, &line->gruns);
|
||||
|
||||
if (partial_start_run)
|
||||
result = g_slist_prepend (result, partial_start_run);
|
||||
list_add_tail(&partial_start_run->list, &line->gruns);
|
||||
|
||||
result = g_slist_prepend (result, state->ellipsis_grun);
|
||||
list_add_tail(&state->ellipsis_grun->list, &line->gruns);
|
||||
|
||||
if (partial_end_run)
|
||||
result = g_slist_prepend (result, partial_end_run);
|
||||
list_add_tail(&partial_end_run->list, &line->gruns);
|
||||
|
||||
for (i = state->gap_end_iter.run_index + 1; i < state->nr_runs; i++)
|
||||
result = g_slist_prepend (result, state->run_info[i].run);
|
||||
list_add_tail(&state->run_info[i].run->list, &line->gruns);
|
||||
|
||||
/* And free the ones we didn't use
|
||||
*/
|
||||
for (i = state->gap_start_iter.run_index; i <= state->gap_end_iter.run_index; i++)
|
||||
pango_glyph_run_free (state->run_info[i].run);
|
||||
|
||||
return g_slist_reverse (result);
|
||||
for (i = state->gap_start_iter.run_index;
|
||||
i <= state->gap_end_iter.run_index; i++)
|
||||
__mg_glyph_run_free(state->run_info[i].run);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Computes the width of the line as currently ellipsized
|
||||
*/
|
||||
@@ -696,7 +655,6 @@ static int current_width (EllipsizeState *state)
|
||||
/**
|
||||
* _pango_layout_line_ellipsize:
|
||||
* @line: a #LAYOUTLINE
|
||||
* @attrs: Attributes being used for itemization/shaping
|
||||
*
|
||||
* Given a #LAYOUTLINE with the runs still in logical order, ellipsize
|
||||
* it according the layout's policy to fit within the set width of the layout.
|
||||
@@ -726,8 +684,8 @@ BOOL __mg_layout_line_ellipsize (LAYOUTLINE *line, int goal_width)
|
||||
|
||||
fixup_ellipsis_grun (&state);
|
||||
|
||||
//g_slist_free (line->runs);
|
||||
//line->runs = get_run_list (&state);
|
||||
__mg_layout_line_free_runs(line);
|
||||
get_run_list(&state, line);
|
||||
is_ellipsized = TRUE;
|
||||
|
||||
out:
|
||||
|
||||
+229
-14
@@ -52,6 +52,201 @@
|
||||
#include "devfont.h"
|
||||
#include "unicode-ops.h"
|
||||
#include "layoutinfo.h"
|
||||
#include "fontname.h"
|
||||
|
||||
static BOOL fontname_get_from_orient(char* fontname, GlyphOrient ort)
|
||||
{
|
||||
int orient_pos;
|
||||
|
||||
orient_pos = fontGetOrientPosFromName(fontname);
|
||||
if (orient_pos < 0)
|
||||
return FALSE;
|
||||
|
||||
switch (ort) {
|
||||
case GLYPH_ORIENT_UPRIGHT:
|
||||
fontname[orient_pos] = FONT_ORIENT_UPRIGHT;
|
||||
break;
|
||||
case GLYPH_ORIENT_SIDEWAYS:
|
||||
fontname[orient_pos] = FONT_ORIENT_SIDEWAYS;
|
||||
break;
|
||||
case GLYPH_ORIENT_UPSIDE_DOWN:
|
||||
fontname[orient_pos] = FONT_ORIENT_UPSIDE_DOWN;
|
||||
break;
|
||||
case GLYPH_ORIENT_SIDEWAYS_LEFT:
|
||||
fontname[orient_pos] = FONT_ORIENT_SIDEWAYS_LEFT;
|
||||
break;
|
||||
default:
|
||||
_WRN_PRINTF("bad orientation param: %d", ort);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Use MiniGUI resource manager to avoid duplicated logfonts */
|
||||
LOGFONT* __mg_create_logfont_for_layout(const LAYOUTINFO* layout,
|
||||
const char* fontname, GlyphOrient ort)
|
||||
{
|
||||
char my_fontname[LEN_LOGFONT_NAME_FULL + 1];
|
||||
LOGFONT* lf;
|
||||
|
||||
if (fontname == NULL)
|
||||
fontname = layout->truninfo->fontname;
|
||||
|
||||
memset (my_fontname, 0, LEN_LOGFONT_NAME_FULL + 1);
|
||||
strncpy (my_fontname, fontname, LEN_LOGFONT_NAME_FULL);
|
||||
if (!fontname_get_from_orient(my_fontname, ort)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lf = (LOGFONT*)LoadResource(my_fontname, RES_TYPE_FONT, 0);
|
||||
if (lf == NULL) {
|
||||
_ERR_PRINTF("%s: failed to create LOGFONT for layout: %p\n",
|
||||
__FUNCTION__, layout);
|
||||
}
|
||||
|
||||
return lf;
|
||||
}
|
||||
|
||||
void __mg_release_logfont_for_layout(const LAYOUTINFO* layout,
|
||||
const char* fontname, GlyphOrient ort)
|
||||
{
|
||||
char my_fontname[LEN_LOGFONT_NAME_FULL + 1];
|
||||
if (fontname == NULL)
|
||||
fontname = layout->truninfo->fontname;
|
||||
|
||||
memset (my_fontname, 0, LEN_LOGFONT_NAME_FULL + 1);
|
||||
strncpy (my_fontname, fontname, LEN_LOGFONT_NAME_FULL);
|
||||
if (!fontname_get_from_orient(my_fontname, ort)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ReleaseRes(Str2Key(my_fontname));
|
||||
}
|
||||
|
||||
LayoutRun* __mg_layout_run_new_orphan(const LAYOUTINFO* layout,
|
||||
const TextRun* trun, const Uchar32* ucs, int nr_ucs)
|
||||
{
|
||||
LOGFONT* lf;
|
||||
LayoutRun* lrun;
|
||||
|
||||
lf = __mg_create_logfont_for_layout(layout, trun->fontname, trun->ort);
|
||||
if (lf == NULL)
|
||||
return NULL;
|
||||
|
||||
lrun = malloc(sizeof(LayoutRun));
|
||||
lrun->lf = lf;
|
||||
lrun->ucs = ucs;
|
||||
lrun->si = 0;
|
||||
lrun->len = nr_ucs;
|
||||
lrun->si = trun->si;
|
||||
lrun->len = trun->len;
|
||||
lrun->lc = trun->lc;
|
||||
lrun->st = trun->st;
|
||||
lrun->el = trun->el;
|
||||
lrun->dir = trun->dir;
|
||||
lrun->ort = trun->ort;
|
||||
lrun->flags |= LAYOUTRUN_FLAG_ORPHAN;
|
||||
|
||||
return lrun;
|
||||
}
|
||||
|
||||
LayoutRun* __mg_layout_run_new_from(const LAYOUTINFO* layout,
|
||||
const TextRun* trun)
|
||||
{
|
||||
LOGFONT* lf;
|
||||
LayoutRun* lrun;
|
||||
|
||||
lf = __mg_create_logfont_for_layout(layout, trun->fontname, trun->ort);
|
||||
if (lf == NULL)
|
||||
return NULL;
|
||||
|
||||
lrun = malloc(sizeof(LayoutRun));
|
||||
lrun->lf = lf;
|
||||
lrun->ucs = layout->truninfo->ucs;
|
||||
lrun->si = trun->si;
|
||||
lrun->len = trun->len;
|
||||
lrun->lc = trun->lc;
|
||||
lrun->st = trun->st;
|
||||
lrun->el = trun->el;
|
||||
lrun->dir = trun->dir;
|
||||
lrun->ort = trun->ort;
|
||||
lrun->flags = trun->flags;
|
||||
|
||||
return lrun;
|
||||
}
|
||||
|
||||
LayoutRun* __mg_layout_run_new_from_offset(const LAYOUTINFO* layout,
|
||||
const TextRun* trun, int offset)
|
||||
{
|
||||
LOGFONT* lf;
|
||||
LayoutRun* lrun;
|
||||
|
||||
if (offset >= trun->len)
|
||||
return NULL;
|
||||
|
||||
lf = __mg_create_logfont_for_layout(layout, trun->fontname, trun->ort);
|
||||
if (lf == NULL)
|
||||
return NULL;
|
||||
|
||||
lrun = malloc(sizeof(LayoutRun));
|
||||
|
||||
lrun->lf = lf;
|
||||
lrun->ucs = layout->truninfo->ucs;
|
||||
lrun->si = trun->si + offset;
|
||||
lrun->len = trun->len - offset;
|
||||
lrun->lc = trun->lc;
|
||||
lrun->st = trun->st;
|
||||
lrun->el = trun->el;
|
||||
lrun->dir = trun->dir;
|
||||
lrun->ort = trun->ort;
|
||||
lrun->flags = trun->flags;
|
||||
|
||||
return lrun;
|
||||
}
|
||||
|
||||
void __mg_layout_run_free(LayoutRun* lrun)
|
||||
{
|
||||
if (lrun->lf) {
|
||||
FONT_RES* font_res = (FONT_RES*)lrun->lf;
|
||||
ReleaseRes(font_res->key);
|
||||
}
|
||||
|
||||
free(lrun);
|
||||
}
|
||||
|
||||
LayoutRun* __mg_layout_run_copy(const LayoutRun* lrun)
|
||||
{
|
||||
LayoutRun *result;
|
||||
|
||||
if (lrun == NULL)
|
||||
return NULL;
|
||||
|
||||
result = malloc(sizeof(LayoutRun));
|
||||
memcpy(result, lrun, sizeof(LayoutRun));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
LayoutRun* __mg_layout_run_split(LayoutRun *orig, int split_index)
|
||||
{
|
||||
LayoutRun *new_run;
|
||||
|
||||
if (orig == NULL)
|
||||
return NULL;
|
||||
if (split_index <= 0)
|
||||
return NULL;
|
||||
if (split_index >= orig->len)
|
||||
return NULL;
|
||||
|
||||
new_run = __mg_layout_run_copy(orig);
|
||||
new_run->len = split_index;
|
||||
|
||||
orig->si += split_index;
|
||||
orig->len -= split_index;
|
||||
|
||||
return new_run;
|
||||
}
|
||||
|
||||
GlyphString* __mg_glyph_string_new (void)
|
||||
{
|
||||
@@ -117,11 +312,33 @@ int __mg_glyph_string_get_width(const GlyphString *glyphs)
|
||||
return width;
|
||||
}
|
||||
|
||||
#define LTR(glyph_run) (((glyph_run)->trun->el & 1) == 0)
|
||||
void __mg_layout_line_free_runs(LAYOUTLINE* line)
|
||||
{
|
||||
while (!list_empty(&line->gruns)) {
|
||||
GlyphRun* run = (GlyphRun*)line->gruns.prev;
|
||||
list_del(line->gruns.prev);
|
||||
__mg_glyph_run_free(run);
|
||||
}
|
||||
}
|
||||
|
||||
void __mg_glyph_run_free(GlyphRun* run)
|
||||
{
|
||||
if (run->lrun) {
|
||||
__mg_layout_run_free(run->lrun);
|
||||
}
|
||||
|
||||
if (run->gs) {
|
||||
__mg_glyph_string_free(run->gs);
|
||||
}
|
||||
|
||||
free(run);
|
||||
}
|
||||
|
||||
#define LTR(glyph_run) (((glyph_run)->lrun->el & 1) == 0)
|
||||
|
||||
/**
|
||||
* __mg_glyph_run_split:
|
||||
* @orig: a #TextRun
|
||||
* @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
|
||||
*
|
||||
@@ -139,11 +356,9 @@ int __mg_glyph_string_get_width(const GlyphString *glyphs)
|
||||
* Return value: the newly allocated item representing text before
|
||||
* @split_index, which should be freed
|
||||
* with pango_glyph_run_free().
|
||||
*
|
||||
* Since: 1.2
|
||||
**/
|
||||
GlyphRun *__mg_glyph_run_split (GlyphRun *orig,
|
||||
const char *text, int split_index)
|
||||
const Uchar32 *text, int split_index)
|
||||
{
|
||||
GlyphRun *new_grun;
|
||||
int i;
|
||||
@@ -152,11 +367,11 @@ GlyphRun *__mg_glyph_run_split (GlyphRun *orig,
|
||||
|
||||
if (orig == NULL)
|
||||
return NULL;
|
||||
if (orig->trun->len <= 0)
|
||||
if (orig->lrun->len <= 0)
|
||||
return NULL;
|
||||
if (split_index <= 0)
|
||||
return NULL;
|
||||
if (split_index >= orig->trun->len)
|
||||
if (split_index >= orig->lrun->len)
|
||||
return NULL;
|
||||
|
||||
if (LTR (orig)) {
|
||||
@@ -189,7 +404,7 @@ GlyphRun *__mg_glyph_run_split (GlyphRun *orig,
|
||||
num_remaining = orig->gs->nr_glyphs - nr_glyphs;
|
||||
|
||||
new_grun = malloc (sizeof(GlyphRun));
|
||||
new_grun->trun = __mg_text_run_split (orig->trun, split_index);
|
||||
new_grun->lrun = __mg_layout_run_split(orig->lrun, split_index);
|
||||
|
||||
new_grun->gs = __mg_glyph_string_new ();
|
||||
__mg_glyph_string_set_size (new_grun->gs, nr_glyphs);
|
||||
@@ -233,7 +448,7 @@ BOOL __mg_glyph_run_iter_next_cluster (GlyphRunIter *iter)
|
||||
int glyph_index = iter->end_glyph;
|
||||
GlyphString *glyphs = iter->glyph_run->gs;
|
||||
int cluster;
|
||||
const TextRun *item = iter->glyph_run->trun;
|
||||
const LayoutRun *item = iter->glyph_run->lrun;
|
||||
|
||||
if (LTR (iter->glyph_run)) {
|
||||
if (glyph_index == glyphs->nr_glyphs)
|
||||
@@ -297,7 +512,7 @@ BOOL __mg_glyph_run_iter_prev_cluster (GlyphRunIter *iter)
|
||||
int glyph_index = iter->start_glyph;
|
||||
GlyphString *glyphs = iter->glyph_run->gs;
|
||||
int cluster;
|
||||
const TextRun *item = iter->glyph_run->trun;
|
||||
const LayoutRun *item = iter->glyph_run->lrun;
|
||||
|
||||
if (LTR (iter->glyph_run)) {
|
||||
if (glyph_index == 0)
|
||||
@@ -372,7 +587,7 @@ BOOL __mg_glyph_run_iter_init_start (GlyphRunIter *iter,
|
||||
else
|
||||
iter->end_glyph = glyph_run->gs->nr_glyphs - 1;
|
||||
|
||||
iter->end_index = glyph_run->trun->si;
|
||||
iter->end_index = glyph_run->lrun->si;
|
||||
iter->end_char = 0;
|
||||
|
||||
iter->start_glyph = iter->end_glyph;
|
||||
@@ -394,8 +609,8 @@ BOOL __mg_glyph_run_iter_init_end (GlyphRunIter *iter,
|
||||
else
|
||||
iter->start_glyph = -1;
|
||||
|
||||
iter->start_index = glyph_run->trun->si + glyph_run->trun->len;
|
||||
iter->start_char = glyph_run->trun->len;
|
||||
iter->start_index = glyph_run->lrun->si + glyph_run->lrun->len;
|
||||
iter->start_char = glyph_run->lrun->len;
|
||||
|
||||
iter->end_glyph = iter->start_glyph;
|
||||
iter->end_index = iter->start_index;
|
||||
@@ -412,7 +627,7 @@ void __mg_glyph_run_get_logical_widths (const GlyphRun *glyph_run,
|
||||
BOOL has_cluster;
|
||||
int dir;
|
||||
|
||||
dir = glyph_run->trun->el % 2 == 0 ? +1 : -1;
|
||||
dir = glyph_run->lrun->el % 2 == 0 ? +1 : -1;
|
||||
for (has_cluster = __mg_glyph_run_iter_init_start (&iter, glyph_run, text);
|
||||
has_cluster;
|
||||
has_cluster = __mg_glyph_run_iter_next_cluster (&iter))
|
||||
|
||||
+35
-61
@@ -84,43 +84,12 @@ LAYOUTINFO* GUIAPI CreateLayoutInfo(
|
||||
return layout;
|
||||
}
|
||||
|
||||
static void release_glyph_string(GlyphString* gs)
|
||||
{
|
||||
if (gs->glyphs)
|
||||
free (gs->glyphs);
|
||||
if (gs->log_clusters);
|
||||
free (gs->log_clusters);
|
||||
|
||||
free(gs);
|
||||
}
|
||||
|
||||
static void release_run(GlyphRun* run)
|
||||
{
|
||||
if (run->trun) {
|
||||
__mg_text_run_free(run->trun);
|
||||
}
|
||||
|
||||
if (run->gs) {
|
||||
release_glyph_string(run->gs);
|
||||
}
|
||||
free(run);
|
||||
}
|
||||
|
||||
void __mg_layout_line_free_runs(LAYOUTLINE* line)
|
||||
{
|
||||
while (!list_empty(&line->gruns)) {
|
||||
GlyphRun* run = (GlyphRun*)line->gruns.prev;
|
||||
list_del(line->gruns.prev);
|
||||
release_run(run);
|
||||
}
|
||||
}
|
||||
|
||||
static void release_line(LAYOUTLINE* line)
|
||||
{
|
||||
while (!list_empty(&line->gruns)) {
|
||||
GlyphRun* run = (GlyphRun*)line->gruns.prev;
|
||||
list_del(line->gruns.prev);
|
||||
release_run(run);
|
||||
__mg_glyph_run_free(run);
|
||||
}
|
||||
|
||||
if (line->log_widths) {
|
||||
@@ -180,7 +149,9 @@ struct _LayoutState {
|
||||
// Start index of line in layout->text
|
||||
int line_start_index;
|
||||
// Current text run
|
||||
TextRun* item;
|
||||
const TextRun* trun;
|
||||
// Current layout run
|
||||
LayoutRun* item;
|
||||
// Start index of line in current item */
|
||||
int start_index_in_item;
|
||||
// the number of not fit uchars in current text run
|
||||
@@ -230,7 +201,7 @@ static void shape_shape(const Uchar32* ucs, int nr_ucs,
|
||||
|
||||
static void shape_full(const Uchar32* item_ucs, int nr_item_ucs,
|
||||
const Uchar32* para_ucs, int nr_para_ucs,
|
||||
const TEXTRUNSINFO* truninfo, TextRun* textrun,
|
||||
const TEXTRUNSINFO* truninfo, LayoutRun* textrun,
|
||||
GlyphString* glyphs)
|
||||
{
|
||||
}
|
||||
@@ -248,7 +219,7 @@ static void distribute_letter_spacing (int letter_spacing,
|
||||
}
|
||||
|
||||
static GlyphString* shape_run(LAYOUTLINE *line, LayoutState *state,
|
||||
TextRun *item)
|
||||
LayoutRun *item)
|
||||
{
|
||||
LAYOUTINFO *layout = line->layout;
|
||||
GlyphString *glyphs = __mg_glyph_string_new ();
|
||||
@@ -269,7 +240,7 @@ static GlyphString* shape_run(LAYOUTLINE *line, LayoutState *state,
|
||||
GlyphRun glyph_run;
|
||||
int space_left, space_right;
|
||||
|
||||
glyph_run.trun = item;
|
||||
glyph_run.lrun = item;
|
||||
glyph_run.gs = glyphs;
|
||||
|
||||
__mg_glyph_run_letter_space (&glyph_run,
|
||||
@@ -294,32 +265,32 @@ static void free_run (GlyphRun *run)
|
||||
free(run);
|
||||
}
|
||||
|
||||
static TextRun *uninsert_run (LAYOUTLINE *line)
|
||||
static LayoutRun *uninsert_run (LAYOUTLINE *line)
|
||||
{
|
||||
GlyphRun *run;
|
||||
TextRun *item;
|
||||
LayoutRun *item;
|
||||
|
||||
run = (GlyphRun*)&line->gruns.next;
|
||||
item = run->trun;
|
||||
item = run->lrun;
|
||||
|
||||
list_del(line->gruns.next);
|
||||
line->len -= run->trun->len;
|
||||
line->len -= run->lrun->len;
|
||||
|
||||
free_run(run);
|
||||
return item;
|
||||
}
|
||||
|
||||
static GlyphRun* insert_run(LAYOUTLINE *line, LayoutState *state,
|
||||
TextRun *text_run, BOOL last_run)
|
||||
LayoutRun *layout_run, BOOL last_run)
|
||||
{
|
||||
GlyphRun *glyph_run = malloc(sizeof(GlyphRun));
|
||||
|
||||
glyph_run->trun = text_run;
|
||||
glyph_run->lrun = layout_run;
|
||||
|
||||
if (last_run && state->log_widths_offset == 0)
|
||||
glyph_run->gs = state->glyphs;
|
||||
else
|
||||
glyph_run->gs = shape_run(line, state, text_run);
|
||||
glyph_run->gs = shape_run(line, state, layout_run);
|
||||
|
||||
if (last_run) {
|
||||
if (state->log_widths_offset > 0)
|
||||
@@ -330,7 +301,7 @@ static GlyphRun* insert_run(LAYOUTLINE *line, LayoutState *state,
|
||||
}
|
||||
|
||||
list_add_tail(&glyph_run->list, &line->gruns);
|
||||
line->len += text_run->len;
|
||||
line->len += layout_run->len;
|
||||
|
||||
return glyph_run;
|
||||
}
|
||||
@@ -394,7 +365,7 @@ BreakResult process_text_run(LAYOUTINFO *layout,
|
||||
LAYOUTLINE *line, LayoutState *state,
|
||||
BOOL force_fit, BOOL no_break_at_end)
|
||||
{
|
||||
TextRun *item = state->item;
|
||||
LayoutRun *item = state->item;
|
||||
BOOL shape_set = FALSE;
|
||||
int width;
|
||||
int i;
|
||||
@@ -456,7 +427,7 @@ BreakResult process_text_run(LAYOUTINFO *layout,
|
||||
if (processing_new_item) {
|
||||
|
||||
GlyphRun glyph_run;
|
||||
glyph_run.trun = item;
|
||||
glyph_run.lrun = item;
|
||||
glyph_run.gs = state->glyphs;
|
||||
|
||||
state->log_widths = malloc (sizeof (int) * item->len);
|
||||
@@ -632,8 +603,8 @@ static void layout_line_reorder(LAYOUTLINE *line)
|
||||
list_for_each(i, &line->gruns) {
|
||||
GlyphRun *grun = (GlyphRun*)i;
|
||||
|
||||
level_or |= grun->trun->el;
|
||||
level_and &= grun->trun->el;
|
||||
level_or |= grun->lrun->el;
|
||||
level_and &= grun->lrun->el;
|
||||
length++;
|
||||
}
|
||||
|
||||
@@ -654,7 +625,7 @@ static void zero_line_final_space (LAYOUTLINE *line,
|
||||
LayoutState *state, GlyphRun *run)
|
||||
{
|
||||
LAYOUTINFO *layout = line->layout;
|
||||
TextRun *item = run->trun;
|
||||
LayoutRun *item = run->lrun;
|
||||
GlyphString *glyphs = run->gs;
|
||||
int glyph = item->el % 2 ? 0 : glyphs->nr_glyphs - 1;
|
||||
|
||||
@@ -711,7 +682,7 @@ static void pad_glyphstring_left (GlyphString *glyphs,
|
||||
|
||||
static inline BOOL is_tab_run(LAYOUTINFO *layout, GlyphRun *grun)
|
||||
{
|
||||
return (layout->truninfo->ucs[grun->trun->si] == '\t');
|
||||
return (layout->truninfo->ucs[grun->lrun->si] == '\t');
|
||||
}
|
||||
|
||||
/* When doing shaping, we add the letter spacing value for a
|
||||
@@ -851,18 +822,18 @@ static void justify_clusters (LAYOUTLINE *line, LayoutState *state)
|
||||
int dir;
|
||||
int offset;
|
||||
|
||||
dir = run->trun->el % 2 == 0 ? +1 : -1;
|
||||
dir = run->lrun->el % 2 == 0 ? +1 : -1;
|
||||
|
||||
/* We need character offset of the start of the run.
|
||||
* We don't have this.
|
||||
* Compute by counting from the beginning of the line.
|
||||
* The naming is confusing. Note that:
|
||||
*
|
||||
* run->trun->si is the index of start of run.
|
||||
* run->lrun->si is the index of start of run.
|
||||
* state->line_start_index is the index of start of line.
|
||||
*/
|
||||
assert(run->trun->si >= state->line_start_index);
|
||||
offset = state->line_start_index + run->trun->si;
|
||||
assert(run->lrun->si >= state->line_start_index);
|
||||
offset = state->line_start_index + run->lrun->si;
|
||||
|
||||
if ((have_cluster = (dir > 0)))
|
||||
__mg_glyph_run_iter_init_start(&cluster_iter, run, text);
|
||||
@@ -989,8 +960,8 @@ static void justify_words (LAYOUTLINE *line,
|
||||
BOOL have_cluster;
|
||||
int offset;
|
||||
|
||||
assert(run->trun->si >= state->line_start_index);
|
||||
offset = state->line_start_index + run->trun->si;
|
||||
assert(run->lrun->si >= state->line_start_index);
|
||||
offset = state->line_start_index + run->lrun->si;
|
||||
|
||||
for (have_cluster = __mg_glyph_run_iter_init_start (&cluster_iter,
|
||||
run, text);
|
||||
@@ -1149,7 +1120,7 @@ static LAYOUTLINE* check_next_line(LAYOUTINFO* layout, LayoutState* state)
|
||||
state->remaining_width = state->line_width;
|
||||
|
||||
while (state->item) {
|
||||
TextRun *item = state->item;
|
||||
LayoutRun *item = state->item;
|
||||
BreakResult result;
|
||||
int old_num_chars;
|
||||
int old_remaining_width;
|
||||
@@ -1275,24 +1246,27 @@ LAYOUTLINE* GUIAPI LayoutNextLine(
|
||||
goto next_line;
|
||||
}
|
||||
|
||||
state.item = (TextRun*)&layout->truninfo->truns.next;
|
||||
state.trun = (TextRun*)&layout->truninfo->truns.next;
|
||||
state.item = __mg_layout_run_new_from(layout, state.trun);
|
||||
state.start_index_in_item = 0;
|
||||
state.left_ucs_in_item = state.item->len;
|
||||
}
|
||||
else {
|
||||
state.start_offset = layout->truninfo->nr_ucs - layout->nr_left_ucs;
|
||||
state.item = __mg_textruns_get_by_offset(layout->truninfo,
|
||||
state.trun = __mg_textruns_get_by_offset(layout->truninfo,
|
||||
state.start_offset, &state.start_index_in_item);
|
||||
if (state.item == NULL) {
|
||||
if (state.trun == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
state.item = __mg_layout_run_new_from_offset(layout,
|
||||
state.trun, state.start_index_in_item);
|
||||
state.left_ucs_in_item = state.item->len - state.start_index_in_item;
|
||||
}
|
||||
|
||||
state.line_width = max_extent;
|
||||
state.remaining_width = max_extent;
|
||||
|
||||
next_line = check_next_line (layout, &state);
|
||||
next_line = check_next_line(layout, &state);
|
||||
|
||||
next_line:
|
||||
if (next_line) {
|
||||
|
||||
+42
-7
@@ -64,9 +64,26 @@ struct _GlyphString {
|
||||
unsigned int space;
|
||||
};
|
||||
|
||||
#define LAYOUTRUN_FLAG_ORPHAN 0x01
|
||||
|
||||
struct _LayoutRun {
|
||||
struct list_head list;
|
||||
LOGFONT* lf; // the logfont for this run
|
||||
const Uchar32* ucs; // the uchar string
|
||||
|
||||
int si; // the start index of this run
|
||||
int len; // the length of the uchar string
|
||||
Uint32 lc:8; // language code
|
||||
Uint32 st:8; // script type
|
||||
Uint32 el:8; // the bidi embedding level
|
||||
Uint32 dir:4; // the run direction
|
||||
Uint32 ort:2; // the glyph orientation
|
||||
Uint32 flags:2;// other flags
|
||||
};
|
||||
|
||||
struct _GlyphRun {
|
||||
struct list_head list;
|
||||
TextRun* trun; // the text run corresponding to the glyph run
|
||||
LayoutRun* lrun; // the layout run corresponding to the glyph run
|
||||
GlyphString* gs; // the glyph string
|
||||
};
|
||||
|
||||
@@ -124,7 +141,28 @@ struct _GlyphRunIter {
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
void __mg_layout_line_free_gruns(LAYOUTLINE* line);
|
||||
LOGFONT* __mg_create_logfont_for_layout(const LAYOUTINFO* layout,
|
||||
const char* fontname, GlyphOrient ort);
|
||||
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);
|
||||
void __mg_glyph_run_free(GlyphRun* run);
|
||||
|
||||
LayoutRun* __mg_layout_run_new_orphan(const LAYOUTINFO* layout,
|
||||
const TextRun* trun, const Uchar32* ucs, int nr_ucs);
|
||||
LayoutRun* __mg_layout_run_new_from(const LAYOUTINFO* layout,
|
||||
const TextRun* trun);
|
||||
LayoutRun* __mg_layout_run_new_from_offset(const LAYOUTINFO* layout,
|
||||
const TextRun* trun, int offset);
|
||||
|
||||
void __mg_layout_run_free(LayoutRun* run);
|
||||
|
||||
LayoutRun* __mg_layout_run_copy(const LayoutRun* run);
|
||||
LayoutRun* __mg_layout_run_split(LayoutRun *orig, int split_index);
|
||||
|
||||
void __mg_layout_line_free_runs(LAYOUTLINE* line);
|
||||
|
||||
GlyphString* __mg_glyph_string_new(void);
|
||||
void __mg_glyph_string_free(GlyphString* string);
|
||||
@@ -148,11 +186,8 @@ void __mg_glyph_run_letter_space (const GlyphRun* glyph_run,
|
||||
|
||||
BOOL __mg_layout_line_ellipsize(LAYOUTLINE *line, int goal_width);
|
||||
|
||||
int __mg_shape_text_run(const TEXTRUNSINFO* info, const TextRun* run,
|
||||
int so, int len, GlyphString* glyphs);
|
||||
|
||||
void __mg_shape_utf8 (const char* text, int len,
|
||||
const TextRun* trun, GlyphString* gs);
|
||||
int __mg_shape_layout_run(const TEXTRUNSINFO* info, const LayoutRun* run,
|
||||
GlyphString* glyphs);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -78,12 +78,12 @@ static void reverse_shaped_glyphs(ShapedGlyph* glyphs, int len)
|
||||
}
|
||||
|
||||
static BOOL shape_text_run(SEInstance* inst,
|
||||
const TEXTRUNSINFO* info, const TextRun* run,
|
||||
const TEXTRUNSINFO* info, const LayoutRun* run,
|
||||
GlyphString* gs)
|
||||
{
|
||||
BOOL ok = FALSE;
|
||||
int i, j;
|
||||
const Uchar32* logical_ucs = info->ucs + run->si;
|
||||
const Uchar32* logical_ucs = run->ucs;
|
||||
int nr_ucs = run->len;
|
||||
|
||||
Uchar32 local_shaped_ucs[LOCAL_ARRAY_SIZE];
|
||||
|
||||
+24
-144
@@ -71,7 +71,7 @@ enum {
|
||||
EMOJI_CHANGED = 1 << 6,
|
||||
};
|
||||
|
||||
typedef struct _TextRunSTATE {
|
||||
typedef struct _TextRunState {
|
||||
TEXTRUNSINFO* runinfo;
|
||||
const Uchar32* text;
|
||||
const Uchar32* end;
|
||||
@@ -96,9 +96,9 @@ typedef struct _TextRunSTATE {
|
||||
|
||||
LanguageCode derived_lang;
|
||||
|
||||
} TextRunSTATE;
|
||||
} TextRunState;
|
||||
|
||||
static void update_embedding_end(TextRunSTATE *state)
|
||||
static void update_embedding_end(TextRunState *state)
|
||||
{
|
||||
state->emb_level = state->els[state->emb_end_offset];
|
||||
while (state->emb_end < state->end &&
|
||||
@@ -111,7 +111,7 @@ static void update_embedding_end(TextRunSTATE *state)
|
||||
state->changed |= EMBEDDING_CHANGED;
|
||||
}
|
||||
|
||||
static void update_end (TextRunSTATE *state)
|
||||
static void update_end (TextRunState *state)
|
||||
{
|
||||
state->run_end = state->emb_end;
|
||||
if (state->script_iter.end < state->run_end)
|
||||
@@ -141,7 +141,7 @@ static LanguageCode compute_derived_language (LanguageCode lang,
|
||||
return derived_lang;
|
||||
}
|
||||
|
||||
static void state_update_for_new_run (TextRunSTATE *state)
|
||||
static void state_update_for_new_run (TextRunState *state)
|
||||
{
|
||||
if (state->changed & (SCRIPT_CHANGED | WIDTH_CHANGED)) {
|
||||
GlyphOrient orient = state->runinfo->ort_base;
|
||||
@@ -164,86 +164,11 @@ static void state_update_for_new_run (TextRunSTATE *state)
|
||||
}
|
||||
}
|
||||
|
||||
/* Use MiniGUI resource manager to avoid duplicated logfonts */
|
||||
LOGFONT* __mg_create_logfont_for_run(const TEXTRUNSINFO* runinfo,
|
||||
const TextRun* run)
|
||||
{
|
||||
char fontname[LEN_LOGFONT_NAME_FULL + 1];
|
||||
int orient_pos = fontGetOrientPosFromName(runinfo->fontname);
|
||||
LOGFONT* lf;
|
||||
|
||||
if (orient_pos < 0)
|
||||
return NULL;
|
||||
|
||||
memset (fontname, 0, LEN_LOGFONT_NAME_FULL + 1);
|
||||
strncpy (fontname, runinfo->fontname, LEN_LOGFONT_NAME_FULL);
|
||||
|
||||
switch (run->ort) {
|
||||
case GLYPH_ORIENT_UPRIGHT:
|
||||
fontname[orient_pos] = FONT_ORIENT_UPRIGHT;
|
||||
break;
|
||||
case GLYPH_ORIENT_SIDEWAYS:
|
||||
fontname[orient_pos] = FONT_ORIENT_SIDEWAYS;
|
||||
break;
|
||||
case GLYPH_ORIENT_UPSIDE_DOWN:
|
||||
fontname[orient_pos] = FONT_ORIENT_UPSIDE_DOWN;
|
||||
break;
|
||||
case GLYPH_ORIENT_SIDEWAYS_LEFT:
|
||||
fontname[orient_pos] = FONT_ORIENT_SIDEWAYS_LEFT;
|
||||
break;
|
||||
default:
|
||||
_WRN_PRINTF("bad orientation param: %d", run->ort);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lf = (LOGFONT*)LoadResource(fontname, RES_TYPE_FONT, 0);
|
||||
if (lf == NULL) {
|
||||
_ERR_PRINTF("%s: failed to create LOGFONT for run\n",
|
||||
__FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return lf;
|
||||
}
|
||||
|
||||
void __mg_release_logfont_for_run(const TEXTRUNSINFO* runinfo,
|
||||
const TextRun* run)
|
||||
{
|
||||
char fontname[LEN_LOGFONT_NAME_FULL + 1];
|
||||
int orient_pos = fontGetOrientPosFromName(runinfo->fontname);
|
||||
|
||||
if (orient_pos < 0)
|
||||
return;
|
||||
|
||||
memset (fontname, 0, LEN_LOGFONT_NAME_FULL + 1);
|
||||
strncpy (fontname, runinfo->fontname, LEN_LOGFONT_NAME_FULL);
|
||||
|
||||
switch (run->ort) {
|
||||
case GLYPH_ORIENT_UPRIGHT:
|
||||
fontname[orient_pos] = FONT_ORIENT_UPRIGHT;
|
||||
break;
|
||||
case GLYPH_ORIENT_SIDEWAYS:
|
||||
fontname[orient_pos] = FONT_ORIENT_SIDEWAYS;
|
||||
break;
|
||||
case GLYPH_ORIENT_UPSIDE_DOWN:
|
||||
fontname[orient_pos] = FONT_ORIENT_UPSIDE_DOWN;
|
||||
break;
|
||||
case GLYPH_ORIENT_SIDEWAYS_LEFT:
|
||||
fontname[orient_pos] = FONT_ORIENT_SIDEWAYS_LEFT;
|
||||
break;
|
||||
default:
|
||||
_WRN_PRINTF("bad orientation param: %d", run->ort);
|
||||
return;
|
||||
}
|
||||
|
||||
ReleaseRes(Str2Key(fontname));
|
||||
}
|
||||
|
||||
static void state_add_character(TextRunSTATE *state,
|
||||
static void state_add_character(TextRunState *state,
|
||||
BOOL no_shaping, BOOL force_break, const Uchar32* pos)
|
||||
{
|
||||
if (state->run) {
|
||||
BOOL without_shaping = (state->run->lf == NULL);
|
||||
BOOL without_shaping = (state->run->flags & TEXTRUN_FLAG_NOT_SHAPING);
|
||||
if (!force_break &&
|
||||
state->run->lc == state->derived_lang &&
|
||||
without_shaping == no_shaping) {
|
||||
@@ -253,6 +178,7 @@ static void state_add_character(TextRunSTATE *state,
|
||||
}
|
||||
|
||||
state->run = malloc(sizeof(TextRun));
|
||||
state->run->fontname = NULL;
|
||||
state->run->si = pos - state->text;
|
||||
state->run->len = 1;
|
||||
state->run->lc = state->derived_lang;
|
||||
@@ -260,12 +186,11 @@ static void state_add_character(TextRunSTATE *state,
|
||||
state->run->el = state->emb_level;
|
||||
state->run->dir = state->runinfo->run_dir;
|
||||
state->run->ort = state->ort_rsv;
|
||||
state->run->flags = 0;
|
||||
|
||||
if (no_shaping)
|
||||
state->run->lf = NULL;
|
||||
else
|
||||
state->run->lf = __mg_create_logfont_for_run(state->runinfo,
|
||||
state->run);
|
||||
if (no_shaping) {
|
||||
state->run->flags |= TEXTRUN_FLAG_NOT_SHAPING;
|
||||
}
|
||||
|
||||
/* The level vs. gravity dance:
|
||||
* If gravity is SOUTH, leave level untouched.
|
||||
@@ -294,14 +219,14 @@ static void state_add_character(TextRunSTATE *state,
|
||||
break;
|
||||
}
|
||||
|
||||
state->run->flags = state->centered_baseline ?
|
||||
TextRun_FLAG_CENTERED_BASELINE : 0;
|
||||
state->run->flags |= state->centered_baseline ?
|
||||
TEXTRUN_FLAG_CENTERED_BASELINE : 0;
|
||||
|
||||
list_add_tail(&state->run->list, &state->runinfo->truns);
|
||||
state->runinfo->nr_runs++;
|
||||
}
|
||||
|
||||
static BOOL state_process_run (TextRunSTATE *state)
|
||||
static BOOL state_process_run (TextRunState *state)
|
||||
{
|
||||
const Uchar32* p;
|
||||
BOOL last_was_forced_break = FALSE;
|
||||
@@ -332,7 +257,7 @@ static BOOL state_process_run (TextRunSTATE *state)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL state_next (TextRunSTATE *state)
|
||||
static BOOL state_next (TextRunState *state)
|
||||
{
|
||||
if (state->run_end == state->end)
|
||||
return FALSE;
|
||||
@@ -367,7 +292,7 @@ static BOOL state_next (TextRunSTATE *state)
|
||||
static BOOL create_text_runs(TEXTRUNSINFO* runinfo, BidiLevel* els)
|
||||
{
|
||||
BOOL ok = FALSE;
|
||||
TextRunSTATE state;
|
||||
TextRunState state;
|
||||
Uint8 local_types_buff[LOCAL_ARRAY_SIZE];
|
||||
Uint8* types_buff = NULL;
|
||||
|
||||
@@ -449,10 +374,10 @@ static inline Uint8 get_glyph_orient_from_fontname (const char* fontname)
|
||||
#ifdef _MGDEVEL_MODE
|
||||
void* GetNextTextRunInfo(TEXTRUNSINFO* runinfo,
|
||||
void* prev,
|
||||
LOGFONT** logfont, int* start_index, int* length,
|
||||
const char** fontname, int* start_index, int* length,
|
||||
LanguageCode* lang_code, ScriptType* script,
|
||||
BidiLevel* embedding_level, GlyphRunDir* run_dir,
|
||||
GlyphOrient* orient)
|
||||
GlyphOrient* orient, Uint8* flags)
|
||||
{
|
||||
TextRun* run = NULL;
|
||||
|
||||
@@ -469,7 +394,7 @@ void* GetNextTextRunInfo(TEXTRUNSINFO* runinfo,
|
||||
run = (TextRun*)list_entry->next;
|
||||
}
|
||||
|
||||
if (logfont) *logfont = run->lf;
|
||||
if (fontname) *fontname = run->fontname;
|
||||
if (start_index) *start_index = run->si;
|
||||
if (length) *length = run->len;
|
||||
if (lang_code) *lang_code = run->lc;
|
||||
@@ -477,6 +402,7 @@ void* GetNextTextRunInfo(TEXTRUNSINFO* runinfo,
|
||||
if (embedding_level) *embedding_level = run->el;
|
||||
if (run_dir) *run_dir = run->dir;
|
||||
if (orient) *orient = run->ort;
|
||||
if (flags) *flags = run->flags;
|
||||
|
||||
return run;
|
||||
}
|
||||
@@ -666,58 +592,12 @@ RGBCOLOR __mg_textruns_get_text_color(const TEXTRUNSINFO* runinfo, int index)
|
||||
return runinfo->attrs.value;
|
||||
}
|
||||
|
||||
TextRun* __mg_textruns_get_by_offset(const TEXTRUNSINFO* runinfo,
|
||||
const TextRun* __mg_textruns_get_by_offset(const TEXTRUNSINFO* runinfo,
|
||||
int offset, int *start_index)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TextRun* __mg_text_run_new_orphan(const TEXTRUNSINFO* info,
|
||||
const Uchar32* ucs, int nr_ucs)
|
||||
{
|
||||
TextRun* trun = malloc(sizeof(TextRun));
|
||||
|
||||
return trun;
|
||||
}
|
||||
|
||||
void __mg_text_run_free(TextRun* trun)
|
||||
{
|
||||
free(trun);
|
||||
}
|
||||
|
||||
TextRun* __mg_text_run_copy(const TextRun* trun)
|
||||
{
|
||||
TextRun *result;
|
||||
|
||||
if (trun == NULL)
|
||||
return NULL;
|
||||
|
||||
result = malloc(sizeof(TextRun));
|
||||
memcpy(result, trun, sizeof(TextRun));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
TextRun* __mg_text_run_split(TextRun *orig, int split_index)
|
||||
{
|
||||
TextRun *new_run;
|
||||
|
||||
if (orig == NULL)
|
||||
return NULL;
|
||||
if (split_index <= 0)
|
||||
return NULL;
|
||||
if (split_index >= orig->len)
|
||||
return NULL;
|
||||
|
||||
new_run = __mg_text_run_copy(orig);
|
||||
new_run->len = split_index;
|
||||
|
||||
orig->si += split_index;
|
||||
orig->len -= split_index;
|
||||
|
||||
return new_run;
|
||||
}
|
||||
|
||||
BOOL GUIAPI SetTextColorInTextRuns(TEXTRUNSINFO* runinfo,
|
||||
int start_index, int length, RGBCOLOR color)
|
||||
{
|
||||
@@ -761,8 +641,8 @@ BOOL GUIAPI DestroyTextRunsInfo(TEXTRUNSINFO* runinfo)
|
||||
while (!list_empty(&runinfo->truns)) {
|
||||
TextRun* run = (TextRun*)runinfo->truns.prev;
|
||||
list_del(runinfo->truns.prev);
|
||||
if (run->lf)
|
||||
__mg_release_logfont_for_run(runinfo, run);
|
||||
if (run->fontname)
|
||||
free(run->fontname);
|
||||
free(run);
|
||||
}
|
||||
|
||||
|
||||
@@ -43,13 +43,14 @@
|
||||
|
||||
#include "list.h"
|
||||
|
||||
typedef struct _LayoutRun LayoutRun;
|
||||
typedef struct _TextRun TextRun;
|
||||
typedef struct _GlyphString GlyphString;
|
||||
typedef struct _SEInstance SEInstance;
|
||||
typedef struct _TextAttrMap TextAttrMap;
|
||||
|
||||
typedef BOOL (*CB_SHAPE_TEXT_RUN)(SEInstance* instance,
|
||||
const TEXTRUNSINFO* info, const TextRun* run,
|
||||
const TEXTRUNSINFO* info, const LayoutRun* run,
|
||||
GlyphString* gs);
|
||||
|
||||
typedef BOOL (*CB_DESTROY_INSTANCE)(SEInstance* instance);
|
||||
@@ -67,16 +68,15 @@ struct _ShapingEngineInfo {
|
||||
CB_DESTROY_INSTANCE free;
|
||||
};
|
||||
|
||||
#define TextRun_FLAG_CENTERED_BASELINE 0x01
|
||||
#define TextRun_FLAG_IS_ELLIPSIS 0x02
|
||||
#define TEXTRUN_FLAG_CENTERED_BASELINE 0x01
|
||||
#define TEXTRUN_FLAG_NOT_SHAPING 0x02
|
||||
|
||||
struct _TextRun {
|
||||
struct list_head list;
|
||||
const char* fontname; // the logfont name for this run; NULL for default
|
||||
LOGFONT* lf; // the logfont for this run
|
||||
char* fontname; // the logfont name for this run; NULL for default
|
||||
|
||||
int si; // start index in the Unicode string
|
||||
int len; // the number of Unicode characters
|
||||
int si; // start index in the uchar string
|
||||
int len; // the length in uchars
|
||||
|
||||
Uint32 lc:8; // language code
|
||||
Uint32 st:8; // script type
|
||||
@@ -92,7 +92,6 @@ struct _TextRun {
|
||||
#define TEXT_ATTR_OUTLINE_COLOR 0x03
|
||||
#define TEXT_ATTR_BACKGROUND_COLOR 0x04
|
||||
|
||||
|
||||
struct _TextAttrMap {
|
||||
struct list_head list;
|
||||
int si;
|
||||
@@ -126,20 +125,8 @@ struct _TEXTRUNSINFO {
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
TextRun* __mg_text_run_new_orphan(const TEXTRUNSINFO* info,
|
||||
const Uchar32* ucs, int nr_ucs);
|
||||
void __mg_text_run_free(TextRun* trun);
|
||||
|
||||
TextRun* __mg_text_run_copy(const TextRun* trun);
|
||||
TextRun* __mg_text_run_split(TextRun *orig, int split_index);
|
||||
|
||||
LOGFONT* __mg_create_logfont_for_run(const TEXTRUNSINFO* runinfo,
|
||||
const TextRun* run);
|
||||
void __mg_release_logfont_for_run(const TEXTRUNSINFO* runinfo,
|
||||
const TextRun* run);
|
||||
|
||||
RGBCOLOR __mg_textruns_get_color(const TEXTRUNSINFO* runinfo, int index);
|
||||
TextRun* __mg_textruns_get_by_offset(const TEXTRUNSINFO* runinfo,
|
||||
const TextRun* __mg_textruns_get_by_offset(const TEXTRUNSINFO* runinfo,
|
||||
int offset, int *start_index);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
Reference in New Issue
Block a user