i worked on a regionbuf set of code (exact rectangles). i THINK it has some

bugs... but its disabled right now and it didnt speed anything up :( but it's
there for perusal and later work anyway...


SVN revision: 13193
This commit is contained in:
Carsten Haitzler 2005-02-05 02:30:13 +00:00
parent 871a93a8d1
commit e79e53e35b
8 changed files with 512 additions and 24 deletions

View File

@ -344,6 +344,7 @@ loop(void)
printf("# EVAS BENCH: %3.3f\n", ((double)frames / (t - time_start)) / 60.0);
printf("#\n");
printf("####################################################\n");
exit(0);
for (i = 0; i < 16; i++) evas_object_del(p_s[i]);
for (i = 0; i < 2; i++) evas_object_del(p_i[i]);
for (i = 0; i < 16; i++) evas_object_del(p_t[i]);

View File

@ -15,7 +15,6 @@
* * strikethrough support
* * solid bg behind text
* * if a word (or char) doesnt fit at all do something sensible
* * layout nodes need to be able to give their source node and offset
* * styles (outline, glow, etxra glow, shadow, soft shadow, etc.)
* * anchors (to query text extents)
* * query text pos given object-relative co-ords
@ -69,9 +68,20 @@ struct _Layout
} font;
struct {
unsigned char r, g, b, a;
} color, underline_color, outline_color, shadow_color;
} color,
underline_color,
double_underline_color,
outline_color,
shadow_color,
glow_color,
outer_glow_color,
backing_color,
strikethrough_color
;
struct {
int inset, x, y, ascent, descent, mascent, mdescent;
int inset, x, y,
ascent, descent,
mascent, mdescent;
} line;
double align, valign;
unsigned char word_wrap : 1;
@ -96,6 +106,10 @@ struct _Layout_Node
Layout layout;
char *text; /* text data until the next node */
int w, h;
Node *source_node;
int source_pos;
unsigned char line_start : 1;
unsigned char line_end : 1;
};
struct _Evas_Object_Textblock
@ -130,18 +144,13 @@ evas_object_textblock_layout_init(Layout *layout)
layout->color.g = 255;
layout->color.b = 255;
layout->color.a = 255;
layout->underline_color.r = 255;
layout->underline_color.g = 255;
layout->underline_color.b = 255;
layout->underline_color.a = 255;
layout->outline_color.r = 255;
layout->outline_color.g = 255;
layout->outline_color.b = 255;
layout->outline_color.a = 255;
layout->shadow_color.r = 255;
layout->shadow_color.g = 255;
layout->shadow_color.b = 255;
layout->shadow_color.a = 255;
layout->underline_color = layout->color;
layout->double_underline_color = layout->color;
layout->outline_color = layout->color;
layout->shadow_color = layout->color;
layout->glow_color = layout->color;
layout->outer_glow_color = layout->color;
layout->strikethrough_color = layout->color;
layout->line.inset = 0;
layout->line.x = 0;
layout->line.y = 0;
@ -520,9 +529,11 @@ evas_object_textblock_layout(Evas_Object *obj)
Layout_Node *lnode;
Node *node;
/* FIXME: if we overflow then this would be punted to an overflow */
/* object instead */
/* FIXME: we cant do this - we need to be able to qury text
* overflow amounts */
/*
if (layout.line.y >= h) goto breakout;
*/
node = (Node *)l;
// printf("NODE: FMT:\"%s\" TXT:\"%s\"\n", node->format, node->text);
if (node->format)
@ -530,12 +541,14 @@ evas_object_textblock_layout(Evas_Object *obj)
/* first handle newline, tab etc. etc */
if (!strcmp(node->format, "\n"))
{
if (lnode)
lnode->line_end = 1;
layout.line.x = 0;
if ((layout.line.y + lnode->layout.line.mascent + lnode->layout.line.mdescent) > h)
if ((layout.line.y + layout.line.mascent + layout.line.mdescent) > h)
{
/* FIXME: this node would overflow to the next textblock */
}
layout.line.y += lnode->layout.line.mascent + lnode->layout.line.mdescent;
layout.line.y += layout.line.mascent + layout.line.mdescent;
}
else
evas_object_textblock_layout_format_modify(&layout, node->format);
@ -548,15 +561,22 @@ evas_object_textblock_layout(Evas_Object *obj)
void *font = NULL;
char *text;
int adj, lastnode;
int srcpos = 0;
text = strdup(node->text);
new_node:
/* FIXME: we cant do this - we need to be able to qury text
* overflow amounts */
/*
if (layout.line.y >= h)
{
free(text);
goto breakout;
}
*/
lnode = calloc(1, sizeof(Layout_Node));
lnode->source_node = node;
lnode->source_pos = srcpos;
evas_object_textblock_layout_copy(&layout, &(lnode->layout));
if (lnode->layout.font.name)
font = evas_font_load(obj->layer->evas, lnode->layout.font.name, lnode->layout.font.source, lnode->layout.font.size);
@ -569,6 +589,7 @@ evas_object_textblock_layout(Evas_Object *obj)
layout.line.mascent = 0;
layout.line.mdescent = 0;
line_start = lnode;
lnode->line_start = 1;
}
lnode->layout.font.font = font;
if (font) ascent = ENFN->font_max_ascent_get(ENDT, font);
@ -663,6 +684,7 @@ evas_object_textblock_layout(Evas_Object *obj)
text2 = strdup(text + chrpos);
lnode->text = text1;
free(text);
srcpos += chrpos;
text = text1;
if (font) ENFN->font_string_size_get(ENDT, font, text, &tw, &th);
lnode->w = tw;
@ -680,9 +702,10 @@ evas_object_textblock_layout(Evas_Object *obj)
lnode2->layout.line.mdescent = layout.line.mdescent;
if (ll == (Evas_Object_List *)line_start) break;
}
lnode->line_end = 1;
layout.line.inset = 0;
layout.line.x = 0;
if ((layout.line.y + lnode->layout.line.mascent + lnode->layout.line.mdescent) > h)
if ((layout.line.y + layout.line.mascent + layout.line.mdescent) > h)
{
/* FIXME: this node would overflow to the next textblock */
}

