1/* Copyright (C) 2007-2008 The Android Open Source Project
2**
3** This software is licensed under the terms of the GNU General Public
4** License version 2, as published by the Free Software Foundation, and
5** may be copied, distributed, and modified under those terms.
6**
7** This program is distributed in the hope that it will be useful,
8** but WITHOUT ANY WARRANTY; without even the implied warranty of
9** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10** GNU General Public License for more details.
11*/
12#include "android/skin/rect.h"
13#include <limits.h>
14
15#define  SKIN_POS_INITIALIZER   { 0, 0 }
16
17void
18skin_pos_rotate( SkinPos*  dst, SkinPos*  src, SkinRotation  rotation )
19{
20    int  x = src->x;
21    int  y = src->y;
22
23    switch ( rotation & 3 ) {
24    case SKIN_ROTATION_0:
25        dst->x = x;
26        dst->y = y;
27        break;
28
29    case SKIN_ROTATION_90:
30        dst->x = -y;
31        dst->y =  x;
32        break;
33
34    case SKIN_ROTATION_180:
35        dst->x = -x;
36        dst->y = -y;
37        break;
38
39    default:
40        dst->x =  y;
41        dst->y = -x;
42    }
43}
44
45
46#define  SKIN_SIZE_INITIALIZER  { 0, 0 }
47
48int
49skin_size_contains( SkinSize*  size, int  x, int  y )
50{
51    return ( (unsigned) x < (unsigned) size->w &&
52             (unsigned) y < (unsigned) size->h );
53}
54
55void
56skin_size_rotate( SkinSize*  dst, SkinSize*  src, SkinRotation  rot )
57{
58    int  w = src->w;
59    int  h = src->h;
60
61    if ((rot & 1) != 0) {
62        dst->w = h;
63        dst->h = w;
64    } else {
65        dst->w = w;
66        dst->h = h;
67    }
68}
69
70/** SKIN RECTANGLES
71 **/
72#define  SKIN_RECT_INITIALIZER  { SKIN_POS_INITIALIZER, SKIN_SIZE_INITIALIZER }
73
74void
75skin_rect_init( SkinRect*  r, int x, int  y, int  w, int  h )
76{
77    if (w < 0 || h < 0)
78        x = y = w = h = 0;
79
80    r->pos.x  = x;
81    r->pos.y  = y;
82    r->size.w = w;
83    r->size.h = h;
84}
85
86
87void
88skin_rect_translate( SkinRect*  r, int  dx, int  dy )
89{
90    r->pos.x += dx;
91    r->pos.y += dy;
92}
93
94
95void
96skin_rect_rotate( SkinRect*  dst, SkinRect*  src, SkinRotation  rot )
97{
98    int  x, y, w, h;
99
100    switch (rot & 3) {
101        case SKIN_ROTATION_90:
102            x = src->pos.x;
103            y = src->pos.y;
104            w = src->size.w;
105            h = src->size.h;
106            dst->pos.x  = -(y + h);
107            dst->pos.y  = x;
108            dst->size.w = h;
109            dst->size.h = w;
110            break;
111
112        case SKIN_ROTATION_180:
113            dst->pos.x = -(src->pos.x + src->size.w);
114            dst->pos.y = -(src->pos.y + src->size.h);
115            dst->size  = src->size;
116            break;
117
118        case SKIN_ROTATION_270:
119            x = src->pos.x;
120            y = src->pos.y;
121            w = src->size.w;
122            h = src->size.h;
123            dst->pos.x  = y;
124            dst->pos.y  = -(x + w);
125            dst->size.w = h;
126            dst->size.h = w;
127            break;
128
129        default:
130            dst[0] = src[0];
131    }
132}
133
134
135int
136skin_rect_contains( SkinRect*  r, int  x, int  y )
137{
138    return ( (unsigned)(x - r->pos.x) < (unsigned)r->size.w &&
139             (unsigned)(y - r->pos.y) < (unsigned)r->size.h );
140}
141
142SkinOverlap
143skin_rect_contains_rect( SkinRect  *r1, SkinRect  *r2 )
144{
145    SkinBox  a, b;
146
147    skin_box_from_rect( &a, r1 );
148    skin_box_from_rect( &b, r2 );
149
150    if (a.x2 <= b.x1 || b.x2 <= a.x1 || a.y2 <= b.y1 || b.y2 <= a.y1) {
151        return SKIN_OUTSIDE;
152    }
153
154    if (b.x1 >= a.x1 && b.x2 <= a.x2 && b.y1 >= a.y1 && b.y2 <= a.y2) {
155        return SKIN_INSIDE;
156    }
157
158    return SKIN_OVERLAP;
159}
160
161
162int
163skin_rect_intersect( SkinRect*  result, SkinRect*  r1, SkinRect*  r2 )
164{
165    SkinBox  a, b, r;
166
167    skin_box_from_rect( &a, r1 );
168    skin_box_from_rect( &b, r2 );
169
170    if (a.x2 <= b.x1 || b.x2 <= a.x1 || a.y2 <= b.y1 || b.y2 <= a.y1) {
171        result->pos.x = result->pos.y = result->size.w = result->size.h = 0;
172        return 0;
173    }
174
175    r.x1 = (a.x1 > b.x1) ? a.x1 : b.x1;
176    r.x2 = (a.x2 < b.x2) ? a.x2 : b.x2;
177    r.y1 = (a.y1 > b.y1) ? a.y1 : b.y1;
178    r.y2 = (a.y2 < b.y2) ? a.y2 : b.y2;
179
180    skin_box_to_rect( &r, result );
181    return 1;
182}
183
184int
185skin_rect_equals( SkinRect*  r1, SkinRect*  r2 )
186{
187    return (r1->pos.x  == r2->pos.x  && r1->pos.y  == r2->pos.y &&
188            r1->size.w == r2->size.w && r2->size.h == r2->size.h);
189}
190
191/** SKIN BOXES
192 **/
193void
194skin_box_minmax_init( SkinBox*  box )
195{
196    box->x1 = box->y1 = INT_MAX;
197    box->x2 = box->y2 = INT_MIN;
198}
199
200void
201skin_box_minmax_update( SkinBox*  a, SkinRect*  r )
202{
203    SkinBox  b[1];
204
205    skin_box_from_rect(b, r);
206
207    if (b->x1 < a->x1) a->x1 = b->x1;
208    if (b->y1 < a->y1) a->y1 = b->y1;
209    if (b->x2 > a->x2) a->x2 = b->x2;
210    if (b->y2 > a->y2) a->y2 = b->y2;
211}
212
213int
214skin_box_minmax_to_rect( SkinBox*  box, SkinRect*  r )
215{
216    if (box->x1 > box->x2) {
217        r->pos.x = r->pos.y = r->size.w = r->size.h = 0;
218        return 0;
219    }
220    skin_box_to_rect( box, r );
221    return 1;
222}
223
224void
225skin_box_from_rect( SkinBox*  box, SkinRect*  r )
226{
227    box->x1 = r->pos.x;
228    box->y1 = r->pos.y;
229    box->x2 = r->size.w + box->x1;
230    box->y2 = r->size.h + box->y1;
231}
232
233void
234skin_box_to_rect( SkinBox*  box, SkinRect*  r )
235{
236    r->pos.x  = box->x1;
237    r->pos.y  = box->y1;
238    r->size.w = box->x2 - box->x1;
239    r->size.h = box->y2 - box->y1;
240}
241
242