more work on textblock. the api as it stands is now complete enough for all
things you might need textblock for for now - need to handle in-text anchors, tabs, margins and styles. SVN revision: 13402
This commit is contained in:
parent
1b696a9abb
commit
8d73bc7292
|
@ -465,6 +465,7 @@ extern "C" {
|
|||
EAPI Evas_Format_Direction evas_object_textblock_format_direction_get (Evas_Object *obj);
|
||||
EAPI void evas_object_textblock_format_size_get (Evas_Object *obj, Evas_Coord *w, Evas_Coord *h);
|
||||
EAPI void evas_object_textblock_native_size_get (Evas_Object *obj, Evas_Coord *w, Evas_Coord *h);
|
||||
EAPI int evas_object_textblock_native_lines_get (Evas_Object *obj);
|
||||
|
||||
EAPI void evas_object_del (Evas_Object *obj);
|
||||
|
||||
|
|
|
@ -10,14 +10,11 @@
|
|||
*
|
||||
* things to add:
|
||||
*
|
||||
* * finish off current api where it is unfinished
|
||||
* * get native extents
|
||||
* * styles (outline, glow, etxra glow, shadow, soft shadow, etc.)
|
||||
* * if a word (or char) doesnt fit at all do something sensible
|
||||
* * anchors (to query text extents)
|
||||
* * anchors (for inline objects other than text - images etc.)
|
||||
* * tabs (indents)
|
||||
* * left and right margins
|
||||
* * get all the current format params at any point
|
||||
* * freeze thaw api
|
||||
*
|
||||
* tough ones:
|
||||
|
@ -128,7 +125,12 @@ struct _Evas_Object_Textblock
|
|||
struct {
|
||||
unsigned char dirty : 1;
|
||||
Evas_Coord w, h;
|
||||
} native, format;
|
||||
} format;
|
||||
struct {
|
||||
unsigned char dirty : 1;
|
||||
Evas_Coord w, h;
|
||||
int lines;
|
||||
} native;
|
||||
Evas_List *font_hold;
|
||||
void *engine_data;
|
||||
};
|
||||
|
@ -564,22 +566,29 @@ evas_object_textblock_layout_fonts_hold_clean(Evas_Object *obj)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
evas_object_textblock_layout_nodes_free(Evas_Object *obj, Layout_Node *lnodes)
|
||||
{
|
||||
while (lnodes)
|
||||
{
|
||||
Layout_Node *lnode;
|
||||
|
||||
lnode = (Layout_Node *)lnodes;
|
||||
lnodes = evas_object_list_remove(lnodes, lnode);
|
||||
evas_object_textblock_layout_clear(obj, &lnode->layout);
|
||||
if (lnode->text) free(lnode->text);
|
||||
free(lnode);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
evas_object_textblock_layout_clean(Evas_Object *obj)
|
||||
{
|
||||
Evas_Object_Textblock *o;
|
||||
|
||||
o = (Evas_Object_Textblock *)(obj->object_data);
|
||||
while (o->layout_nodes)
|
||||
{
|
||||
Layout_Node *lnode;
|
||||
|
||||
lnode = (Layout_Node *)o->layout_nodes;
|
||||
o->layout_nodes = evas_object_list_remove(o->layout_nodes, lnode);
|
||||
evas_object_textblock_layout_clear(obj, &lnode->layout);
|
||||
if (lnode->text) free(lnode->text);
|
||||
free(lnode);
|
||||
}
|
||||
evas_object_textblock_layout_nodes_free(obj, o->layout_nodes);
|
||||
o->layout_nodes = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -637,23 +646,18 @@ evas_object_textblock_char_is_white(int c)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
evas_object_textblock_layout(Evas_Object *obj)
|
||||
static Layout_Node *
|
||||
evas_object_textblock_layout_internal(Evas_Object *obj, int w, int h, int *format_w, int *format_h, int *line_count)
|
||||
{
|
||||
Evas_Object_Textblock *o;
|
||||
Layout layout;
|
||||
Evas_Object_List *l, *ll;
|
||||
Evas_Coord w, h;
|
||||
Evas_Object_List *l, *ll, *layout_nodes = NULL;
|
||||
Layout_Node *line_start = NULL;
|
||||
int text_pos = 0, fh = 0, last_mdescent = 0, line = 0, last_line = 0;
|
||||
int text_pos = 0, fw = 0, fh = 0, last_mdescent = 0, line = 0, last_line = 0;
|
||||
int last_line_underline = 0, last_line_double_underline = 0;
|
||||
|
||||
o = (Evas_Object_Textblock *)(obj->object_data);
|
||||
evas_object_textblock_layout_init(&layout);
|
||||
w = obj->cur.geometry.w;
|
||||
h = obj->cur.geometry.h;
|
||||
o->last_w = w;
|
||||
o->last_h = h;
|
||||
/* format width is object width */
|
||||
// printf("RE-LAYOUT %ix%i!\n", w, h);
|
||||
for (l = (Evas_Object_List *)o->nodes; l; l = l->next)
|
||||
|
@ -745,9 +749,14 @@ evas_object_textblock_layout(Evas_Object *obj)
|
|||
layout.line.descent = descent;
|
||||
if (layout.line.mascent < ascent) layout.line.mascent = ascent;
|
||||
if (layout.line.mdescent < descent) layout.line.mdescent = descent;
|
||||
if (font) chrpos = ENFN->font_char_at_coords_get(ENDT, font, text,
|
||||
w - layout.line.x, 0,
|
||||
&cx, &cy, &cw, &ch);
|
||||
if (w > 0)
|
||||
{
|
||||
if (font) chrpos = ENFN->font_char_at_coords_get(ENDT, font, text,
|
||||
w - layout.line.x, 0,
|
||||
&cx, &cy, &cw, &ch);
|
||||
}
|
||||
else
|
||||
chrpos = -1;
|
||||
/* if the text fits... just add */
|
||||
if (chrpos < 0)
|
||||
{
|
||||
|
@ -760,11 +769,13 @@ evas_object_textblock_layout(Evas_Object *obj)
|
|||
lnode->text_pos = text_pos;
|
||||
text_pos += lnode->text_len;
|
||||
if (font) hadvance = ENFN->font_h_advance_get(ENDT, font, text);
|
||||
o->layout_nodes = evas_object_list_append(o->layout_nodes, lnode);
|
||||
layout_nodes = evas_object_list_append(layout_nodes, lnode);
|
||||
/* and advance */
|
||||
/* fix up max ascent/descent for the line */
|
||||
adj = (double)(w - (lnode->layout.line.x + tw + layout.line.inset)) * layout.align;
|
||||
adj -= line_start->layout.line.x;
|
||||
if ((layout.line.x + hadvance) > fw)
|
||||
fw = layout.line.x + hadvance;
|
||||
layout.line.x += hadvance;
|
||||
lnode->layout.line.advance = hadvance;
|
||||
for (ll = l->next; ll; ll = ll->next)
|
||||
|
@ -865,7 +876,7 @@ evas_object_textblock_layout(Evas_Object *obj)
|
|||
lnode->w = tw;
|
||||
lnode->h = th;
|
||||
lnode->layout.line.advance = hadvance;
|
||||
o->layout_nodes = evas_object_list_append(o->layout_nodes, lnode);
|
||||
layout_nodes = evas_object_list_append(layout_nodes, lnode);
|
||||
adj = (double)(w - (lnode->layout.line.x + tw + layout.line.inset)) * layout.align;
|
||||
adj -= line_start->layout.line.x;
|
||||
for (ll = (Evas_Object_List *)lnode; ll; ll = ll->prev)
|
||||
|
@ -903,8 +914,9 @@ evas_object_textblock_layout(Evas_Object *obj)
|
|||
}
|
||||
breakout:
|
||||
evas_object_textblock_layout_clear(obj, &layout);
|
||||
o->lines = last_line + 1;
|
||||
o->format.w = w;
|
||||
*line_count = last_line + 1;
|
||||
if (w > 0) *format_w = w;
|
||||
else *format_w = fw;
|
||||
if (last_line_double_underline)
|
||||
{
|
||||
if (last_mdescent < 3) fh += 3 - last_mdescent;
|
||||
|
@ -913,7 +925,24 @@ evas_object_textblock_layout(Evas_Object *obj)
|
|||
{
|
||||
if (last_mdescent < 1) fh += 1 - last_mdescent;
|
||||
}
|
||||
*format_h = fh;
|
||||
}
|
||||
|
||||
static void
|
||||
evas_object_textblock_layout(Evas_Object *obj)
|
||||
{
|
||||
Evas_Object_Textblock *o;
|
||||
int w, h, fw = 0, fh = 0, lines = 0;
|
||||
|
||||
o = (Evas_Object_Textblock *)(obj->object_data);
|
||||
w = obj->cur.geometry.w;
|
||||
h = obj->cur.geometry.h;
|
||||
o->last_w = w;
|
||||
o->last_h = h;
|
||||
o->layout_nodes = evas_object_textblock_layout_internal(obj, w, h, &fw, &fh, &lines);
|
||||
o->format.w = fw;
|
||||
o->format.h = fh;
|
||||
o->lines = lines;
|
||||
o->format.dirty = 0;
|
||||
}
|
||||
|
||||
|
@ -934,9 +963,15 @@ evas_object_textblock_native_calc(Evas_Object *obj)
|
|||
{
|
||||
Evas_Object_Textblock *o;
|
||||
Layout layout;
|
||||
int fw = 0, fh = 0, lines = 0;
|
||||
Layout_Node *lnodes;
|
||||
|
||||
o = (Evas_Object_Textblock *)(obj->object_data);
|
||||
/* FIXME: takes nodes and produce layotu nodes ignoring object size */
|
||||
lnodes = evas_object_textblock_layout_internal(obj, 0, 0, &fw, &fh, &lines);
|
||||
evas_object_textblock_layout_nodes_free(obj, lnodes);
|
||||
o->native.w = fw;
|
||||
o->native.h = fh;
|
||||
o->native.lines = lines;
|
||||
}
|
||||
|
||||
static Node *
|
||||
|
@ -2182,6 +2217,8 @@ char *
|
|||
evas_object_textblock_current_format_get(Evas_Object *obj)
|
||||
{
|
||||
Evas_Object_Textblock *o;
|
||||
Layout_Node *lnode;
|
||||
int ps;
|
||||
|
||||
MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
|
||||
return NULL;
|
||||
|
@ -2190,7 +2227,146 @@ evas_object_textblock_current_format_get(Evas_Object *obj)
|
|||
MAGIC_CHECK(o, Evas_Object_Textblock, MAGIC_OBJ_TEXTBLOCK);
|
||||
return NULL;
|
||||
MAGIC_CHECK_END();
|
||||
/* FIXME: DO */
|
||||
if (o->format.dirty)
|
||||
evas_object_textblock_format_calc(obj);
|
||||
lnode = evas_object_textblock_layout_node_pos_get(obj, o->pos, &ps);
|
||||
if (lnode)
|
||||
{
|
||||
char tbuf[512];
|
||||
char *buf;
|
||||
int sz;
|
||||
|
||||
sz = 0;
|
||||
/* save typing below */
|
||||
#define CHECK_COL(str, col) \
|
||||
if (lnode->layout.col.a > 0) \
|
||||
{ \
|
||||
snprintf(tbuf, sizeof(tbuf), "#02x02x02x02x", lnode->layout.col.r, lnode->layout.col.g, lnode->layout.col.b, lnode->layout.col.a); \
|
||||
sz += strlen(str"=") + strlen(tbuf) + 1; \
|
||||
}
|
||||
/* FIXME: we dont handle any strings with a space in them */
|
||||
if (lnode->layout.font.name) sz += strlen("font=") + strlen(lnode->layout.font.name) + 1;
|
||||
if (lnode->layout.font.source) sz += strlen("source=") + strlen(lnode->layout.font.source) + 1;
|
||||
if (lnode->layout.font.size > 0)
|
||||
{
|
||||
snprintf(tbuf, sizeof(tbuf), "%i", (int)lnode->layout.font.size);
|
||||
sz += strlen("size=") + strlen(tbuf) + 1;
|
||||
}
|
||||
CHECK_COL("color", color);
|
||||
CHECK_COL("underline_color", underline_color);
|
||||
CHECK_COL("double_underline_color", double_underline_color);
|
||||
CHECK_COL("outline_color", outline_color);
|
||||
CHECK_COL("shadow_color", shadow_color);
|
||||
CHECK_COL("glow_color", glow_color);
|
||||
CHECK_COL("outer_glow_color", outer_glow_color);
|
||||
CHECK_COL("backing_color", backing_color);
|
||||
CHECK_COL("strikethrough_color", strikethrough_color);
|
||||
if (lnode->layout.align != 0.0)
|
||||
{
|
||||
if (lnode->layout.align == 0.5) strcpy(tbuf, "center");
|
||||
else if (lnode->layout.align == 1.0) strcpy(tbuf, "right");
|
||||
else snprintf(tbuf, sizeof(tbuf), "%3.3f", (double)lnode->layout.align);
|
||||
sz += strlen("align=") + strlen(tbuf) + 1;
|
||||
}
|
||||
if (lnode->layout.valign != -1.0)
|
||||
{
|
||||
if (lnode->layout.valign == 0.5) strcpy(tbuf, "center");
|
||||
else if (lnode->layout.valign == 1.0) strcpy(tbuf, "bottom");
|
||||
else snprintf(tbuf, sizeof(tbuf), "%3.3f", (double)lnode->layout.valign);
|
||||
sz += strlen("valign=") + strlen(tbuf) + 1;
|
||||
}
|
||||
if (lnode->layout.word_wrap) sz += strlen("wrap=word") + 1;
|
||||
if (lnode->layout.second_underline) sz += strlen("underline=double") + 1;
|
||||
else if (lnode->layout.underline) sz += strlen("underline=on") + 1;
|
||||
if (lnode->layout.strikethrough) sz += strlen("strikethrough=on") + 1;
|
||||
if (lnode->layout.backing) sz += strlen("backing=on") + 1;
|
||||
|
||||
#define PRINT_COL(str, col) \
|
||||
if (lnode->layout.col.a > 0) \
|
||||
{ \
|
||||
if (buf[0] != 0) strcat(buf, " "); \
|
||||
strcat(buf, str"="); \
|
||||
snprintf(tbuf, sizeof(tbuf), "#02x02x02x02x", lnode->layout.col.r, lnode->layout.col.g, lnode->layout.col.b, lnode->layout.col.a); \
|
||||
strcat(buf, tbuf); \
|
||||
}
|
||||
|
||||
buf = malloc(sz);
|
||||
if (buf)
|
||||
{
|
||||
buf[0] = 0;
|
||||
if (lnode->layout.font.name)
|
||||
{
|
||||
strcat(buf, "font=");
|
||||
strcat(buf, lnode->layout.font.name);
|
||||
}
|
||||
if (lnode->layout.font.source)
|
||||
{
|
||||
if (buf[0] != 0) strcat(buf, " ");
|
||||
strcat(buf, "source=");
|
||||
strcat(buf, lnode->layout.font.source);
|
||||
}
|
||||
if (lnode->layout.font.size > 0)
|
||||
{
|
||||
if (buf[0] != 0) strcat(buf, " ");
|
||||
strcat(buf, "size=");
|
||||
snprintf(tbuf, sizeof(tbuf), "%i", (int)lnode->layout.font.size);
|
||||
strcat(buf, tbuf);
|
||||
}
|
||||
PRINT_COL("color", color);
|
||||
PRINT_COL("underline_color", underline_color);
|
||||
PRINT_COL("double_underline_color", double_underline_color);
|
||||
PRINT_COL("outline_color", outline_color);
|
||||
PRINT_COL("shadow_color", shadow_color);
|
||||
PRINT_COL("glow_color", glow_color);
|
||||
PRINT_COL("outer_glow_color", outer_glow_color);
|
||||
PRINT_COL("backing_color", backing_color);
|
||||
PRINT_COL("strikethrough_color", strikethrough_color);
|
||||
if (lnode->layout.align != 0.0)
|
||||
{
|
||||
if (lnode->layout.align == 0.5) strcpy(tbuf, "center");
|
||||
else if (lnode->layout.align == 1.0) strcpy(tbuf, "right");
|
||||
else snprintf(tbuf, sizeof(tbuf), "%3.3f", (double)lnode->layout.align);
|
||||
if (buf[0] != 0) strcat(buf, " ");
|
||||
strcat(buf, "align=");
|
||||
strcat(buf, tbuf);
|
||||
}
|
||||
if (lnode->layout.valign != -1.0)
|
||||
{
|
||||
if (lnode->layout.valign == 0.5) strcpy(tbuf, "center");
|
||||
else if (lnode->layout.valign == 1.0) strcpy(tbuf, "bottom");
|
||||
else snprintf(tbuf, sizeof(tbuf), "%3.3f", (double)lnode->layout.valign);
|
||||
if (buf[0] != 0) strcat(buf, " ");
|
||||
strcat(buf, "valign=");
|
||||
strcat(buf, tbuf);
|
||||
}
|
||||
if (lnode->layout.word_wrap)
|
||||
{
|
||||
if (buf[0] != 0) strcat(buf, " ");
|
||||
strcat(buf, "wrap=word");
|
||||
}
|
||||
if (lnode->layout.second_underline)
|
||||
{
|
||||
if (buf[0] != 0) strcat(buf, " ");
|
||||
strcat(buf, "underline=double");
|
||||
}
|
||||
else if (lnode->layout.underline)
|
||||
{
|
||||
if (buf[0] != 0) strcat(buf, " ");
|
||||
strcat(buf, "underline=on");
|
||||
}
|
||||
if (lnode->layout.strikethrough)
|
||||
{
|
||||
if (buf[0] != 0) strcat(buf, " ");
|
||||
strcat(buf, "strikethrough=on");
|
||||
}
|
||||
if (lnode->layout.backing)
|
||||
{
|
||||
if (buf[0] != 0) strcat(buf, " ");
|
||||
strcat(buf, "backing=on");
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
/* so what do we do eh? do we return 1 string with all "stateful" format
|
||||
* data in it (font, size, color, underline etc.) space delimited... or
|
||||
* what? i am tempted to opt for this solution right now - caller must
|
||||
|
@ -2278,15 +2454,28 @@ evas_object_textblock_native_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coor
|
|||
return;
|
||||
MAGIC_CHECK_END();
|
||||
if (o->native.dirty)
|
||||
{
|
||||
/* FIXME: DO */
|
||||
evas_object_textblock_native_calc(obj);
|
||||
o->native.dirty = 0;
|
||||
}
|
||||
evas_object_textblock_native_calc(obj);
|
||||
if (w) *w = o->native.w;
|
||||
if (h) *h = o->native.h;
|
||||
}
|
||||
|
||||
int
|
||||
evas_object_textblock_native_lines_get(Evas_Object *obj)
|
||||
{
|
||||
Evas_Object_Textblock *o;
|
||||
|
||||
MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
|
||||
return 0;
|
||||
MAGIC_CHECK_END();
|
||||
o = (Evas_Object_Textblock *)(obj->object_data);
|
||||
MAGIC_CHECK(o, Evas_Object_Textblock, MAGIC_OBJ_TEXTBLOCK);
|
||||
return 0;
|
||||
MAGIC_CHECK_END();
|
||||
if (o->native.dirty)
|
||||
evas_object_textblock_native_calc(obj);
|
||||
return o->native.lines;
|
||||
}
|
||||
|
||||
/* all nice and private */
|
||||
static void
|
||||
evas_object_textblock_init(Evas_Object *obj)
|
||||
|
|
Loading…
Reference in New Issue