View File

@ -284,7 +284,7 @@ evas_engine_buffer_output_setup(int w,
}
re->tb = evas_common_tilebuf_new(w, h);
/* in preliminary tests 16x16 gave highest framerates */
evas_common_tilebuf_set_tile_size(re->tb, 16, 16);
evas_common_tilebuf_set_tile_size(re->tb, 16, 16);
return re;
}

View File

@ -46,6 +46,7 @@ evas_scale_main.c \
evas_scale_sample.c \
evas_scale_smooth.c \
evas_tiler.c \
evas_regionbuf.c \
evas_blend_ops.h
EXTRA_DIST = \

View File

@ -496,6 +496,47 @@ evas_common_draw_context_cutout_split(Cutout_Rect *in, Cutout_Rect *split)
return out;
}
return NULL;
#undef INX1
#undef INX2
#undef SPX1
#undef SPX2
#undef INY1
#undef INY2
#undef SPY1
#undef SPY2
#undef X1_IN
#undef X2_IN
#undef Y1_IN
#undef Y2_IN
#undef R_NEW
}
Cutout_Rect *
evas_common_draw_context_cutout_merge(Cutout_Rect *in, Cutout_Rect *merge)
{
/* 1 input rect, multiple out */
Cutout_Rect *out;
Cutout_Rect *r;
Evas_Object_List *l;
for (l = (Evas_Object_List *)in; l; l = l->next)
{
r = (Cutout_Rect *)l;
merge = evas_common_draw_context_cutouts_split(merge, r);
if (!merge) return in;
}
r = merge;
out = in;
while (r)
{
Cutout_Rect *r2;
r2 = r;
r = evas_object_list_remove(r, r);
out = evas_object_list_append(out, r2);
}
return out;
}
Gfx_Func_Blend_Src_Dst

View File

@ -0,0 +1,355 @@
#include "evas_common.h"
Regionbuf *
evas_common_regionbuf_new(int w, int h)
{
Regionbuf *rb;
rb = calloc(1, sizeof(Regionbuf) + (h * sizeof(Regionspan)));
if (!rb) return NULL;
rb->spans = (Regionspan **)(rb + sizeof(Regionbuf));
rb->w = w;
rb->h = h;
return rb;
}
void
evas_common_regionbuf_free(Regionbuf *rb)
{
evas_common_regionbuf_clear(rb);
free(rb);
}
void
evas_common_regionbuf_clear(Regionbuf *rb)
{
int y;
for (y = 0; y < rb->h; y++)
{
while (rb->spans[y])
{
Regionspan *span;
span = rb->spans[y];
rb->spans[y] = evas_object_list_remove(rb->spans[y], rb->spans[y]);
free(span);
}
}
}
void
evas_common_regionbuf_span_add(Regionbuf *rb, int x1, int x2, int y)
{
Evas_Object_List *l;
Regionspan *span, *span2, *nspan, *sp_start, *sp_stop;
/* abort if outside */
if ((y < 0) ||
(y >= rb->h) ||
(x2 < 0) ||
(x1 >= rb->w)) return;
/* clip to horiz bounds */
if (x1 < 0) x1 = 0;
if (x2 < (rb->w - 1)) x2 = rb->w - 1;
sp_start = NULL;
sp_stop = NULL;
for (l = (Evas_Object_List *)rb->spans[y]; l; l = l->next)
{
span = (Regionspan *)l;
nspan = (Regionspan *)l->next;
/* we dont know what t do with the span yet */
if (!sp_start)
{
/* if new span starts before or on this span or just after
* with no gap */
if (x1 <= (span->x2 + 1))
sp_start = span;
/* if there is no next span */
if (!nspan)
{
sp_stop = span;
break;
}
/* if new span ends before the next span starts with a gap of
* 1 pixel (or more) */
else if (x2 < (nspan->x1 - 1))
{
sp_stop = span;
break;
}
}
/* we already know it already starts before or in sp_start */
else
{
/* there is no span after this one, so this has to be the stop */
if (!nspan)
{
sp_stop = span;
break;
}
/* if new span ends before the next span starts with a gap of
* 1 pixel (or more) */
else if (x2 < (nspan->x1 - 1))
{
sp_stop = span;
break;
}
}
}
/* sp_start is where the new span starts in or before */
/* sp_stop is where the new span stops in or after */
if ((sp_start) && (sp_stop))
{
/* same start and stop */
if (sp_start == sp_stop)
{
if (x2 < (sp_start->x1 - 1))
{
span2 = calloc(1, sizeof(Regionspan));
span2->x1 = x1;
span2->x2 = x2;
rb->spans[y] = evas_object_list_prepend_relative(rb->spans[y], span2, sp_start);
return;
}
if (x1 < sp_start->x1)
sp_start->x1 = x1;
if (x2 > sp_start->x2)
sp_start->x2 = x2;
return;
}
else
{
/* remove all nodes after sp_start and before_sp_stop because
* the new */
for (l = ((Evas_Object_List *)sp_start)->next; l != (Evas_Object_List *)sp_stop;)
{
span = (Regionspan *)l;
l = l->next;
rb->spans[y] = evas_object_list_remove(rb->spans[y], span);
free(span);
}
/* remove the end span */
rb->spans[y] = evas_object_list_remove(rb->spans[y], sp_stop);
/* if the new span is before the start span - extend */
if (x1 < sp_start->x1)
sp_start->x1 = x1;
/* if it goes beyond the stop span - extend stop span */
if (x2 > sp_stop->x2)
sp_stop->x2 = x2;
/* extend start span to stop span */
sp_start->x2 = sp_stop->x2;
/* don't need stop span anymore */
free(sp_stop);
return;
}
}
/* no start AND stop... just append */
span2 = calloc(1, sizeof(Regionspan));
span2->x1 = x1;
span2->x2 = x2;
rb->spans[y] = evas_object_list_append(rb->spans[y], span2);
}
void
evas_common_regionbuf_span_del(Regionbuf *rb, int x1, int x2, int y)
{
/* FIXME: del span */
Evas_Object_List *l;
Regionspan *span, *span2, *nspan, *sp_start, *sp_stop;
/* abort if outside */
if ((y < 0) ||
(y >= rb->h) ||
(x2 < 0) ||
(x1 >= rb->w)) return;
/* clip to horiz bounds */
if (x1 < 0) x1 = 0;
if (x2 < (rb->w - 1)) x2 = rb->w - 1;
sp_start = NULL;
sp_stop = NULL;
for (l = (Evas_Object_List *)rb->spans[y]; l; l = l->next)
{
span = (Regionspan *)l;
nspan = (Regionspan *)l->next;
/* we dont know what t do with the span yet */
if (!sp_start)
{
/* if new span starts before or on this span or just after
* with no gap */
if (x1 <= (span->x2))
sp_start = span;
/* if there is no next span */
if (!nspan)
{
sp_stop = span;
break;
}
/* if new span ends before the next span starts with a gap of
* 1 pixel (or more) */
else if (x2 < nspan->x1)
{
sp_stop = span;
break;
}
}
/* we already know it already starts before or in sp_start */
else
{
/* there is no span after this one, so this has to be the stop */
if (!nspan)
{
sp_stop = span;
break;
}
/* if new span ends before the next span starts with a gap of
* 1 pixel (or more) */
else if (x2 < nspan->x1)
{
sp_stop = span;
break;
}
}
}
/* sp_start is where the new span starts in or before */
/* sp_stop is where the new span stops in or after */
if ((sp_start) && (sp_stop))
{
/* same start and stop */
if (sp_start == sp_stop)
{
/* if it ends before this the span start starts... return */
if (x2 < sp_start->x1)
return;
/* it starts on or before this span */
else if (x1 <= sp_start->x1)
{
/* right edge is within the span */
if (x2 < sp_start->x2)
{
sp_start->x2 = x2;
return;
}
else
{
rb->spans[y] = evas_object_list_remove(rb->spans[y], sp_start);
return;
}
}
/* it ends on or after the end of thsi span */
else if (x2 >= sp_start->x2)
{
/* it starts after the start */
if (x1 > sp_start->x1)
{
sp_start->x1 = x1;
return;
}
/* remove it all */
else
{
rb->spans[y] = evas_object_list_remove(rb->spans[y], sp_start);
return;
}
return;
}
/* this breaks the span into 2 */
else
{
span2 = calloc(1, sizeof(Regionspan));
span2->x1 = sp_start->x1;
span2->x2 = x1 - 1;
rb->spans[y] = evas_object_list_prepend_relative(rb->spans[y], span2, sp_start);
sp_start->x1 = x2 + 1;
return;
}
}
else
{
/* remove all nodes after sp_start and before_sp_stop because
* the new */
for (l = ((Evas_Object_List *)sp_start)->next; l != (Evas_Object_List *)sp_stop;)
{
span = (Regionspan *)l;
l = l->next;
rb->spans[y] = evas_object_list_remove(rb->spans[y], span);
free(span);
}
/* all of the start span is cut out */
if (x1 <= sp_start->x1)
{
rb->spans[y] = evas_object_list_remove(rb->spans[y], sp_start);
free(sp_start);
}
/* chup it off at the new span start */
else
sp_start->x2 = x1 - 1;
/* all of the end span is cut out */
if (x2 >= sp_stop->x2)
{
rb->spans[y] = evas_object_list_remove(rb->spans[y], sp_stop);
free(sp_stop);
}
/* chop it up at the end */
else
sp_stop->x1 = x2 + 1;
return;
}
}
}
Tilebuf_Rect *
evas_common_regionbuf_rects_get(Regionbuf *rb)
{
Tilebuf_Rect *rects = NULL, *r;
int y;
/* FIXME: take spans, make rects */
for (y = 0; y < rb->h; y++)
{
Evas_Object_List *l, *ll;
for (l = (Evas_Object_List *)rb->spans[y]; l;)
{
Regionspan *span;
Regionspan *sp_start;
int yy;
sp_start = (Regionspan *)l;
l = l->next;
rb->spans[y] = evas_object_list_remove(rb->spans[y], sp_start);
for (yy = y + 1; yy < rb->h; yy++)
{
int match = 0;
for (ll = (Evas_Object_List *)rb->spans[yy]; ll;)
{
span = (Regionspan *)ll;
ll = ll->next;
if (span->x1 == sp_start->x1)
{
if ((span->x1 != sp_start->x1) ||
(span->x2 != sp_start->x2))
{
goto coallate;
}
match = 1;
rb->spans[yy] = evas_object_list_remove(rb->spans[yy], span);
free(span);
}
}
if (!match) goto coallate;
}
coallate:
r = calloc(1, sizeof(Tilebuf_Rect));
r->x = sp_start->x1;
r->y = y;
r->w = sp_start->x2 - sp_start->x1 + 1;
r->h = yy - y;
rects = evas_object_list_append(rects, r);
free(sp_start);
}
}
evas_common_regionbuf_clear(rb);
return rects;
}

