From b6722837022dcb9eee786018622525fc26883055 Mon Sep 17 00:00:00 2001 From: Carsten Haitzler Date: Fri, 9 Sep 2005 14:19:06 +0000 Subject: [PATCH] tb2 work! :) SVN revision: 16671 --- legacy/evas/src/lib/Evas.h | 20 +- .../src/lib/canvas/evas_object_textblock.c | 316 +++++++++++++++++- .../src/lib/engines/common/evas_font_query.c | 17 +- 3 files changed, 335 insertions(+), 18 deletions(-) diff --git a/legacy/evas/src/lib/Evas.h b/legacy/evas/src/lib/Evas.h index 82dc9c291a..e4851c8e0f 100644 --- a/legacy/evas/src/lib/Evas.h +++ b/legacy/evas/src/lib/Evas.h @@ -463,8 +463,14 @@ extern "C" { /* NEW texblock api - intended to replace the old - not complete yet */ - typedef struct _Evas_Textblock_Style Evas_Textblock_Style; - typedef struct _Evas_Textblock_Cursor Evas_Textblock_Cursor; + typedef struct _Evas_Textblock_Style Evas_Textblock_Style; + typedef struct _Evas_Textblock_Cursor Evas_Textblock_Cursor; + typedef struct _Evas_Textblock_Rectangle Evas_Textblock_Rectangle; + + struct _Evas_Textblock_Rectangle + { + Evas_Coord x, y, w, h; + }; EAPI Evas_Object *evas_object_textblock2_add(Evas *e); @@ -505,16 +511,20 @@ extern "C" { EAPI void evas_textblock2_cursor_format_append(Evas_Textblock_Cursor *cur, const char *format); EAPI void evas_textblock2_cursor_format_prepend(Evas_Textblock_Cursor *cur, const char *format); - /* FIXME: add node delete, cursor delete, range delete */ + EAPI void evas_textblock2_cursor_node_delete(Evas_Textblock_Cursor *cur); + EAPI void evas_textblock2_cursor_char_delete(Evas_Textblock_Cursor *cur); + EAPI void evas_textblock2_cursor_range_delete(Evas_Textblock_Cursor *cur1, Evas_Textblock_Cursor *cur2); EAPI const char *evas_textblock2_cursor_node_text_get(Evas_Textblock_Cursor *cur); EAPI const char *evas_textblock2_cursor_node_format_get(Evas_Textblock_Cursor *cur); - /* FIXME: add text range get */ + EAPI char *evas_textblock2_cursor_range_text_get(Evas_Textblock_Cursor *cur1, Evas_Textblock_Cursor *cur2); EAPI int evas_textblock2_cursor_char_geometry_get(Evas_Textblock_Cursor *cur, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch); EAPI int evas_textblock2_cursor_line_geometry_get(Evas_Textblock_Cursor *cur, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch); EAPI Evas_Bool evas_textblock2_cursor_char_coord_set(Evas_Textblock_Cursor *cur, Evas_Coord x, Evas_Coord y); - + EAPI int evas_textblock2_cursor_line_coord_set(Evas_Textblock_Cursor *cur, Evas_Coord y); + EAPI Evas_List *evas_textblock2_cursor_range_geometry_get(Evas_Textblock_Cursor *cur1, Evas_Textblock_Cursor *cur2); + EAPI Evas_Bool evas_object_textblock2_line_number_geometry_get(Evas_Object *obj, int line, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch); EAPI void evas_object_textblock2_clear(Evas_Object *obj); EAPI void evas_object_textblock2_size_formatted_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h); diff --git a/legacy/evas/src/lib/canvas/evas_object_textblock.c b/legacy/evas/src/lib/canvas/evas_object_textblock.c index dc413955ac..e5fc7915e3 100644 --- a/legacy/evas/src/lib/canvas/evas_object_textblock.c +++ b/legacy/evas/src/lib/canvas/evas_object_textblock.c @@ -138,10 +138,10 @@ struct _Evas_Object_Textblock Evas_Textblock_Cursor *cursor; Evas_List *cursors; Evas_Object_Textblock_Node *nodes; - Evas_Object_Textblock_Line *lines; - int last_w; + Evas_Object_Textblock_Line *lines; + int last_w; struct { - int l, r, t, b; + int l, r, t, b; } style_pad; char *markup_text; char changed : 1; @@ -357,12 +357,23 @@ _strbuf_insert(char *s, char *s2, int pos, int *len, int *alloc) static char * _strbuf_remove(char *s, int p, int p2, int *len, int *alloc) { -/* int l2; int tlen; + char *tbuf; - tlen = *len + l2; - if (tlen > *alloc) + if ((p == 0) && (p2 == *len)) + { + free(s); + *len = 0; + *alloc = 0; + return NULL; + } + tbuf = malloc(*len - p2 + 1); + strcpy(tbuf, s + p2); + strcpy(s + p, tbuf); + free(tbuf); + tlen = *len - (p2 - p); + if (tlen < ((*alloc >> 5) << 15)) { char *ts; int talloc; @@ -373,11 +384,7 @@ _strbuf_remove(char *s, int p, int p2, int *len, int *alloc) s = ts; *alloc = talloc; } - strncpy(s + pos + l2, s + pos, *len - pos); - strncpy(s + pos, s2, l2); *len = tlen; - s[tlen] = 0; - */ return s; } @@ -2482,6 +2489,7 @@ evas_object_textblock2_text_markup_set(Evas_Object *obj, const char *text) } o->markup_text = strdup(text); } + /* FIXME: adjust cursors that are affected by the change */ } const char * @@ -2880,6 +2888,7 @@ evas_textblock2_cursor_compare(Evas_Textblock_Cursor *cur1, Evas_Textblock_Curso Evas_Object_List *l1, *l2; if (!cur1) return 0; + if (!cur2) return 0; if (cur1->obj != cur2->obj) return 0; if ((!cur1->node) || (!cur2->node)) return 0; if (cur1->node == cur2->node) @@ -2946,6 +2955,7 @@ evas_textblock2_cursor_text_append(Evas_Textblock_Cursor *cur, const char *text) o->native.valid = 0; o->changed = 1; evas_object_change(cur->obj); + /* FIXME: adjust cursors that are affected by the change */ } void @@ -2975,6 +2985,7 @@ evas_textblock2_cursor_text_prepend(Evas_Textblock_Cursor *cur, const char *text o->native.valid = 0; o->changed = 1; evas_object_change(cur->obj); + /* FIXME: adjust cursors that are affected by the change */ } void @@ -3035,6 +3046,7 @@ evas_textblock2_cursor_format_append(Evas_Textblock_Cursor *cur, const char *for o->native.valid = 0; o->changed = 1; evas_object_change(cur->obj); + /* FIXME: adjust cursors that are affected by the change */ } void @@ -3090,6 +3102,168 @@ evas_textblock2_cursor_format_prepend(Evas_Textblock_Cursor *cur, const char *fo o->native.valid = 0; o->changed = 1; evas_object_change(cur->obj); + /* FIXME: adjust cursors that are affected by the change */ +} + +void +evas_textblock2_cursor_node_delete(Evas_Textblock_Cursor *cur) +{ + Evas_Object_Textblock *o; + Evas_Object_Textblock_Node *n, *n2; + + if (!cur) return; + o = (Evas_Object_Textblock *)(cur->obj->object_data); + n = cur->node; + n2 = (Evas_Object_Textblock_Node *)(((Evas_Object_List *)n)->next); + if (n2) + { + cur->node = n2; + cur->pos = 0; + } + else + { + n2 = (Evas_Object_Textblock_Node *)(((Evas_Object_List *)n)->prev); + cur->node = n2; + cur->pos = 0; + evas_textblock2_cursor_char_last(cur); + } + + o->nodes = evas_object_list_remove(o->nodes, n); + if (n->text) free(n->text); + free(n); + + o->formatted.valid = 0; + o->native.valid = 0; + o->changed = 1; + evas_object_change(cur->obj); + /* FIXME: adjust cursors that are affected by the change */ +} + +void +evas_textblock2_cursor_char_delete(Evas_Textblock_Cursor *cur) +{ + Evas_Object_Textblock *o; + Evas_Object_Textblock_Node *n, *n2; + int chr, index; + + if (!cur) return; + o = (Evas_Object_Textblock *)(cur->obj->object_data); + n = cur->node; + if (n->type == NODE_FORMAT) + { + evas_textblock2_cursor_node_delete(cur); + return; + } + index = cur->pos; + chr = evas_common_font_utf8_get_next((unsigned char *)n->text, &index); + if (chr == 0) return; + n->text = _strbuf_remove(n->text, cur->pos, index, &(n->len), &(n->alloc)); + if (!n->text) + { + evas_textblock2_cursor_node_delete(cur); + return; + } + if (cur->pos == n->len) + { + n2 = (Evas_Object_Textblock_Node *)(((Evas_Object_List *)n)->next); + if (n2) + { + cur->node = n2; + cur->pos = 0; + } + else + { + cur->pos = 0; + evas_textblock2_cursor_char_last(cur); + } + } + + o->formatted.valid = 0; + o->native.valid = 0; + o->changed = 1; + evas_object_change(cur->obj); + /* FIXME: adjust cursors that are affected by the change */ +} + +void +evas_textblock2_cursor_range_delete(Evas_Textblock_Cursor *cur1, Evas_Textblock_Cursor *cur2) +{ + Evas_Object_Textblock *o; + Evas_Object_Textblock_Node *n1, *n2, *n; + Evas_Object_List *l; + + int chr, index; + + if (!cur1) return; + if (!cur2) return; + if (cur1->obj != cur2->obj) return; + o = (Evas_Object_Textblock *)(cur1->obj->object_data); + if (evas_textblock2_cursor_compare(cur1, cur2) > 0) + { + Evas_Textblock_Cursor *tc; + + tc = cur1; + cur1 = cur2; + cur2 = tc; + } + n1 = cur1->node; + n2 = cur2->node; + index = cur2->pos; + chr = evas_common_font_utf8_get_next((unsigned char *)n2->text, &index); + if (chr == 0) return; + if (n1 == n2) + { + if (cur1->pos == cur2->pos) + { + evas_textblock2_cursor_char_delete(cur1); + return; + } + n1->text = _strbuf_remove(n1->text, cur1->pos, index, &(n->len), &(n->alloc)); + if (!n1->text) + { + evas_textblock2_cursor_node_delete(cur1); + return; + } + if (cur1->pos == n1->len) + { + n2 = (Evas_Object_Textblock_Node *)(((Evas_Object_List *)n1)->next); + if (n2) + { + cur1->node = n2; + cur1->pos = 0; + } + else + { + cur1->pos = 0; + evas_textblock2_cursor_char_last(cur1); + } + } + } + else + { + Evas_List *removes = NULL; + + n1->text = _strbuf_remove(n1->text, cur1->pos, index, &(n->len), &(n->alloc)); + for (l = ((Evas_Object_List *)n1)->next; l != (Evas_Object_List *)n2; l = l->next) + removes = evas_list_append(removes, l); + while (removes) + { + n = removes->data; + o->nodes = evas_object_list_remove(o->nodes, n); + if (n->text) free(n->text); + free(n); + removes = evas_list_remove_list(removes, removes); + } + if (!n1->text) + evas_textblock2_cursor_node_delete(cur1); + if (!n2->text) + evas_textblock2_cursor_node_delete(cur2); + } + o->formatted.valid = 0; + o->native.valid = 0; + o->changed = 1; + evas_object_change(cur1->obj); + /* FIXME: adjust cursors that are affected by the change */ } const char * @@ -3116,6 +3290,30 @@ evas_textblock2_cursor_node_format_get(Evas_Textblock_Cursor *cur) return NULL; } +char * +evas_textblock2_cursor_range_text_get(Evas_Textblock_Cursor *cur1, Evas_Textblock_Cursor *cur2) +{ + Evas_Object_Textblock *o; + Evas_Object_Textblock_Node *n1, *n2; + + if (!cur1) return NULL; + if (!cur2) return NULL; + if (cur1->obj != cur2->obj) return NULL; + o = (Evas_Object_Textblock *)(cur1->obj->object_data); + if (evas_textblock2_cursor_compare(cur1, cur2) > 0) + { + Evas_Textblock_Cursor *tc; + + tc = cur1; + cur1 = cur2; + cur2 = tc; + } + n1 = cur1->node; + n2 = cur2->node; + /* FIXME: */ + return NULL; +} + int evas_textblock2_cursor_char_geometry_get(Evas_Textblock_Cursor *cur, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch) { @@ -3144,6 +3342,11 @@ evas_textblock2_cursor_char_geometry_get(Evas_Textblock_Cursor *cur, Evas_Coord &x, &y, &w, &h); if (ret <= 0) return -1; x = ln->x + it->x - it->inset + x; + if (x < ln->x) + { + x = ln->x; + w -= (ln->x - x); + } y = ln->y; h = ln->h; } @@ -3205,6 +3408,8 @@ evas_textblock2_cursor_char_coord_set(Evas_Textblock_Cursor *cur, Evas_Coord x, if (!cur) return 0; o = (Evas_Object_Textblock *)(cur->obj->object_data); if (!o->formatted.valid) _relayout(cur->obj); + x += o->style_pad.l; + y += o->style_pad.t; for (l = (Evas_Object_List *)o->lines; l; l = l->next) { Evas_Object_Textblock_Line *ln; @@ -3261,6 +3466,96 @@ evas_textblock2_cursor_char_coord_set(Evas_Textblock_Cursor *cur, Evas_Coord x, return 0; } +int +evas_textblock2_cursor_line_coord_set(Evas_Textblock_Cursor *cur, Evas_Coord y) +{ + Evas_Object_Textblock *o; + Evas_Object_List *l; + Evas_Object_Textblock_Line *ln = NULL; + + if (!cur) return -1; + o = (Evas_Object_Textblock *)(cur->obj->object_data); + if (!o->formatted.valid) _relayout(cur->obj); + y += o->style_pad.t; + for (l = (Evas_Object_List *)o->lines; l; l = l->next) + { + Evas_Object_Textblock_Line *ln; + + ln = (Evas_Object_Textblock_Line *)l; + if (ln->y > y) break; + if ((ln->y <= y) && ((ln->y + ln->h) > y)) + { + evas_textblock2_cursor_line_set(cur, ln->line_no); + return ln->line_no; + } + } + return -1; +} + +Evas_List * +evas_textblock2_cursor_range_geometry_get(Evas_Textblock_Cursor *cur1, Evas_Textblock_Cursor *cur2) +{ + Evas_Object_Textblock *o; + Evas_List *rects = NULL; + Evas_Coord cx, cy, cw, ch, lx, ly, lw, lh; + Evas_Textblock_Rectangle *tr; + int i, line, line2; + + if (!cur1) return NULL; + if (!cur2) return NULL; + if (cur1->obj != cur2->obj) return NULL; + o = (Evas_Object_Textblock *)(cur1->obj->object_data); + if (evas_textblock2_cursor_compare(cur1, cur2) > 0) + { + Evas_Textblock_Cursor *tc; + + tc = cur1; + cur1 = cur2; + cur2 = tc; + } + line = evas_textblock2_cursor_char_geometry_get(cur1, &cx, &cy, &cw, &ch); + line = evas_textblock2_cursor_line_geometry_get(cur1, &lx, &ly, &lw, &lh); + line2 = evas_textblock2_cursor_line_geometry_get(cur2, NULL, NULL, NULL, NULL); + if (line == line2) + { + tr = calloc(1, sizeof(Evas_Textblock_Rectangle)); + rects = evas_list_append(rects, tr); + tr->x = cx; + tr->y = ly; + tr->h = lh; + line = evas_textblock2_cursor_char_geometry_get(cur2, &cx, &cy, &cw, &ch); + tr->w = cx + cw - tr->x; + } + else + { + tr = calloc(1, sizeof(Evas_Textblock_Rectangle)); + rects = evas_list_append(rects, tr); + tr->x = cx; + tr->y = ly; + tr->h = lh; + tr->w = lx + lw - cx; + for (i = line +1; i < line2; i++) + { + evas_object_textblock2_line_number_geometry_get(cur1->obj, i, &lx, &ly, &lw, &lh); + tr = calloc(1, sizeof(Evas_Textblock_Rectangle)); + rects = evas_list_append(rects, tr); + tr->x = lx; + tr->y = ly; + tr->h = lh; + tr->w = lw; + } + line = evas_textblock2_cursor_char_geometry_get(cur2, &cx, &cy, &cw, &ch); + line = evas_textblock2_cursor_line_geometry_get(cur2, &lx, &ly, &lw, &lh); + tr = calloc(1, sizeof(Evas_Textblock_Rectangle)); + rects = evas_list_append(rects, tr); + tr->x = lx; + tr->y = ly; + tr->h = lh; + tr->w = cx + cw - lx; + } + return rects; +} + /* general controls */ Evas_Bool evas_object_textblock2_line_number_geometry_get(Evas_Object *obj, int line, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch) @@ -3308,6 +3603,7 @@ evas_object_textblock2_clear(Evas_Object *obj) o->native.valid = 0; o->changed = 1; evas_object_change(obj); + /* FIXME: adjust cursors that are affected by the change */ } void diff --git a/legacy/evas/src/lib/engines/common/evas_font_query.c b/legacy/evas/src/lib/engines/common/evas_font_query.c index acc5933e0a..b693151b6f 100644 --- a/legacy/evas/src/lib/engines/common/evas_font_query.c +++ b/legacy/evas/src/lib/engines/common/evas_font_query.c @@ -27,7 +27,7 @@ evas_common_font_query_size(RGBA_Font *fn, const char *text, int *w, int *h) FT_UInt index; RGBA_Font_Glyph *fg; int chr_x, chr_y, chr_w; - int gl; + int gl, kern; gl = evas_common_font_utf8_get_next((unsigned char *)text, &chr); if (gl == 0) break; @@ -35,6 +35,7 @@ evas_common_font_query_size(RGBA_Font *fn, const char *text, int *w, int *h) /* hmmm kerning means i can't sanely do my own cached metric tables! */ /* grrr - this means font face sharing is kinda... not an option if */ /* you want performance */ + kern = 0; if ((use_kerning) && (prev_index) && (index) && (pface == fi->src->ft.face)) { @@ -42,7 +43,10 @@ evas_common_font_query_size(RGBA_Font *fn, const char *text, int *w, int *h) if (FT_Get_Kerning(fi->src->ft.face, prev_index, index, ft_kerning_default, &delta) == 0) - pen_x += delta.x << 2; + { + kern = delta.x << 2; + pen_x += kern; + } } pface = fi->src->ft.face; fg = evas_common_font_int_cache_glyph_get(fi, index); @@ -50,7 +54,14 @@ evas_common_font_query_size(RGBA_Font *fn, const char *text, int *w, int *h) chr_x = (pen_x + (fg->glyph_out->left << 8)) >> 8; chr_y = (pen_y + (fg->glyph_out->top << 8)) >> 8; - chr_w = fg->glyph_out->bitmap.width; +// chr_w = fg->glyph_out->bitmap.width; + chr_w = fg->glyph_out->bitmap.width + (kern >> 8); + { + int advw; + + advw = ((fg->glyph->advance.x + (kern << 8)) >> 16); + if (chr_w < advw) chr_w = advw; + } if ((!prev_index) && (chr_x < 0)) start_x = chr_x;