/* Special categories */
static MSymbol McatCc, McatCf;
-static MSymbol Mdepth;
-
\f
/* Glyph-string composer. */
int pos;
MSymbol language = Mnil, script = Mnil, charset = 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;
if (c < 0x100)
{
+ /* Short cut for the obvious case. */
+ g_tmp.category = Mnil;
if (c == ' ' || c == '\n' || c == '\t')
g_tmp.type = GLYPH_SPACE, this_script = Mnil;
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)
+ /* Search forward for a character that explicitly
+ specifies a script. */
+ for (i = pos + 1; i < to; i++)
+ {
+ int c1 = mtext_ref_char (mt, i);
+ MSymbol sym = ((c1 > 0x20 && c1 < 0x100) ? Mlatin
+ : mchar_get_prop (c1, Mscript));
+
+ if (sym != Minherited && sym != Mnil)
+ {
+ 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_CHAR)
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 (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 = '^';
+ g_tmp.c = '^';
APPEND_GLYPH (gstring, g_tmp);
if (c < ' ')
- g_tmp.code = g_tmp.c + 0x40;
+ g_tmp.c = c + 0x40;
else
- g_tmp.code = '?';
+ g_tmp.c = '?';
}
APPEND_GLYPH (gstring, g_tmp);
if (c == '\n'
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);
}
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)
{
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);
+ (*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)
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;
}
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;
}
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)
}
M17N_OBJECT_UNREF (gstring->top);
- return 1;
+ return 0;
}
/*=*/
}
info->from = g->pos;
info->to = g->to;
+ info->glyph_code = g->code;
info->this.x = g->lbearing;
info->this.y = - gstring->line_ascent;
info->this.height = gstring->height;
+ info->this.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->this.width += g->width, info->logical_width += (g++)->width);
+ info->this.width += g[-1].rbearing - g[-1].width;
if (g->type != GLYPH_ANCHOR)
info->right_from = g->pos, info->right_to = g->to;
/*=*/
+int
+mdraw_glyph_list (MFrame *frame, MText *mt, int from, int to,
+ MDrawControl *control, MDrawGlyphInfo *info,
+ int array_size, int *num_glyphs_return)
+{
+ MGlyphString *gstring;
+ MGlyph *g;
+ int n;
+
+ 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 (n < array_size)
+ {
+ info->from = g->pos;
+ info->to = g->to;
+ info->glyph_code = (g->type == GLYPH_CHAR ? g->code : 0);
+ info->x = g->xoff;
+ info->y = g->yoff;
+ info->this.x = g->lbearing;
+ info->this.y = - g->ascent;
+ info->this.height = g->ascent + g->descent;
+ info->this.width = g->rbearing - g->lbearing;
+ info->logical_width = g->width;
+ if (g->rface->rfont)
+ info->font = &g->rface->rfont->font;
+ else
+ info->font = NULL;
+ info++;
+ }
+ n++;
+ }
+ M17N_OBJECT_UNREF (gstring->top);
+
+ *num_glyphs_return = n;
+ return (n <= array_size ? 0 : -1);
+}
+
+/*=*/
+
/***en
@brief Draw one or more textitems.
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