summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2006-12-03 16:24:28 +1100
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2006-12-03 16:24:28 +1100
commit1ef6eaa1c4c6f895546fe9ad42d40e572be4a8aa (patch)
tree9a5ca3da3f4f7baa18e54ddbbad6aae712b86e6b
parent223adfae7caab8603c22159db00af7c08da9023c (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.h30
-rw-r--r--twin_box.c6
-rw-r--r--twin_draw.c36
-rw-r--r--twin_pixmap.c70
-rw-r--r--twin_poly.c13
-rw-r--r--twin_window.c12
6 files changed, 138 insertions, 29 deletions
diff --git a/twin.h b/twin.h
index c2603c6..2e13fe0 100644
--- a/twin.h
+++ b/twin.h
@@ -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);
diff --git a/twin_box.c b/twin_box.c
index b1aa299..72ed5e1 100644
--- a/twin_box.c
+++ b/twin_box.c
@@ -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: