diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2006-12-03 16:24:28 +1100 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2006-12-03 16:24:28 +1100 |
commit | 1ef6eaa1c4c6f895546fe9ad42d40e572be4a8aa (patch) | |
tree | 9a5ca3da3f4f7baa18e54ddbbad6aae712b86e6b | |
parent | 223adfae7caab8603c22159db00af7c08da9023c (diff) |
Rework clip handling. The clip rectangle and the origin of drawing
are now two different things, so that you can clip drawing within
changing your coordinate system.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r-- | twin.h | 30 | ||||
-rw-r--r-- | twin_box.c | 6 | ||||
-rw-r--r-- | twin_draw.c | 36 | ||||
-rw-r--r-- | twin_pixmap.c | 70 | ||||
-rw-r--r-- | twin_poly.c | 13 | ||||
-rw-r--r-- | twin_window.c | 12 |
6 files changed, 138 insertions, 29 deletions
@@ -117,9 +117,13 @@ typedef struct _twin_pixmap { /* * Clipping - a single rectangle in pixmap coordinates. - * Drawing is done relative to this rectangle + * Drawing is done clipped by this rectangle and relative + * to origin_x, origin_y */ twin_rect_t clip; + twin_coord_t origin_x; + twin_coord_t origin_y; + /* * Pixels */ @@ -955,15 +959,35 @@ void twin_pixmap_disable_update (twin_pixmap_t *pixmap); void -twin_pixmap_clip (twin_pixmap_t *pixmap, +twin_pixmap_get_origin (twin_pixmap_t *pixmap, + twin_coord_t *ox, twin_coord_t *oy); + +void +twin_pixmap_set_origin (twin_pixmap_t *pixmap, + twin_coord_t ox, twin_coord_t oy); + +void +twin_pixmap_origin_to_clip (twin_pixmap_t *pixmap); + +void +twin_pixmap_offset (twin_pixmap_t *pixmap, + twin_coord_t offx, twin_coord_t offy); + + +void +twin_pixmap_clip (twin_pixmap_t *pixmap, twin_coord_t left, twin_coord_t top, twin_coord_t right, twin_coord_t bottom); void twin_pixmap_set_clip (twin_pixmap_t *pixmap, twin_rect_t clip); + +twin_rect_t +twin_pixmap_get_clip (twin_pixmap_t *pixmap); + twin_rect_t -twin_pixmap_current_clip (twin_pixmap_t *pixmap); +twin_pixmap_save_clip (twin_pixmap_t *pixmap); void twin_pixmap_restore_clip (twin_pixmap_t *pixmap, twin_rect_t rect); @@ -230,17 +230,21 @@ _twin_box_dispatch (twin_widget_t *widget, twin_event_t *event) if (child->paint) { twin_pixmap_t *pixmap = box->widget.window->pixmap; - twin_rect_t clip = twin_pixmap_current_clip (pixmap); + twin_rect_t clip = twin_pixmap_save_clip (pixmap); + twin_coord_t ox, oy; + twin_pixmap_get_origin (pixmap, &ox, &oy); if (child->shape != TwinShapeRectangle) twin_fill (child->window->pixmap, widget->background, TWIN_SOURCE, child->extents.left, child->extents.top, child->extents.right, child->extents.bottom); twin_pixmap_set_clip (pixmap, child->extents); + twin_pixmap_origin_to_clip (pixmap); child->paint = TWIN_FALSE; (*child->dispatch) (child, event); twin_pixmap_restore_clip (pixmap, clip); + twin_pixmap_set_origin (pixmap, ox, oy); } break; default: diff --git a/twin_draw.c b/twin_draw.c index 3045cea..48a9da6 100644 --- a/twin_draw.c +++ b/twin_draw.c @@ -276,8 +276,8 @@ static void _twin_composite_simple (twin_pixmap_t *dst, twin_coord_t sdx, sdy; twin_source_u s; - dst_x += dst->clip.left; - dst_y += dst->clip.top; + dst_x += dst->origin_x; + dst_y += dst->origin_y; left = dst_x; top = dst_y; right = dst_x + width; @@ -296,7 +296,10 @@ static void _twin_composite_simple (twin_pixmap_t *dst, if (left >= right || top >= bottom) return; - if (src->source_kind != TWIN_PIXMAP) + if (src->source_kind == TWIN_PIXMAP) { + src_x += src->u.pixmap->origin_x; + src_y += src->u.pixmap->origin_y; + } else s.c = src->u.argb; sdx = src_x - dst_x; @@ -307,7 +310,10 @@ static void _twin_composite_simple (twin_pixmap_t *dst, twin_source_u m; twin_coord_t mdx, mdy; - if (msk->source_kind != TWIN_PIXMAP) + if (msk->source_kind == TWIN_PIXMAP) { + msk_x += msk->u.pixmap->origin_x; + msk_y += msk->u.pixmap->origin_y; + } else m.c = msk->u.argb; mdx = msk_x - dst_x; @@ -533,8 +539,8 @@ static void _twin_composite_xform (twin_pixmap_t *dst, twin_xform_t *sxform = NULL, *mxform = NULL; twin_source_u s; - dst_x += dst->clip.left; - dst_y += dst->clip.top; + dst_x += dst->origin_x; + dst_y += dst->origin_y; left = dst_x; top = dst_y; right = dst_x + width; @@ -556,7 +562,9 @@ static void _twin_composite_xform (twin_pixmap_t *dst, width = right - left; height = bottom - top; - if (src->source_kind == TWIN_PIXMAP) { + if (src->source_kind == TWIN_PIXMAP) { + src_x += src->u.pixmap->origin_x; + src_y += src->u.pixmap->origin_y; sxform = twin_pixmap_init_xform(src->u.pixmap, left, width, src_x, src_y); if (sxform == NULL) @@ -570,6 +578,8 @@ static void _twin_composite_xform (twin_pixmap_t *dst, twin_source_u m; if (msk->source_kind == TWIN_PIXMAP) { + msk_x += msk->u.pixmap->origin_x; + msk_y += msk->u.pixmap->origin_y; mxform = twin_pixmap_init_xform(msk->u.pixmap, left, width, msk_x, msk_y); if (mxform == NULL) @@ -660,11 +670,13 @@ twin_fill (twin_pixmap_t *dst, twin_src_op op; twin_source_u src; twin_coord_t iy; - - left += dst->clip.left; - right += dst->clip.left; - top += dst->clip.top; - bottom += dst->clip.top; + + /* offset */ + left += dst->origin_x; + top += dst->origin_y; + right += dst->origin_x; + bottom += dst->origin_y; + /* clip */ if (left < dst->clip.left) left = dst->clip.left; diff --git a/twin_pixmap.c b/twin_pixmap.c index b390ad6..e056093 100644 --- a/twin_pixmap.c +++ b/twin_pixmap.c @@ -43,6 +43,7 @@ twin_pixmap_create (twin_format_t format, pixmap->clip.left = pixmap->clip.top = 0; pixmap->clip.right = pixmap->width; pixmap->clip.bottom = pixmap->height; + pixmap->origin_x = pixmap->origin_y = 0; pixmap->stride = stride; pixmap->disable = 0; pixmap->p.v = pixmap + 1; @@ -71,6 +72,7 @@ twin_pixmap_create_const (twin_format_t format, pixmap->clip.left = pixmap->clip.top = 0; pixmap->clip.right = pixmap->width; pixmap->clip.bottom = pixmap->height; + pixmap->origin_x = pixmap->origin_y = 0; pixmap->stride = stride; pixmap->disable = 0; pixmap->p = pixels; @@ -184,32 +186,90 @@ twin_pixmap_disable_update (twin_pixmap_t *pixmap) } void +twin_pixmap_set_origin (twin_pixmap_t *pixmap, + twin_coord_t ox, twin_coord_t oy) +{ + pixmap->origin_x = ox; + pixmap->origin_y = oy; +} + +void +twin_pixmap_offset (twin_pixmap_t *pixmap, + twin_coord_t offx, twin_coord_t offy) +{ + pixmap->origin_x += offx; + pixmap->origin_y += offy; +} + +void +twin_pixmap_get_origin (twin_pixmap_t *pixmap, + twin_coord_t *ox, twin_coord_t *oy) +{ + *ox = pixmap->origin_x; + *oy = pixmap->origin_y; +} + +void +twin_pixmap_origin_to_clip (twin_pixmap_t *pixmap) +{ + pixmap->origin_x = pixmap->clip.left; + pixmap->origin_y = pixmap->clip.top; +} + +void twin_pixmap_clip (twin_pixmap_t *pixmap, twin_coord_t left, twin_coord_t top, twin_coord_t right, twin_coord_t bottom) { + left += pixmap->origin_x; + right += pixmap->origin_x; + top += pixmap->origin_y; + bottom += pixmap->origin_y; + if (left > pixmap->clip.left) pixmap->clip.left = left; if (top > pixmap->clip.top) pixmap->clip.top = top; if (right < pixmap->clip.right) pixmap->clip.right = right; if (bottom < pixmap->clip.bottom) pixmap->clip.bottom = bottom; + if (pixmap->clip.left >= pixmap->clip.right) pixmap->clip.right = pixmap->clip.left = 0; if (pixmap->clip.top >= pixmap->clip.bottom) pixmap->clip.bottom = pixmap->clip.top = 0; + + if (pixmap->clip.left < 0) + pixmap->clip.left = 0; + if (pixmap->clip.top < 0) + pixmap->clip.top = 0; + if (pixmap->clip.right > pixmap->width) + pixmap->clip.right = pixmap->width; + if (pixmap->clip.bottom > pixmap->height) + pixmap->clip.bottom = pixmap->height; } void twin_pixmap_set_clip (twin_pixmap_t *pixmap, twin_rect_t clip) { twin_pixmap_clip (pixmap, - clip.left + pixmap->clip.left, - clip.top + pixmap->clip.top, - clip.right + pixmap->clip.left, - clip.bottom+ pixmap->clip.top); + clip.left, clip.top, + clip.right, clip.bottom); +} + + +twin_rect_t +twin_pixmap_get_clip (twin_pixmap_t *pixmap) +{ + twin_rect_t clip = pixmap->clip; + + clip.left -= pixmap->origin_x; + clip.right -= pixmap->origin_x; + clip.top -= pixmap->origin_y; + clip.bottom -= pixmap->origin_y; + + return clip; } twin_rect_t -twin_pixmap_current_clip (twin_pixmap_t *pixmap) +twin_pixmap_save_clip (twin_pixmap_t *pixmap) { return pixmap->clip; } diff --git a/twin_poly.c b/twin_poly.c index 16c2b1f..71e5578 100644 --- a/twin_poly.c +++ b/twin_poly.c @@ -206,8 +206,8 @@ _span_fill (twin_pixmap_t *pixmap, if (left < twin_int_to_sfixed (pixmap->clip.left)) left = twin_int_to_sfixed (pixmap->clip.left); - if (right > twin_int_to_sfixed (pixmap->width)) - right = twin_int_to_sfixed (pixmap->width); + if (right > twin_int_to_sfixed (pixmap->clip.right)) + right = twin_int_to_sfixed (pixmap->clip.right); /* convert to sample grid */ left = _twin_sfixed_grid_ceil (left) >> TWIN_POLY_FIXED_SHIFT; @@ -353,15 +353,13 @@ twin_fill_path (twin_pixmap_t *pixmap, twin_path_t *path, int nalloc; int s; int p; - twin_sfixed_t sdx = twin_int_to_sfixed (dx); - twin_sfixed_t sdy = twin_int_to_sfixed (dy); + twin_sfixed_t sdx = twin_int_to_sfixed (dx + pixmap->origin_x); + twin_sfixed_t sdy = twin_int_to_sfixed (dy + pixmap->origin_y); nalloc = path->npoints + path->nsublen + 1; edges = malloc (sizeof (twin_edge_t) * nalloc); p = 0; nedges = 0; - dx += twin_int_to_sfixed (pixmap->clip.left); - dy += twin_int_to_sfixed (pixmap->clip.top); for (s = 0; s <= path->nsublen; s++) { int sublen; @@ -375,7 +373,8 @@ twin_fill_path (twin_pixmap_t *pixmap, twin_path_t *path, if (npoints > 1) { n = _twin_edge_build (path->points + p, npoints, edges + nedges, - sdx, sdy, twin_int_to_sfixed (pixmap->clip.top)); + sdx, sdy, + twin_int_to_sfixed (pixmap->clip.top)); p = sublen; nedges += n; } diff --git a/twin_window.c b/twin_window.c index d4c69c7..ff2862f 100644 --- a/twin_window.c +++ b/twin_window.c @@ -70,6 +70,7 @@ twin_window_create (twin_screen_t *screen, twin_pixmap_clip (window->pixmap, window->client.left, window->client.top, window->client.right, window->client.bottom); + twin_pixmap_origin_to_clip (window->pixmap); window->pixmap->window = window; twin_pixmap_move (window->pixmap, x, y); window->damage.left = window->damage.right = 0; @@ -136,9 +137,11 @@ twin_window_configure (twin_window_t *window, for (i = 0; i < old->disable; i++) twin_pixmap_disable_update (window->pixmap); twin_pixmap_destroy (old); + twin_pixmap_reset_clip (window->pixmap); twin_pixmap_clip (window->pixmap, window->client.left, window->client.top, window->client.right, window->client.bottom); + twin_pixmap_origin_to_clip (window->pixmap); } if (x != window->pixmap->x || y != window->pixmap->y) twin_pixmap_move (window->pixmap, x, y); @@ -207,6 +210,7 @@ twin_window_frame (twin_window_t *window) const char *name; twin_pixmap_reset_clip (pixmap); + twin_pixmap_origin_to_clip (pixmap); twin_fill (pixmap, 0x00000000, TWIN_SOURCE, 0, 0, pixmap->width, window->client.top); @@ -264,12 +268,14 @@ twin_window_frame (twin_window_t *window) 0, twin_fixed_to_int (twin_fixed_ceil (c_right - t_arc_2)), window->client.top); - + twin_pixmap_origin_to_clip (pixmap); + twin_path_move (path, text_x - twin_fixed_floor (menu_x), text_y); twin_path_utf8 (path, window->name); twin_paint_path (pixmap, TWIN_FRAME_TEXT, path); twin_pixmap_reset_clip (pixmap); + twin_pixmap_origin_to_clip (pixmap); /* widgets */ @@ -307,12 +313,16 @@ twin_window_frame (twin_window_t *window) twin_pixmap_clip (pixmap, window->client.left, window->client.top, window->client.right, window->client.bottom); + twin_pixmap_origin_to_clip (pixmap); + twin_path_destroy (path); } void twin_window_draw (twin_window_t *window) { + twin_pixmap_t *pixmap = window->pixmap; + switch (window->style) { case TwinWindowPlain: default: |