From 7fe60435bce6595a9c58a9bfd8244d74b5320e96 Mon Sep 17 00:00:00 2001 From: Benjamin Franzke Date: Tue, 15 Jan 2013 08:46:13 +0100 Subject: Import DirectFB141_2k11R3_beta5 --- Source/DirectFB/src/gfx/clip.c | 379 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 379 insertions(+) create mode 100755 Source/DirectFB/src/gfx/clip.c (limited to 'Source/DirectFB/src/gfx/clip.c') diff --git a/Source/DirectFB/src/gfx/clip.c b/Source/DirectFB/src/gfx/clip.c new file mode 100755 index 0000000..195dc73 --- /dev/null +++ b/Source/DirectFB/src/gfx/clip.c @@ -0,0 +1,379 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include + +#include + +#include + +#include + +#include + +#define REGION_CODE(x,y,cx1,cx2,cy1,cy2) ( ( (y) > (cy2) ? 8 : 0) | \ + ( (y) < (cy1) ? 4 : 0) | \ + ( (x) > (cx2) ? 2 : 0) | \ + ( (x) < (cx1) ? 1 : 0) ) + + +DFBBoolean +dfb_clip_line( const DFBRegion *clip, DFBRegion *line ) +{ + unsigned char region_code1 = REGION_CODE( line->x1, line->y1, + clip->x1, + clip->x2, + clip->y1, + clip->y2 ); + + unsigned char region_code2 = REGION_CODE( line->x2, line->y2, + clip->x1, + clip->x2, + clip->y1, + clip->y2 ); + + while (region_code1 | region_code2) { + /* line completely outside the clipping rectangle */ + if (region_code1 & region_code2) + return DFB_FALSE; + + + if (region_code1) { + if (region_code1 & 8) { /* divide line at bottom*/ + line->x1 = line->x1 +(line->x2-line->x1) * (clip->y2 - line->y1) / (line->y2-line->y1); + line->y1 = clip->y2; + } + else + if (region_code1 & 4) { /* divide line at top*/ + line->x1 = line->x1 +(line->x2-line->x1) * (clip->y1 - line->y1) / (line->y2-line->y1); + line->y1 = clip->y1; + } + else + if (region_code1 & 2) { /* divide line at right*/ + line->y1 = line->y1 +(line->y2-line->y1) * (clip->x2 - line->x1) / (line->x2-line->x1); + line->x1 = clip->x2; + } + else + if (region_code1 & 1) { /* divide line at right*/ + line->y1 = line->y1 +(line->y2-line->y1) * (clip->x1 - line->x1) / (line->x2-line->x1); + line->x1 = clip->x1; + } + region_code1 = REGION_CODE( line->x1, line->y1, + clip->x1, + clip->x2, + clip->y1, + clip->y2 ); + } + else { + if (region_code2 & 8) { /* divide line at bottom*/ + line->x2 = line->x1 +(line->x2-line->x1) * (clip->y2 - line->y1) / (line->y2-line->y1); + line->y2 = clip->y2; + } + else + if (region_code2 & 4) { /* divide line at top*/ + line->x2 = line->x1 +(line->x2-line->x1) * (clip->y1 - line->y1) / (line->y2-line->y1); + line->y2 = clip->y1; + } + else + if (region_code2 & 2) { /* divide line at right*/ + line->y2 = line->y1 +(line->y2-line->y1) * (clip->x2 - line->x1) / (line->x2-line->x1); + line->x2 = clip->x2; + } + else + if (region_code2 & 1) { /* divide line at right*/ + line->y2 = line->y1 +(line->y2-line->y1) * (clip->x1 - line->x1) / (line->x2-line->x1); + line->x2 = clip->x1; + } + region_code2 = REGION_CODE( line->x2, line->y2, clip->x1, + clip->x2, + clip->y1, + clip->y2 ); + } + } + + /* successfully clipped or clipping not neccessary */ + return DFB_TRUE; +} + +DFBEdgeFlags +dfb_clip_edges( const DFBRegion *clip, DFBRectangle *rect ) +{ + DFBEdgeFlags flags = DFEF_ALL; + + if ((clip->x1 >= rect->x + rect->w) || + (clip->x2 < rect->x) || + (clip->y1 >= rect->y + rect->h) || + (clip->y2 < rect->y)) + return DFEF_NONE; + + if (clip->x1 > rect->x) { + rect->w += rect->x - clip->x1; + rect->x = clip->x1; + + flags &= ~DFEF_LEFT; + } + + if (clip->y1 > rect->y) { + rect->h += rect->y - clip->y1; + rect->y = clip->y1; + + flags &= ~DFEF_TOP; + } + + if (clip->x2 < rect->x + rect->w - 1) { + rect->w = clip->x2 - rect->x + 1; + + flags &= ~DFEF_RIGHT; + } + + if (clip->y2 < rect->y + rect->h - 1) { + rect->h = clip->y2 - rect->y + 1; + + flags &= ~DFEF_BOTTOM; + } + + return flags; +} + +DFBBoolean +dfb_clip_rectangle( const DFBRegion *clip, DFBRectangle *rect ) +{ + if ((clip->x1 >= rect->x + rect->w) || + (clip->x2 < rect->x) || + (clip->y1 >= rect->y + rect->h) || + (clip->y2 < rect->y)) + return DFB_FALSE; + + if (clip->x1 > rect->x) { + rect->w += rect->x - clip->x1; + rect->x = clip->x1; + } + + if (clip->y1 > rect->y) { + rect->h += rect->y - clip->y1; + rect->y = clip->y1; + } + + if (clip->x2 < rect->x + rect->w - 1) + rect->w = clip->x2 - rect->x + 1; + + if (clip->y2 < rect->y + rect->h - 1) + rect->h = clip->y2 - rect->y + 1; + + return DFB_TRUE; +} + +DFBBoolean +dfb_clip_triangle_precheck( const DFBRegion *clip, const DFBTriangle *tri ) +{ + int x, y, w, h; + + x = MIN (MIN (tri->x1, tri->x2), tri->x3); + y = MIN (MIN (tri->y1, tri->y2), tri->y3); + w = MAX (MAX (tri->x1, tri->x2), tri->x3) - x; + h = MAX (MAX (tri->y1, tri->y2), tri->y3) - y; + + if (clip->x1 > x || + clip->x2 < x + w || + clip->y1 > y || + clip->y2 < y + h) + return DFB_FALSE; + + return DFB_TRUE; +} + +DFBBoolean +dfb_clip_triangle( const DFBRegion *clip, const DFBTriangle *tri, DFBPoint p[6], int *num ) +{ + DFBRegion edges[3]; + int num_edges; + int i, n; + DFBPoint p1 = {0, 0}, p2 = {0, 0}; + + /* Initialize edges. */ + edges[0].x1 = tri->x1; edges[0].y1 = tri->y1; + edges[0].x2 = tri->x2; edges[0].y2 = tri->y2; + edges[1].x1 = tri->x2; edges[1].y1 = tri->y2; + edges[1].x2 = tri->x3; edges[1].y2 = tri->y3; + edges[2].x1 = tri->x3; edges[2].y1 = tri->y3; + edges[2].x2 = tri->x1; edges[2].y2 = tri->y1; + num_edges = 3; + + for (i = 0; i < num_edges; i++) { + DFBRegion *reg = &edges[i]; + DFBRegion line; + bool i1, i2; + + /* Clip the edge to the clipping region. */ + line = *reg; + if (dfb_clip_line( clip, &line )) { + *reg = line; + continue; + } + + /* If the edge doesn't intersect clipping region, then + * intersect the edge with the diagonals of the clipping + * rectangle. If intersection point exits, add the nearest + * corner of the clipping region to the list of vertices. + */ + + /* Diagonal (x1,y1) (x2,y2). */ + line = (DFBRegion) { clip->x1, clip->y1, clip->x2, clip->y2 }; + i1 = dfb_line_segment_intersect( &line, reg, &p1.x, &p1.y ); + if (i1) { + /* Get nearest corner. */ + if (p1.x <= clip->x1 || p1.y <= clip->y1) { + p1.x = clip->x1; + p1.y = clip->y1; + } else { + p1.x = clip->x2; + p1.y = clip->y2; + } + } + + /* Diagonal (x2,y1) (x1,y2). */ + line = (DFBRegion) { clip->x2, clip->y1, clip->x1, clip->y2 }; + i2 = dfb_line_segment_intersect( &line, reg, &p2.x, &p2.y ); + if (i2) { + /* Get nearest corner. */ + if (p2.x >= clip->x2 || p2.y <= clip->y1) { + p2.x = clip->x2; + p2.y = clip->y1; + } else { + p2.x = clip->x1; + p2.y = clip->y2; + } + } + + if (i1 && i2) { + reg->x1 = p1.x; + reg->y1 = p1.y; + reg->x2 = p2.x; + reg->y2 = p2.y; + } + else if (i1) { + reg->x1 = reg->x2 = p1.x; + reg->y1 = reg->y2 = p1.y; + } + else if (i2) { + reg->x1 = reg->x2 = p2.x; + reg->y1 = reg->y2 = p2.y; + } + else { + /* Redudant edge. Remote it. */ + memmove( reg, &edges[i+1], (num_edges-i-1) * sizeof(DFBRegion) ); + num_edges--; + i--; + } + } + + if (num_edges < 1) { + *num = 0; + return DFB_FALSE; + } + + /* Get vertices from edges. */ + p[0].x = edges[0].x1; p[0].y = edges[0].y1; + n = 1; + if (edges[0].x2 != edges[0].x1 || edges[0].y2 != edges[0].y1) { + p[1].x = edges[0].x2; p[1].y = edges[0].y2; + n++; + } + + for (i = 1; i < num_edges; i++) { + if (edges[i].x1 != p[n-1].x || edges[i].y1 != p[n-1].y) { + p[n].x = edges[i].x1; p[n].y = edges[i].y1; + n++; + } + if (edges[i].x2 != p[n-1].x || edges[i].y2 != p[n-1].y) { + p[n].x = edges[i].x2; p[n].y = edges[i].y2; + n++; + } + } + + if (p[n-1].x == p[0].x && p[n-1].y == p[0].y) + n--; + + *num = n; + + /* Actually fail if the number of vertices is below 3. */ + return (n >= 3); +} + + +void +dfb_clip_blit( const DFBRegion *clip, + DFBRectangle *srect, int *dx, int *dy ) +{ + if (clip->x1 > *dx ) { + srect->w = MIN( (clip->x2 - clip->x1) + 1, + (*dx + srect->w) - clip->x1); + + srect->x+= clip->x1 - *dx; + *dx = clip->x1; + } + else if (clip->x2 < *dx + srect->w - 1) { + srect->w = clip->x2 - *dx + 1; + } + + if (clip->y1 > *dy ) { + srect->h = MIN( (clip->y2 - clip->y1) + 1, + (*dy + srect->h) - clip->y1); + srect->y+= clip->y1 - *dy; + *dy = clip->y1; + } + else if (clip->y2 < *dy + srect->h - 1) { + srect->h = clip->y2 - *dy + 1; + } +} + +void +dfb_clip_stretchblit( const DFBRegion *clip, + DFBRectangle *srect, DFBRectangle *drect ) +{ + DFBRectangle orig_dst = *drect; + + dfb_clip_rectangle( clip, drect ); + + if (drect->x != orig_dst.x) + srect->x += (int)( (drect->x - orig_dst.x) * + (srect->w / (float)orig_dst.w) ); + + if (drect->y != orig_dst.y) + srect->y += (int)( (drect->y - orig_dst.y) * + (srect->h / (float)orig_dst.h) ); + + if (drect->w != orig_dst.w) + srect->w = (int)( srect->w * (drect->w / (float)orig_dst.w) ); + + if (drect->h != orig_dst.h) + srect->h = (int)( srect->h * (drect->h / (float)orig_dst.h) ); +} + -- cgit