static MSymbol M_glyph_string;
/* Special scripts */
-static MSymbol Mlatin, Minherited;
+static MSymbol Minherited;
/* Special categories */
static MSymbol McatCc, McatCf;
-static MSymbol Mdepth;
-
\f
/* Glyph-string composer. */
{
int len = gstring->used - 2;
MGlyph *glyphs;
- int *idx = alloca (sizeof (int) * len);
- int gidx;
int bidi_sensitive = gstring->control.orientation_reversed;
- int size = 0;
- MGlyph *g = MGLYPH (1);
+ MGlyph *g;
int i;
#ifdef HAVE_FRIBIDI
- FriBidiCharType base = (gstring->control.orientation_reversed
- ? FRIBIDI_TYPE_RTL : FRIBIDI_TYPE_LTR);
+ FriBidiCharType base = bidi_sensitive ? FRIBIDI_TYPE_RTL : FRIBIDI_TYPE_LTR;
FriBidiChar *logical = alloca (sizeof (FriBidiChar) * len);
FriBidiChar *visual;
FriBidiStrIndex *indices;
- FriBidiLevel *levels = alloca (sizeof (FriBidiLevel) * len);
+ FriBidiLevel *levels;
#else /* not HAVE_FRIBIDI */
int *logical = alloca (sizeof (int) * len);
int *indices;
char *levels = alloca (len);
#endif /* not HAVE_FRIBIDI */
- while (g->type != GLYPH_ANCHOR)
+ for (g = MGLYPH (1), i = 0; g->type != GLYPH_ANCHOR; g++, i++)
{
- MSymbol bidi = (MSymbol) mchar_get_prop (g->c, Mbidi_category);
-
- if (bidi == MbidiR || bidi == MbidiAL
- || bidi == MbidiRLE || bidi == MbidiRLO)
+ if (! bidi_sensitive
+#ifndef HAVE_FRIBIDI
+ || 1
+#endif /* not HAVE_FRIBIDI */
+ )
{
- bidi_sensitive = 1;
- levels[size] = 1;
+ MSymbol bidi = (MSymbol) mchar_get_prop (g->c, Mbidi_category);
+
+ if (bidi == MbidiR || bidi == MbidiAL
+ || bidi == MbidiRLE || bidi == MbidiRLO)
+ {
+ bidi_sensitive = 1;
+#ifndef HAVE_FRIBIDI
+ levels[i] = 1;
+#endif /* not HAVE_FRIBIDI */
+ }
}
- else
- levels[size] = 0;
- idx[size] = GLYPH_INDEX (g);
- logical[size++] = g++->c;
- while (g->type != GLYPH_ANCHOR && g->combining_code)
- g++;
+ logical[i] = g->c;
}
if (! bidi_sensitive)
return;
- glyphs = alloca (sizeof (MGlyph) * gstring->used);
- memcpy (glyphs, gstring->glyphs, (sizeof (MGlyph) * gstring->used));
+ glyphs = alloca (sizeof (MGlyph) * len);
+ memcpy (glyphs, gstring->glyphs + 1, sizeof (MGlyph) * len);
#ifdef HAVE_FRIBIDI
- visual = alloca (sizeof (FriBidiChar) * size);
- indices = alloca (sizeof (FriBidiStrIndex) * size);
+ visual = alloca (sizeof (FriBidiChar) * (len + 1));
+ indices = alloca (sizeof (FriBidiStrIndex) * (len + 1));
+ levels = alloca (sizeof (FriBidiLevel) * (len + 1));
- fribidi_log2vis (logical, size, &base, visual, NULL, indices, levels);
+ fribidi_log2vis (logical, len, &base, visual, indices, NULL, levels);
#else /* not HAVE_FRIBIDI */
- indices = alloca (sizeof (int) * size);
- for (i = 0; i < size; i++)
+ indices = alloca (sizeof (int) * len);
+ for (i = 0; i < len; i++)
{
if (levels[i])
{
int j, k;
- for (j = i + 1; j < size && levels[j]; j++);
+ for (j = i + 1; j < len && levels[j]; j++);
for (k = j--; i < k; i++, j--)
indices[i] = j;
i--;
}
#endif /* not HAVE_FRIBIDI */
- /* IDX are indices to gstring->glyphs[]. The glyphs for LOGICAL[N]
- starts from gstring->glyphs[IDX[N]].
-
- INDICES are indices to LOGICAL[]. The glyph for VISUAL[N] is
- originally at LOGICAL[INDICES[N]]. */
-
- for (i = 0, gidx = 1; i < size; i++)
+ for (i = 0; i < len;)
{
+ /* Index into gstring->glyphs plus 1 for GLYPHS[i]. */
int j = indices[i];
- int k = idx[j];
+ /* Length of grapheme-cluster */
+ int seglen;
- glyphs[k].bidi_level = levels[j];
+ g = glyphs + i;
#ifdef HAVE_FRIBIDI
- if (visual[i] != logical[j])
+ if (visual[j] != logical[i])
{
/* Mirrored. */
- glyphs[k].c = visual[i];
- if (glyphs[k].rface->rfont)
- glyphs[k].code = mfont__encode_char (glyphs[k].rface->rfont,
- glyphs[k].c);
+ g->c = visual[j];
+ if (g->rface->rfont)
+ g->code = mfont__encode_char (g->rface->rfont, g->c);
}
-#endif /* not HAVE_FRIBIDI */
- *(MGLYPH (gidx)) = glyphs[k];
- for (gidx++, k++;
- k < gstring->used - 1 && glyphs[k].combining_code;
- gidx++, k++)
+#endif /* HAVE_FRIBIDI */
+ g->bidi_level = levels[i];
+ for (seglen = 1, g++;
+ i + seglen < len && (glyphs[i].pos == glyphs[i + seglen].pos
+ || glyphs[i + seglen].combining_code);
+ seglen++, g++)
{
- glyphs[k].bidi_level = levels[j];
- *(MGLYPH (gidx)) = glyphs[k];
+ g->bidi_level = levels[i];
+ if (indices[i + seglen] < j)
+ j = indices[i + seglen];
}
+ memcpy (MGLYPH (j + 1), glyphs + i, sizeof (MGlyph) * seglen);
+ i += seglen;
}
}
MGlyph g_tmp, *g;
int pos;
MSymbol language = Mnil, script = Mnil, charset = Mnil;
+ MSymbol non_latin_script = Mnil;
MRealizedFace *rface = default_rface;
- int non_ascii_found;
int size = gstring->control.fixed_width;
- int i, limit;
+ int i;
int last;
MLIST_RESET (gstring);
stop = face_change = charset_change = language_change = pos = from;
last = 0;
- non_ascii_found = 0;
while (1)
{
int c;
c = mtext_ref_char (mt, pos);
else
c = '\n';
- g_tmp.category = Mnil;
+ g_tmp.category = mchar_get_prop (c, Mcategory);
if (c < 0x100)
{
- if (c == ' ' || c == '\n' || c == '\t')
- g_tmp.type = GLYPH_SPACE, this_script = Mnil;
- else
- g_tmp.type = GLYPH_CHAR, this_script = Mlatin;
+ /* Short cut for the obvious case. */
+ g_tmp.type = (c == ' ' || c == '\n' || c == '\t'
+ ? GLYPH_SPACE : GLYPH_CHAR);
+ this_script = Mlatin;
}
else
{
- g_tmp.category = mchar_get_prop (c, Mcategory);
g_tmp.type = GLYPH_CHAR;
this_script = (MSymbol) mchar_get_prop (c, Mscript);
- if (this_script == Minherited)
+ if (this_script == Minherited || this_script == Mnil)
this_script = script;
+ if (this_script == Mnil)
+ this_script = non_latin_script;
+ if (this_script == Mnil)
+ {
+ /* Search forward for a character that explicitly
+ specifies a non-latin script. */
+ int c1;
+ MSymbol sym;
+
+ for (i = pos + 1; i < to; i++)
+ if ((c1 = mtext_ref_char (mt, i)) >= 0x100
+ && (sym = mchar_get_prop (c1, Mscript)) != Mnil
+ && sym != Minherited)
+ {
+ this_script = sym;
+ break;
+ }
+ }
}
if (pos == stop || script != this_script
|| MGLYPH (last)->type != g_tmp.type)
{
g = MGLYPH (last);
- if (non_ascii_found && g->type == GLYPH_CHAR)
+ if (g->type != GLYPH_ANCHOR)
while (g < gstring->glyphs + gstring->used)
g = mface__for_chars (script, language, charset,
g, gstring->glyphs + gstring->used, size);
- last = gstring->used;
- non_ascii_found = 0;
- script = this_script;
if (pos == to)
break;
- if (pos < mtext_nchars (mt) && pos == language_change)
- {
- language = (MSymbol) mtext_get_prop (mt, pos, Mlanguage);
- mtext_prop_range (mt, Mlanguage, pos, NULL, &language_change, 0);
- }
- if (pos < mtext_nchars (mt) && pos == charset_change)
- {
- charset = (MSymbol) mtext_get_prop (mt, pos, Mcharset);
- mtext_prop_range (mt, Mcharset, pos, NULL, &charset_change, 0);
- }
- if (pos < mtext_nchars (mt) && pos == face_change)
+ last = gstring->used;
+ script = this_script;
+ if (script != Mnil && script != Mlatin)
+ non_latin_script = script;
+ if (pos == stop)
{
- MFace *faces[64];
- int num = mtext_get_prop_values (mt, pos, Mface,
- (void **) faces, 64);
-
- mtext_prop_range (mt, Mface, pos, NULL, &face_change, 1);
- rface = (num > 0
- ? mface__realize (frame, faces, num,
- language, charset, size)
- : default_rface);
+ if (pos < mtext_nchars (mt) && pos == language_change)
+ {
+ language = (MSymbol) mtext_get_prop (mt, pos, Mlanguage);
+ mtext_prop_range (mt, Mlanguage, pos, NULL,
+ &language_change, 0);
+ }
+ if (pos < mtext_nchars (mt) && pos == charset_change)
+ {
+ charset = (MSymbol) mtext_get_prop (mt, pos, Mcharset);
+ mtext_prop_range (mt, Mcharset, pos, NULL,
+ &charset_change, 0);
+ }
+ if (pos < mtext_nchars (mt) && pos == face_change)
+ {
+ MFace *faces[64];
+ int num = mtext_get_prop_values (mt, pos, Mface,
+ (void **) faces, 64);
+
+ mtext_prop_range (mt, Mface, pos, NULL, &face_change, 1);
+ rface = (num > 0
+ ? mface__realize (frame, faces, num,
+ language, charset, size)
+ : default_rface);
+ }
+ stop = to;
+ if (stop > language_change)
+ stop = language_change;
+ if (stop > charset_change)
+ stop = charset_change;
+ if (face_change < stop)
+ stop = face_change;
}
- stop = to;
- if (stop > language_change)
- stop = language_change;
- if (stop > charset_change)
- stop = charset_change;
- if (face_change < stop)
- stop = face_change;
}
- g_tmp.c = g_tmp.code = c;
+ g_tmp.c = c;
g_tmp.pos = pos++;
g_tmp.to = pos;
g_tmp.rface = rface;
- if (c >= 0x100)
- non_ascii_found = 1;
- else if (g_tmp.type == GLYPH_CHAR && (c <= 32 || c == 127))
+ if ((c <= 32 || c == 127) && g_tmp.type == GLYPH_CHAR)
{
- g_tmp.code = '^';
- APPEND_GLYPH (gstring, g_tmp);
- if (c < ' ')
- g_tmp.code = g_tmp.c + 0x40;
- else
- g_tmp.code = '?';
+ MGlyph ctrl[2];
+
+ ctrl[0] = ctrl[1] = g_tmp;
+ ctrl[0].c = '^';
+ ctrl[1].c = c < ' ' ? c + 0x40 : '?';
+ mface__for_chars (Mlatin, language, charset, ctrl, ctrl + 2, size);
+ APPEND_GLYPH (gstring, ctrl[0]);
+ APPEND_GLYPH (gstring, ctrl[1]);
}
- APPEND_GLYPH (gstring, g_tmp);
+ else
+ APPEND_GLYPH (gstring, g_tmp);
if (c == '\n'
&& gstring->control.two_dimensional)
break;
}
- limit = pos - from;
-
/* Append an anchor glyph. */
g_tmp.type = GLYPH_ANCHOR;
g_tmp.c = 0;
}
if (start + 1 < i)
reorder_combining_chars (gstring, start, i);
+ if (this->type == GLYPH_ANCHOR)
+ break;
}
g = MGLYPH (i);
}
}
+typedef struct {
+ int width, lbearing, rbearing;
+} MSubTextExtents;
+
static void
-layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to)
+layout_glyphs (MFrame *frame, MGlyphString *gstring, int from, int to,
+ MSubTextExtents *extents)
{
int g_physical_ascent, g_physical_descent;
- int g_width, g_lbearing, g_rbearing;
MGlyph *g = MGLYPH (from);
MGlyph *last_g = MGLYPH (to);
+ int i;
g_physical_ascent = gstring->physical_ascent;
g_physical_descent = gstring->physical_descent;
- g_width = g_lbearing = g_rbearing = 0;
+ extents->width = extents->lbearing = extents->rbearing = 0;
+
+ for (i = from; i < to;)
+ {
+ if ( MGLYPH (i)->otf_encoded)
+ i++;
+ else
+ {
+ int j = i++;
- mfont__get_metric (gstring, from, to);
+ while (i < to && ! MGLYPH (i)->otf_encoded) i++;
+ mfont__get_metric (gstring, j, i);
+ }
+ }
+ g = MGLYPH (from);
while (g < last_g)
{
MGlyph *base = g++;
if (g == last_g || ! g->combining_code)
{
/* No combining. */
+ if (base->width == 0 && ! base->left_padding && ! base->right_padding
+ && GLYPH_INDEX (base) > from)
+ {
+ MGlyph *prev = base - 1;
+
+ if (base->pos < prev->pos)
+ prev->pos = base->pos;
+ else
+ base->pos = prev->pos;
+ if (base->to > prev->to)
+ prev->to = base->to;
+ else
+ base->to = prev->to;
+ }
+
if (base->left_padding && base->lbearing < 0)
{
base->xoff = - base->lbearing;
{
base->width = base->rbearing;
}
- lbearing = (base->lbearing < 0 ? base->lbearing : 0);
- rbearing = base->rbearing;
+ lbearing = (base->xoff + base->lbearing < 0
+ ? base->xoff + base->lbearing : 0);
+ rbearing = base->xoff + base->rbearing;
}
else
{
while (g != last_g && g->combining_code)
{
- int combining_code, base_x, base_y, add_x, add_y, off_x, off_y;
-
- combining_code = g->combining_code;
- if (COMBINING_BY_CLASS_P (combining_code))
- g->combining_code = combining_code
- = combining_code_from_class (COMBINING_CODE_CLASS
- (combining_code));
-
- rfont = g->rface->rfont;
- size = rfont->font.property[MFONT_SIZE];
- off_x = (size * (COMBINING_CODE_OFF_X (combining_code) - 128)
- / 1000);
- off_y = (size * (COMBINING_CODE_OFF_Y (combining_code) - 128)
- / 1000);
- base_x = COMBINING_CODE_BASE_X (combining_code);
- base_y = COMBINING_CODE_BASE_Y (combining_code);
- add_x = COMBINING_CODE_ADD_X (combining_code);
- add_y = COMBINING_CODE_ADD_Y (combining_code);
+ int combining_code = g->combining_code;
if (begin > g->pos)
begin = g->pos;
else if (end < g->to)
end = g->to;
- g->xoff = left + (width * base_x - g->width * add_x) / 2 + off_x;
- if (g->xoff < left)
- left = g->xoff;
- if (g->xoff + g->width > right)
- right = g->xoff + g->width;
- width = right - left;
+ if (! COMBINING_PRECOMPUTED_P (combining_code))
+ {
+ int base_x, base_y, add_x, add_y, off_x, off_y;
+
+ if (COMBINING_BY_CLASS_P (combining_code))
+ g->combining_code = combining_code
+ = combining_code_from_class (COMBINING_CODE_CLASS
+ (combining_code));
+
+ rfont = g->rface->rfont;
+ size = rfont->font.property[MFONT_SIZE];
+ off_x = (size * (COMBINING_CODE_OFF_X (combining_code) - 128)
+ / 1000);
+ off_y = (size * (COMBINING_CODE_OFF_Y (combining_code) - 128)
+ / 1000);
+ base_x = COMBINING_CODE_BASE_X (combining_code);
+ base_y = COMBINING_CODE_BASE_Y (combining_code);
+ add_x = COMBINING_CODE_ADD_X (combining_code);
+ add_y = COMBINING_CODE_ADD_Y (combining_code);
+
+ g->xoff = left + (width * base_x - g->width * add_x) / 2 + off_x;
+ if (g->xoff < left)
+ left = g->xoff;
+ if (g->xoff + g->width > right)
+ right = g->xoff + g->width;
+ width = right - left;
+
+ if (base_y < 3)
+ g->yoff = top + height * base_y / 2;
+ else
+ g->yoff = 0;
+ if (add_y < 3)
+ g->yoff -= (g->ascent + g->descent) * add_y / 2 - g->ascent;
+ g->yoff -= off_y;
+ }
+
if (g->xoff + g->lbearing < left + lbearing)
lbearing = g->xoff + g->lbearing - left;
if (g->xoff + g->rbearing > left + rbearing)
rbearing = g->xoff + g->rbearing - left;
-
- if (base_y < 3)
- g->yoff = top + height * base_y / 2;
- else
- g->yoff = 0;
- if (add_y < 3)
- g->yoff -= (g->ascent + g->descent) * add_y / 2 - g->ascent;
- g->yoff -= off_y;
if (g->yoff - g->ascent < top)
top = g->yoff - g->ascent;
if (g->yoff + g->descent > bottom)
g_physical_ascent = MAX (g_physical_ascent, base->ascent);
g_physical_descent = MAX (g_physical_descent, base->descent);
- g_lbearing = MIN (g_lbearing, g_width + lbearing);
- g_rbearing = MAX (g_rbearing, g_width + rbearing);
- g_width += base->width;
+ extents->lbearing = MIN (extents->lbearing, extents->width + lbearing);
+ extents->rbearing = MAX (extents->rbearing, extents->width + rbearing);
+ extents->width += base->width;
}
gstring->physical_ascent = g_physical_ascent;
gstring->physical_descent = g_physical_descent;
- gstring->sub_width = g_width;
- gstring->sub_lbearing = g_lbearing;
- gstring->sub_rbearing = g_rbearing;
}
{
int extra_width;
int to = GLYPH_INDEX (g);
+ MSubTextExtents extents;
- layout_glyphs (frame, gstring, from, to);
- extra_width = - gstring->sub_lbearing;
+ layout_glyphs (frame, gstring, from, to, &extents);
+ extra_width = - extents.lbearing;
if (extra_width > 0
- && (GLYPH_INDEX (g) > 1
- || control->align_head))
+ && ! control->disable_overlapping_adjustment
+ && (! control->orientation_reversed
+ ? ((to > 1 || control->align_head)
+ && g->type != GLYPH_ANCHOR)
+ : (((g->type && GLYPH_ANCHOR) || control->align_head)
+ && to > 1)))
{
g = MGLYPH (from);
pad = *g;
pad.xoff = 0;
pad.lbearing = 0;
pad.width = pad.rbearing = extra_width;
+ pad.left_padding = 1;
INSERT_GLYPH (gstring, from, pad);
to++;
- gstring->sub_lbearing = 0;
- gstring->sub_width += extra_width;
- gstring->sub_rbearing += extra_width;
+ extents.lbearing = 0;
+ extents.width += extra_width;
+ extents.rbearing += extra_width;
g = MGLYPH (from - 1);
if (g->type == GLYPH_SPACE)
}
else
{
- extra_width -= g->width - 2;
+ extra_width = g->width - 2;
g->width = 2;
}
gstring->width -= extra_width;
}
}
- extra_width = gstring->sub_rbearing - gstring->sub_width;
- if (extra_width > 0)
+ g = MGLYPH (to);
+ extra_width = extents.rbearing - extents.width;
+ if (extra_width > 0
+ && ! control->disable_overlapping_adjustment
+ && (GLYPH_INDEX (g) < gstring->used - 1
+ || (control->orientation_reversed && control->align_head)))
{
- g = MGLYPH (to);
if (g->type == GLYPH_SPACE && box == g->rface->box)
{
- g--;
- pad = *g;
+ pad = g[-1];
pad.type = GLYPH_PAD;
pad.xoff = 0;
pad.lbearing = 0;
pad.width = pad.rbearing = extra_width;
INSERT_GLYPH (gstring, to, pad);
to++;
+ g = MGLYPH (to);
}
else
g[-1].width += extra_width;
- gstring->sub_width += extra_width;
+ extents.width += extra_width;
}
- if (gstring->lbearing > gstring->width + gstring->sub_lbearing)
- gstring->lbearing = gstring->width + gstring->sub_lbearing;
- if (gstring->rbearing < gstring->width + gstring->sub_rbearing)
- gstring->rbearing = gstring->width + gstring->sub_rbearing;
- gstring->width += gstring->sub_width;
+ if (gstring->lbearing > gstring->width + extents.lbearing)
+ gstring->lbearing = gstring->width + extents.lbearing;
+ if (gstring->rbearing < gstring->width + extents.rbearing)
+ gstring->rbearing = gstring->width + extents.rbearing;
+ gstring->width += extents.width;
if (gstring->ascent < rface->ascent)
gstring->ascent = rface->ascent;
if (gstring->descent < rface->descent)
gstring->descent = rface->descent;
- g = MGLYPH (to);
}
else
{
if (gstring->from <= control->cursor_pos
&& gstring->to > control->cursor_pos)
cursor_pos = control->cursor_pos;
- if (cursor_bidi
+ if (cursor_pos >= 0
+ && cursor_bidi
&& gstring->from <= control->cursor_pos - 1
&& gstring->to > control->cursor_pos - 1)
prev_pos = control->cursor_pos - 1;
this_x += fromg->width, this_width -= fromg->width;
if (g[-1].type == GLYPH_BOX)
this_width -= g[-1].width;
- mwin__fill_space (frame, win, rface, 0,
- this_x, y - gstring->text_ascent, this_width,
- gstring->text_ascent + gstring->text_descent,
- control->clip_region);
+ (frame->driver->fill_space)
+ (frame, win, rface, 0,
+ this_x, y - gstring->text_ascent, this_width,
+ gstring->text_ascent + gstring->text_descent,
+ control->clip_region);
}
if (cursor)
{
? control->cursor_width : cursor_width);
}
else
- {
- if (cursor->bidi_level % 2)
- rect.x += cursor_width - 1;
- rect.width = 1;
- }
- mwin__fill_space (frame, win, rface, 1,
- rect.x, rect.y, rect.width, rect.height,
- control->clip_region);
+ rect.width = 1;
+ if (cursor->bidi_level % 2)
+ rect.x += cursor_width - rect.width;
+ (*frame->driver->fill_space)
+ (frame, win, rface, 1, rect.x, rect.y, rect.width, rect.height,
+ control->clip_region);
if (! region)
- region = mwin__region_from_rect (&rect);
+ region = (*frame->driver->region_from_rect) (&rect);
else
- mwin__region_add_rect (region, &rect);
- mwin__verify_region (frame, region);
+ (*frame->driver->region_add_rect) (region, &rect);
if (cursor_bidi)
{
if (cursor->bidi_level % 2)
rect.x -= 3;
rect.height = 2;
rect.width = cursor_width < 4 ? cursor_width : 4;
- mwin__fill_space (frame, win, rface, 1,
- rect.x, rect.y, rect.width, rect.height,
- control->clip_region);
- mwin__region_add_rect (region, &rect);
- mwin__verify_region (frame, region);
+ (*frame->driver->fill_space)
+ (frame, win, rface, 1,
+ rect.x, rect.y, rect.width, rect.height,
+ control->clip_region);
+ (*frame->driver->region_add_rect) (region, &rect);
}
}
rect.y = y - gstring->text_ascent;
rect.height = gstring->text_ascent + gstring->text_descent;
rect.width = 1;
- mwin__fill_space (frame, win, rface, 1,
- rect.x, rect.y, rect.width, rect.height,
- control->clip_region);
+ (*frame->driver->fill_space)
+ (frame, win, rface, 1,
+ rect.x, rect.y, rect.width, rect.height,
+ control->clip_region);
if (! region)
- region = mwin__region_from_rect (&rect);
+ region = (*frame->driver->region_from_rect) (&rect);
else
- mwin__region_add_rect (region, &rect);
- mwin__verify_region (frame, region);
+ (*frame->driver->region_add_rect) (region, &rect);
rect.y += rect.height - 2;
rect.height = 2;
rect.width = cursor_width < 4 ? cursor_width : 4;
if (! (cursor->bidi_level % 2))
rect.x -= rect.width - 1;
- mwin__fill_space (frame, win, rface, 1,
+ (*frame->driver->fill_space) (frame, win, rface, 1,
rect.x, rect.y, rect.width, rect.height,
control->clip_region);
- mwin__region_add_rect (region, &rect);
- mwin__verify_region (frame, region);
+ (*frame->driver->region_add_rect) (region, &rect);
}
}
x += width;
{
MDrawMetric rect;
- mwin__region_to_rect (region, &rect);
+ (*frame->driver->region_to_rect) (region, &rect);
if (rect.x > x)
{
while (g != gend && x + g->rbearing <= rect.x)
while (g != gend
&& g->type == from_g->type
&& g->rface == rface
- && (g->code < 0) == (from_g->code < 0)
+ && ((g->code == MCHAR_INVALID_CODE)
+ == (from_g->code == MCHAR_INVALID_CODE))
&& g->enabled)
width += g++->width;
if (from_g->type == GLYPH_CHAR)
{
- if (rface->rfont && from_g->code >= 0)
+ if (rface->rfont && from_g->code != MCHAR_INVALID_CODE)
(rface->rfont->driver->render) (win, x, y, gstring, from_g, g,
reverse, region);
else
- mwin__draw_empty_boxes (win, x, y, gstring, from_g, g,
+ (*frame->driver->draw_empty_boxes) (win, x, y, gstring, from_g, g,
reverse, region);
}
else if (from_g->type == GLYPH_BOX)
/* Draw the left or right side of a box. If
from_g->lbearing is nonzero, this is the left side,
else this is the right side. */
- mwin__draw_box (frame, win, gstring, from_g, x, y, 0, region);
+ (*frame->driver->draw_box) (frame, win, gstring, from_g, x, y, 0, region);
}
if (from_g->type != GLYPH_BOX)
{
if (rface->hline)
- mwin__draw_hline (frame, win, gstring, rface, reverse,
+ (*frame->driver->draw_hline) (frame, win, gstring, rface, reverse,
x, y, width, region);
if (rface->box
&& ! reverse)
/* Draw the top and bottom side of a box. */
- mwin__draw_box (frame, win, gstring, from_g,
+ (*frame->driver->draw_box) (frame, win, gstring, from_g,
x, y, width, region);
}
x += width;
{
rect.y = y - gstring->line_ascent;
rect.height = gstring->height;
- clip_region = mwin__region_from_rect (&rect);
+ clip_region = (*frame->driver->region_from_rect) (&rect);
if (control->clip_region)
- mwin__intersect_region (clip_region, control->clip_region);
+ (*frame->driver->intersect_region) (clip_region, control->clip_region);
}
else
clip_region = control->clip_region;
if (cursor_region)
{
if (clip_region)
- mwin__intersect_region (cursor_region, clip_region);
+ (*frame->driver->intersect_region) (cursor_region, clip_region);
render_glyphs (frame, win, x, y, to_x - x, gstring, from_idx, to_idx,
1, cursor_region);
}
if (clip_region != control->clip_region)
- mwin__free_region (clip_region);
+ (*frame->driver->free_region) (clip_region);
if (cursor_region)
- mwin__free_region (cursor_region);
+ (*frame->driver->free_region) (cursor_region);
return;
}
gstring->frame = frame;
gstring->tick = frame->tick;
gstring->top = gstring;
- gstring->mt = mt;
gstring->control = *control;
gstring->indent = gstring->width_limit = 0;
if (control->format)
else
gstring->width_limit = control->max_line_width;
gstring->anti_alias = control->anti_alias;
- if (gstring->anti_alias
- && (unsigned) mwin__device_get_prop (frame->device, Mdepth) < 8)
- gstring->anti_alias = 0;
return gstring;
}
int pos;
/* Setup the array POS_WIDTH so that POS_WIDTH[I - GSTRING->from] is
- a width of glyphs for the character at I of GSTRING->mt. If I is
- not a beginning of a grapheme cluster, the corresponding element
- is 0. */
+ a width of glyphs for the character at I of MT. If I is not a
+ beginning of a grapheme cluster, the corresponding element is
+ 0. */
MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW);
memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from));
for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
pos = gstring->from + i;
if (gstring->control.line_break)
{
- pos = (*gstring->control.line_break) (gstring->mt, gstring->from + i,
+ pos = (*gstring->control.line_break) (mt, gstring->from + i,
gstring->from, gstring->to, 0, 0);
- if (pos <= gstring->from || pos >= gstring->to)
- return;
+ if (pos <= gstring->from)
+ pos = gstring->from + 1;
+ else if (pos >= gstring->to)
+ pos = gstring->to;
}
+ else if (i == 0)
+ pos++;
compose_glyph_string (frame, mt, gstring->from, pos, gstring);
layout_glyph_string (frame, gstring);
}
|| gstring->tick != frame->tick
|| memcmp (control, &gstring->control,
(char *) (&control->with_cursor)
- - (char *) (control)))
+ - (char *) (control))
+ || control->cursor_width != gstring->control.cursor_width
+ || control->cursor_bidi != gstring->control.cursor_bidi)
{
mtext_detach_property (prop);
gstring = NULL;
int beg, end;
int line = 0, y = 0;
- if (control->two_dimensional)
- {
- beg = mtext_character (mt, pos, 0, '\n');
- if (beg < 0)
- beg = 0;
- else
- beg++;
- end = mtext_nchars (mt) + (control->cursor_width != 0);
- }
+ beg = mtext_character (mt, pos, 0, '\n');
+ if (beg < 0)
+ beg = 0;
else
- {
- beg = pos;
- end = to;
- }
+ beg++;
+ end = mtext_nchars (mt) + (control->cursor_width != 0);
+
gstring = alloc_gstring (frame, mt, beg, control, line, y);
compose_glyph_string (frame, mt, beg, end, gstring);
layout_glyph_string (frame, gstring);
end = gstring->to;
- if (control->two_dimensional
- && gstring->width_limit
+ if (gstring->width_limit
&& gstring->width > gstring->width_limit)
{
MGlyphString *gst = gstring;
memset (&scratch_gstring, 0, sizeof (scratch_gstring));
MLIST_INIT1 (&scratch_gstring, glyphs, 3);
- Mlatin = msymbol ("latin");
Minherited = msymbol ("inherited");
McatCc = msymbol ("Cc");
McatCf = msymbol ("Cf");
- Mdepth = msymbol ("depth");
MbidiR = msymbol ("R");
MbidiAL = msymbol ("AL");
{
MDrawControl control;
+ M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
memset (&control, 0, sizeof control);
control.as_image = 0;
return draw_text (frame, win, x, y, mt, from, to, &control);
{
MDrawControl control;
+ M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
memset (&control, 0, sizeof control);
control.as_image = 1;
return draw_text (frame, win, x, y, mt, from, to, &control);
mdraw_text_with_control (MFrame *frame, MDrawWindow win, int x, int y,
MText *mt, int from, int to, MDrawControl *control)
{
+ M_CHECK_WRITABLE (frame, MERROR_DRAW, -1);
return draw_text (frame, win, x, y, mt, from, to, control);
}
ASSURE_CONTROL (control);
*num_chars_return = to - from;
if (array_size < *num_chars_return)
- return 0;
+ MERROR (MERROR_DRAW, -1);
if (overall_logical_return)
memset (overall_logical_return, 0, sizeof (MDrawMetric));
if (overall_ink_return)
return 0;
}
- for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR;)
+ for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR; g++)
if (g->pos >= from && g->pos < to)
{
int start = g->pos;
int rbearing = g->rbearing;
int ascent = g->ascent;
int descent = g->descent;
- int logical_ascent = g->rface->rfont->ascent;
- int logical_descent = g->rface->rfont->descent;
+ int logical_ascent;
+ int logical_descent;
+ if (g->rface->rfont)
+ {
+ logical_ascent = g->rface->rfont->ascent;
+ logical_descent = g->rface->rfont->descent;
+ }
+ else
+ {
+ logical_ascent = g->rface->ascent;
+ logical_descent = g->rface->descent;
+ }
for (g++; g->type != GLYPH_ANCHOR && g->pos == start; g++)
{
if (lbearing < width + g->lbearing)
end = to;
while (start < end)
{
- ink_array_return[start - from].x = x + lbearing;
- ink_array_return[start - from].y = - ascent;
- ink_array_return[start - from].width = rbearing - lbearing;
- ink_array_return[start - from].height = ascent + descent;
- logical_array_return[start - from].x = x;
- logical_array_return[start - from].y = - logical_descent;
- logical_array_return[start - from].height
- = logical_ascent + logical_descent;
- logical_array_return[start - from].width = width;
+ if (ink_array_return)
+ {
+ ink_array_return[start - from].x = x + lbearing;
+ ink_array_return[start - from].y = - ascent;
+ ink_array_return[start - from].width = rbearing - lbearing;
+ ink_array_return[start - from].height = ascent + descent;
+ }
+ if (logical_array_return)
+ {
+ logical_array_return[start - from].x = x;
+ logical_array_return[start - from].y = - logical_descent;
+ logical_array_return[start - from].height
+ = logical_ascent + logical_descent;
+ logical_array_return[start - from].width = width;
+ }
start++;
}
x += width;
+ g--;
}
if (overall_ink_return)
}
M17N_OBJECT_UNREF (gstring->top);
- return 1;
+ return 0;
}
/*=*/
if (! control->orientation_reversed)
{
width = gstring->indent;
- for (g = MGLYPH (1); g[1].type != GLYPH_ANCHOR; g++)
+ for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
if (g->pos >= from && g->pos < to)
{
width += g->width;
}
info->from = g->pos;
info->to = g->to;
- info->this.x = g->lbearing;
- info->this.y = - gstring->line_ascent;
- info->this.height = gstring->height;
+ info->metrics.x = g->lbearing;
+ info->metrics.y = - gstring->line_ascent;
+ info->metrics.height = gstring->height;
+ info->metrics.width = - g->lbearing + g->width;
if (g->rface->rfont)
info->font = &g->rface->rfont->font;
else
info->font = NULL;
- /* info->this.width is calculated later. */
+ /* info->logical_width is calculated later. */
if (info->from > info->line_from)
{
else
info->next_to = -1;
- for (info->this.width = (g++)->width;
+ for (info->logical_width = (g++)->width;
g->pos == pos && g->type != GLYPH_ANCHOR;
- info->this.width += (g++)->width);
+ info->metrics.width += g->width, info->logical_width += (g++)->width);
+ info->metrics.width += g[-1].rbearing - g[-1].width;
if (g->type != GLYPH_ANCHOR)
info->right_from = g->pos, info->right_to = g->to;
/*=*/
/***en
+ @brief Compute information about glyph sequence.
+
+ The mdraw_glyph_list () function computes information about glyphs
+ corresponding to the text between $FROM and $TO of M-text $MT when
+ it is drawn on a window of frame $FRAME using the
+ mdraw_text_with_control () function with the drawing control
+ object $CONTROL. $GLYPHS is an array of objects to store the
+ information, and $ARRAY_SIZE is the array size.
+
+ If $ARRAY_SIZE is large enough to cover all glyphs, it stores the
+ number of actually filled elements in the place pointed by
+ $NUM_GLYPHS_RETURN, and returns 0.
+
+ Otherwise, it stores the required array size in the place pointed
+ by $NUM_GLYPHS_RETURN, and returns -1. */
+
+/***ja
+ @brief ¥°¥ê¥ÕÎó¤Ë´Ø¤¹¤ë¾ðÊó¤ò·×»»¤¹¤ë.
+
+ ´Ø¿ô mdraw_glyph_list () ¤Ï¡¢´Ø¿ô mdraw_text_with_control () ¤¬ÉÁ²è
+ À©¸æ¥ª¥Ö¥¸¥§¥¯¥È $CONTROL ¤òÍѤ¤¤ÆM-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç
+ ¤ò¥Õ¥ì¡¼¥à $FRAME ¤ËÉÁ²è¤·¤¿¾ì¹ç¤Î¡¢³Æ¥°¥ê¥Õ¤Î¾ðÊó¤ò $GLYPHS ¤¬»Ø¤¹
+ ÇÛÎó¤Ë³ÊǼ¤¹¤ë¡£ $ARRAY_SIZE ¤Ï¤½¤ÎÇÛÎó¤Î¥µ¥¤¥º¤Ç¤¢¤ë¡£
+
+ ¤â¤· $ARRAY_SIZE ¤¬¤¹¤Ù¤Æ¤Î¥°¥ê¥Õ¤Ë¤Ä¤¤¤Æ¤Î¾ðÊó¤ò³ÊǼ¤¹¤ë¤Î¤Ë½½Ê¬¤Ç
+ ¤¢¤ì¤Ð¡¢ $NUM_GLYPHS_RETURN ¤¬»Ø¤¹¾ì½ê¤Ë¼ÂºÝ¤ËËä¤á¤¿Í×ÁǤοô¤òÀßÄê
+ ¤· 0 ¤òÊÖ¤¹¡£ */
+
+/***
+ @seealso
+ MDrawGlyph
+*/
+
+int
+mdraw_glyph_list (MFrame *frame, MText *mt, int from, int to,
+ MDrawControl *control, MDrawGlyph *glyphs,
+ int array_size, int *num_glyphs_return)
+{
+ MGlyphString *gstring;
+ MGlyph *g;
+ int n;
+ int pad_width = 0;
+
+ ASSURE_CONTROL (control);
+ *num_glyphs_return = 0;
+ M_CHECK_RANGE (mt, from, to, -1, 0);
+ gstring = get_gstring (frame, mt, from, to, control);
+ if (! gstring)
+ return -1;
+ for (g = MGLYPH (1), n = 0; g->type != GLYPH_ANCHOR; g++)
+ {
+ if (g->type == GLYPH_BOX
+ || g->pos < from || g->pos >= to)
+ continue;
+ if (g->type == GLYPH_PAD)
+ {
+ if (g->left_padding)
+ pad_width = g->width;
+ else if (n > 0)
+ {
+ pad_width = 0;
+ glyphs[-1].x_advance += g->width;
+ }
+ continue;
+ }
+ if (n < array_size)
+ {
+ glyphs->from = g->pos;
+ glyphs->to = g->to;
+ glyphs->glyph_code = g->code;
+ glyphs->x_off = g->xoff + pad_width;
+ glyphs->y_off = g->yoff;
+ glyphs->lbearing = g->lbearing;
+ glyphs->rbearing = g->rbearing;
+ glyphs->ascent = g->ascent;
+ glyphs->descent = g->descent;
+ glyphs->x_advance = g->width + pad_width;
+ glyphs->y_advance = 0;
+ if (g->rface->rfont)
+ {
+ glyphs->font = &g->rface->rfont->font;
+ glyphs->font_type = g->rface->rfont->type;
+ glyphs->fontp = g->rface->rfont->fontp;
+ }
+ else
+ {
+ glyphs->font = NULL;
+ glyphs->font_type = Mnil;
+ glyphs->fontp = NULL;
+ }
+ pad_width = 0;
+ glyphs++;
+ }
+ n++;
+ }
+ M17N_OBJECT_UNREF (gstring->top);
+
+ *num_glyphs_return = n;
+ return (n <= array_size ? 0 : -1);
+}
+
+/*=*/
+
+/***en
@brief Draw one or more textitems.
The mdraw_text_items () function draws one or more M-texts on
mdraw_text_items (MFrame *frame, MDrawWindow win, int x, int y,
MDrawTextItem *items, int nitems)
{
+ if (! (frame->device_type & MDEVICE_SUPPORT_OUTPUT))
+ return;
while (nitems-- > 0)
{
if (items->face)
If pointer $OVERALL_RETURN is not @c NULL, this function also
computes the extents of the overall text and stores the results in
- the members of the structure pointed to by $OVERALL_RETURN */
+ the members of the structure pointed to by $OVERALL_RETURN. */
/***ja
@brief M-text ¤Îʸ»úËè¤Îɽ¼¨ÈϰϾðÊó¤òÆÀ¤ë.
´Ø¿ô mdraw_per_char_extents () ¤Ï¡¢M-text $MT Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
¤ò·×»»¤¹¤ë¡£¤³¤Î·×»»¤ËÍѤ¤¤ë¥Õ¥©¥ó¥È¤Ï¡¢$MT ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ç
- »ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤È¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ·è
- ¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢Åö³º M-text Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
- ¾ðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£¤³¤Îɽ¼¨ÈϰϾðÊó¤Ï¡¢M-text ¤Îɽ¼¨¸¶ÅÀ
- ¤«¤é¤ÎÁêÂаÌÃ֤Ǥ¢¤ë¡£$ARRAY_RETURN ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text ¤Îʸ»ú¿ô°Ê
- ¾å¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
+ »ØÄꤵ¤ì¤¿¥Õ¥§¡¼¥¹¤Èa¡¢¥Õ¥ì¡¼¥à $FRAME ¤Î¥Ç¥Õ¥©¥ë¥È¥Õ¥§¡¼¥¹¤Ë¤è¤Ã¤Æ
+ ·è¤Þ¤ë¡£$ARRAY_RETURN ¤Î³ÆÍ×ÁǤϡ¢Åö³º M-text Ãæ¤Î³Æʸ»ú¤Îɽ¼¨ÈÏ°Ï
+ ¾ðÊó¤Ë¤è¤Ã¤Æ½ç¤ËËä¤á¤é¤ì¤ë¡£¤³¤Îɽ¼¨ÈϰϾðÊó¤Ï¡¢M-text ¤Îɽ¼¨¸¶ÅÀ¤«
+ ¤é¤ÎÁêÂаÌÃ֤Ǥ¢¤ë¡£$ARRAY_RETURN ¤ÎÍ×ÁÇ¿ô¤Ï¡¢M-text ¤Î°Ê¾å¤Ç¤Ê¤±¤ì
+ ¤Ð¤Ê¤é¤Ê¤¤¡£
¥Ý¥¤¥ó¥¿ $OVERALL_RETURN ¤¬ @c NULL ¤Ç¤Ê¤¤¾ì¹ç¤Ï¡¢¥Æ¥¥¹¥ÈÁ´ÂΤÎɽ
¼¨ÈϰϾðÊó¤â·×»»¤·¡¢¤½¤Î·ë²Ì¤ò $OVERALL_RETURN ¤Î»Ø¤¹¹½Â¤ÂΤ˳ÊǼ
void
mdraw_per_char_extents (MFrame *frame, MText *mt,
- MDrawMetric *array_return,
- MDrawMetric *overall_return)
+ MDrawMetric *array_return,
+ MDrawMetric *overall_return)
{
+ int n = mtext_nchars (mt);
+
+ mdraw_text_per_char_extents (frame, mt, 0, n, NULL, array_return, NULL,
+ n, &n, overall_return, NULL);
}
/***en