View File

@ -2,9 +2,12 @@
#define TILE(tb, x, y) ((tb)->tiles.tiles[((y) * (tb)->tiles.w) + (x)])
#ifdef RECTUPDATE
#else
static int tilebuf_x_intersect(Tilebuf *tb, int x, int w, int *x1, int *x2, int *x1_fill, int *x2_fill);
static int tilebuf_y_intersect(Tilebuf *tb, int y, int h, int *y1, int *y2, int *y1_fill, int *y2_fill);
static int tilebuf_intersect(int tsize, int tlen, int tnum, int x, int w, int *x1, int *x2, int *x1_fill, int *x2_fill);
#endif
static void tilebuf_setup(Tilebuf *tb);
void
@ -31,7 +34,11 @@ evas_common_tilebuf_new(int w, int h)
void
evas_common_tilebuf_free(Tilebuf *tb)
{
#ifdef RECTUPDATE
evas_common_regionbuf_free(tb->rb);
#else
if (tb->tiles.tiles) free(tb->tiles.tiles);
#endif
free(tb);
}
@ -126,6 +133,13 @@ evas_common_tilebuf_get_tile_size(Tilebuf *tb, int *tw, int *th)
int
evas_common_tilebuf_add_redraw(Tilebuf *tb, int x, int y, int w, int h)
{
#ifdef RECTUPDATE
int i;
for (i = 0; i < h; i++)
evas_common_regionbuf_span_add(tb->rb, x, x + w - 1, y + i);
return 1;
#else
int tx1, tx2, ty1, ty2, tfx1, tfx2, tfy1, tfy2, xx, yy;
int num;
@ -148,11 +162,18 @@ evas_common_tilebuf_add_redraw(Tilebuf *tb, int x, int y, int w, int h)
}
}
return num;
#endif
}
int
evas_common_tilebuf_del_redraw(Tilebuf *tb, int x, int y, int w, int h)
{
#ifdef RECTUPDATE
int i;
for (i = 0; i < h; i++)
evas_common_regionbuf_span_del(tb->rb, x, x + w - 1, y + i);
#else
int tx1, tx2, ty1, ty2, tfx1, tfx2, tfy1, tfy2, xx, yy;
int num;
@ -179,6 +200,7 @@ evas_common_tilebuf_del_redraw(Tilebuf *tb, int x, int y, int w, int h)
}
}
return num;
#endif
}
int
@ -198,13 +220,20 @@ evas_common_tilebuf_add_motion_vector(Tilebuf *tb, int x, int y, int w, int h, i
void
evas_common_tilebuf_clear(Tilebuf *tb)
{
#ifdef RECTUPDATE
evas_common_regionbuf_clear(tb->rb);
#else
if (!tb->tiles.tiles) return;
memset(tb->tiles.tiles, 0, tb->tiles.w * tb->tiles.h * sizeof(Tilebuf_Tile));
#endif
}
Tilebuf_Rect *
evas_common_tilebuf_get_render_rects(Tilebuf *tb)
{
#ifdef RECTUPDATE
return evas_common_regionbuf_rects_get(tb->rb);
#else
Tilebuf_Rect *rects = NULL;
int x, y;
@ -269,6 +298,7 @@ evas_common_tilebuf_get_render_rects(Tilebuf *tb)
}
}
return rects;
#endif
}
void
@ -295,6 +325,9 @@ evas_common_tilebuf_free_render_rects(Tilebuf_Rect *rects)
static void
tilebuf_setup(Tilebuf *tb)
{
#ifdef RECTUPDATE
tb->rb = evas_common_regionbuf_new(tb->outbuf_w, tb->outbuf_h);
#else
if (tb->tiles.tiles) free(tb->tiles.tiles);
tb->tiles.tiles = NULL;
@ -310,8 +343,11 @@ tilebuf_setup(Tilebuf *tb)
return;
}
memset(tb->tiles.tiles, 0, tb->tiles.w * tb->tiles.h * sizeof(Tilebuf_Tile));
#endif
}
#ifdef RECTUPDATE
#else
static int
tilebuf_x_intersect(Tilebuf *tb, int x, int w, int *x1, int *x2, int *x1_fill, int *x2_fill)
{
@ -359,3 +395,4 @@ tilebuf_intersect(int tsize, int tlen, int tnum, int x, int w, int *x1, int *x2,
return 1;
tnum = 0;
}
#endif

View File

@ -23,6 +23,9 @@
/*****************************************************************************/
/* use exact rects for updates not tiles */
/* #define RECTUPDATE */
#undef MIN
#define MIN(_x, _y) \
(((_x) < (_y)) ? (_x) : (_y))
@ -177,6 +180,9 @@ typedef struct _Tilebuf Tilebuf;
typedef struct _Tilebuf_Tile Tilebuf_Tile;
typedef struct _Tilebuf_Rect Tilebuf_Rect;
typedef struct _Regionbuf Regionbuf;
typedef struct _Regionspan Regionspan;
typedef void (*Gfx_Func_Blend_Src_Dst) (DATA32 *src, DATA32 *dst, int len);
typedef void (*Gfx_Func_Blend_Color_Dst) (DATA32 src, DATA32 *dst, int len);
typedef void (*Gfx_Func_Blend_Src_Cmod_Dst) (DATA32 *src, DATA32 *dst, int len, DATA8 *rmod, DATA8 *gmod, DATA8 *bmod, DATA8 *amod);
@ -385,11 +391,15 @@ struct _Tilebuf
struct {
int w, h;
} tile_size;
#ifdef RECTUPDATE
Regionbuf *rb;
#else
struct {
int w, h;
Tilebuf_Tile *tiles;
} tiles;
#endif
};
struct _Tilebuf_Tile
@ -413,6 +423,18 @@ struct _Tilebuf_Rect
int x, y, w, h;
};
struct _Regionbuf
{
int w, h;
Regionspan **spans;
};
struct _Regionspan
{
Evas_Object_List _list_data;
int x1, x2;
};
struct _Cutout_Rect
{
Evas_Object_List _list_data;
@ -890,7 +912,15 @@ int evas_common_tilebuf_add_motion_vector (Tilebuf *tb, int x, int y,
void evas_common_tilebuf_clear (Tilebuf *tb);
Tilebuf_Rect *evas_common_tilebuf_get_render_rects (Tilebuf *tb);
void evas_common_tilebuf_free_render_rects (Tilebuf_Rect *rects);
Regionbuf *evas_common_regionbuf_new (int w, int h);
void evas_common_regionbuf_free (Regionbuf *rb);
void evas_common_regionbuf_clear (Regionbuf *rb);
void evas_common_regionbuf_span_add (Regionbuf *rb, int x1, int x2, int y);
void evas_common_regionbuf_span_del (Regionbuf *rb, int x1, int x2, int y);
Tilebuf_Rect *evas_common_regionbuf_rects_get (Regionbuf *rb);
/****/
void evas_common_draw_init (void);
@ -915,7 +945,7 @@ Cutout_Rect *evas_common_draw_context_apply_cutouts (RGBA_Draw_Context
void evas_common_draw_context_apply_free_cutouts(Cutout_Rect *rects);
Cutout_Rect *evas_common_draw_context_cutouts_split (Cutout_Rect *in, Cutout_Rect *split);
Cutout_Rect *evas_common_draw_context_cutout_split (Cutout_Rect *in, Cutout_Rect *split);
Cutout_Rect *evas_common_draw_context_cutout_merge (Cutout_Rect *in, Cutout_Rect *merge);
Gfx_Func_Blend_Src_Dst evas_common_draw_func_blend_get (RGBA_Image *src, RGBA_Image *dst, int pixels);
Gfx_Func_Blend_Color_Dst evas_common_draw_func_blend_color_get (DATA32 src, RGBA_Image *dst, int pixels);
Gfx_Func_Blend_Src_Cmod_Dst evas_common_draw_func_blend_cmod_get (RGBA_Image *src, RGBA_Image *dst, int pixels);