SkPoint.h revision b7d956df4665e06f3ae98cb696cef7c04452ab8e
1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef SkPoint_DEFINED
18#define SkPoint_DEFINED
19
20#include "SkMath.h"
21#include "SkScalar.h"
22
23/** \struct SkIPoint
24
25    SkIPoint holds two 32 bit integer coordinates
26*/
27struct SkIPoint {
28    int32_t fX, fY;
29
30    static SkIPoint Make(int32_t x, int32_t y) {
31        SkIPoint pt;
32        pt.set(x, y);
33        return pt;
34    }
35
36    int32_t x() const { return fX; }
37    int32_t y() const { return fY; }
38    void setX(int32_t x) { fX = x; }
39    void setY(int32_t y) { fY = y; }
40
41    /**
42     *  Returns true iff fX and fY are both zero.
43     */
44    bool isZero() const { return (fX | fY) == 0; }
45
46    /**
47     *  Set both fX and fY to zero. Same as set(0, 0)
48     */
49    void setZero() { fX = fY = 0; }
50
51    /** Set the x and y values of the point. */
52    void set(int32_t x, int32_t y) { fX = x; fY = y; }
53
54    /** Rotate the point clockwise, writing the new point into dst
55        It is legal for dst == this
56    */
57    void rotateCW(SkIPoint* dst) const;
58
59    /** Rotate the point clockwise, writing the new point back into the point
60    */
61
62    void rotateCW() { this->rotateCW(this); }
63
64    /** Rotate the point counter-clockwise, writing the new point into dst.
65        It is legal for dst == this
66    */
67    void rotateCCW(SkIPoint* dst) const;
68
69    /** Rotate the point counter-clockwise, writing the new point back into
70        the point
71    */
72    void rotateCCW() { this->rotateCCW(this); }
73
74    /** Negate the X and Y coordinates of the point.
75    */
76    void negate() { fX = -fX; fY = -fY; }
77
78    /** Return a new point whose X and Y coordinates are the negative of the
79        original point's
80    */
81    SkIPoint operator-() const {
82        SkIPoint neg;
83        neg.fX = -fX;
84        neg.fY = -fY;
85        return neg;
86    }
87
88    /** Add v's coordinates to this point's */
89    void operator+=(const SkIPoint& v) {
90        fX += v.fX;
91        fY += v.fY;
92    }
93
94    /** Subtract v's coordinates from this point's */
95    void operator-=(const SkIPoint& v) {
96        fX -= v.fX;
97        fY -= v.fY;
98    }
99
100    /** Returns true if the point's coordinates equal (x,y) */
101    bool equals(int32_t x, int32_t y) const {
102        return fX == x && fY == y;
103    }
104
105    friend bool operator==(const SkIPoint& a, const SkIPoint& b) {
106        return a.fX == b.fX && a.fY == b.fY;
107    }
108
109    friend bool operator!=(const SkIPoint& a, const SkIPoint& b) {
110        return a.fX != b.fX || a.fY != b.fY;
111    }
112
113    /** Returns a new point whose coordinates are the difference between
114        a and b (i.e. a - b)
115    */
116    friend SkIPoint operator-(const SkIPoint& a, const SkIPoint& b) {
117        SkIPoint v;
118        v.set(a.fX - b.fX, a.fY - b.fY);
119        return v;
120    }
121
122    /** Returns a new point whose coordinates are the sum of a and b (a + b)
123    */
124    friend SkIPoint operator+(const SkIPoint& a, const SkIPoint& b) {
125        SkIPoint v;
126        v.set(a.fX + b.fX, a.fY + b.fY);
127        return v;
128    }
129
130    /** Returns the dot product of a and b, treating them as 2D vectors
131    */
132    static int32_t DotProduct(const SkIPoint& a, const SkIPoint& b) {
133        return a.fX * b.fX + a.fY * b.fY;
134    }
135
136    /** Returns the cross product of a and b, treating them as 2D vectors
137    */
138    static int32_t CrossProduct(const SkIPoint& a, const SkIPoint& b) {
139        return a.fX * b.fY - a.fY * b.fX;
140    }
141};
142
143struct SK_API SkPoint {
144    SkScalar    fX, fY;
145
146    static SkPoint Make(SkScalar x, SkScalar y) {
147        SkPoint pt;
148        pt.set(x, y);
149        return pt;
150    }
151
152    SkScalar x() const { return fX; }
153    SkScalar y() const { return fY; }
154
155    /** Set the point's X and Y coordinates */
156    void set(SkScalar x, SkScalar y) { fX = x; fY = y; }
157
158    /** Set the point's X and Y coordinates by automatically promoting (x,y) to
159        SkScalar values.
160    */
161    void iset(int32_t x, int32_t y) {
162        fX = SkIntToScalar(x);
163        fY = SkIntToScalar(y);
164    }
165
166    /** Set the point's X and Y coordinates by automatically promoting p's
167        coordinates to SkScalar values.
168    */
169    void iset(const SkIPoint& p) {
170        fX = SkIntToScalar(p.fX);
171        fY = SkIntToScalar(p.fY);
172    }
173
174    /** Return the euclidian distance from (0,0) to the point
175    */
176    SkScalar length() const { return SkPoint::Length(fX, fY); }
177
178    /** Set the point (vector) to be unit-length in the same direction as it
179        currently is, and return its old length. If the old length is
180        degenerately small (nearly zero), do nothing and return false, otherwise
181        return true.
182    */
183    bool normalize();
184
185    /** Set the point (vector) to be unit-length in the same direction as the
186        x,y params. If the vector (x,y) has a degenerate length (i.e. nearly 0)
187        then return false and do nothing, otherwise return true.
188    */
189    bool setNormalize(SkScalar x, SkScalar y);
190
191    /** Scale the point (vector) to have the specified length, and return that
192        length. If the original length is degenerately small (nearly zero),
193        do nothing and return false, otherwise return true.
194    */
195    bool setLength(SkScalar length);
196
197    /** Set the point (vector) to have the specified length in the same
198     direction as (x,y). If the vector (x,y) has a degenerate length
199     (i.e. nearly 0) then return false and do nothing, otherwise return true.
200    */
201    bool setLength(SkScalar x, SkScalar y, SkScalar length);
202
203    /** Scale the point's coordinates by scale, writing the answer into dst.
204        It is legal for dst == this.
205    */
206    void scale(SkScalar scale, SkPoint* dst) const;
207
208    /** Scale the point's coordinates by scale, writing the answer back into
209        the point.
210    */
211    void scale(SkScalar value) { this->scale(value, this); }
212
213    /** Rotate the point clockwise by 90 degrees, writing the answer into dst.
214        It is legal for dst == this.
215    */
216    void rotateCW(SkPoint* dst) const;
217
218    /** Rotate the point clockwise by 90 degrees, writing the answer back into
219        the point.
220    */
221    void rotateCW() { this->rotateCW(this); }
222
223    /** Rotate the point counter-clockwise by 90 degrees, writing the answer
224        into dst. It is legal for dst == this.
225    */
226    void rotateCCW(SkPoint* dst) const;
227
228    /** Rotate the point counter-clockwise by 90 degrees, writing the answer
229        back into the point.
230    */
231    void rotateCCW() { this->rotateCCW(this); }
232
233    /** Negate the point's coordinates
234    */
235    void negate() {
236        fX = -fX;
237        fY = -fY;
238    }
239
240    /** Returns a new point whose coordinates are the negative of the point's
241    */
242    SkPoint operator-() const {
243        SkPoint neg;
244        neg.fX = -fX;
245        neg.fY = -fY;
246        return neg;
247    }
248
249    /** Add v's coordinates to the point's
250    */
251    void operator+=(const SkPoint& v) {
252        fX += v.fX;
253        fY += v.fY;
254    }
255
256    /** Subtract v's coordinates from the point's
257    */
258    void operator-=(const SkPoint& v) {
259        fX -= v.fX;
260        fY -= v.fY;
261    }
262
263    /** Returns true if the point's coordinates equal (x,y)
264    */
265    bool equals(SkScalar x, SkScalar y) const { return fX == x && fY == y; }
266
267    friend bool operator==(const SkPoint& a, const SkPoint& b) {
268        return a.fX == b.fX && a.fY == b.fY;
269    }
270
271    friend bool operator!=(const SkPoint& a, const SkPoint& b) {
272        return a.fX != b.fX || a.fY != b.fY;
273    }
274
275    /** Returns a new point whose coordinates are the difference between
276        a's and b's (a - b)
277    */
278    friend SkPoint operator-(const SkPoint& a, const SkPoint& b) {
279        SkPoint v;
280        v.set(a.fX - b.fX, a.fY - b.fY);
281        return v;
282    }
283
284    /** Returns a new point whose coordinates are the sum of a's and b's (a + b)
285    */
286    friend SkPoint operator+(const SkPoint& a, const SkPoint& b) {
287        SkPoint v;
288        v.set(a.fX + b.fX, a.fY + b.fY);
289        return v;
290    }
291
292    /** Returns the euclidian distance from (0,0) to (x,y)
293    */
294    static SkScalar Length(SkScalar x, SkScalar y);
295
296    /** Normalize pt, returning its previous length. If the prev length is too
297        small (degenerate), return 0 and leave pt unchanged.
298     */
299    static SkScalar Normalize(SkPoint* pt);
300
301    /** Returns the euclidian distance between a and b
302    */
303    static SkScalar Distance(const SkPoint& a, const SkPoint& b) {
304        return Length(a.fX - b.fX, a.fY - b.fY);
305    }
306
307    /** Returns the dot product of a and b, treating them as 2D vectors
308    */
309    static SkScalar DotProduct(const SkPoint& a, const SkPoint& b) {
310        return SkScalarMul(a.fX, b.fX) + SkScalarMul(a.fY, b.fY);
311    }
312
313    /** Returns the cross product of a and b, treating them as 2D vectors
314    */
315    static SkScalar CrossProduct(const SkPoint& a, const SkPoint& b) {
316        return SkScalarMul(a.fX, b.fY) - SkScalarMul(a.fY, b.fX);
317    }
318};
319
320typedef SkPoint SkVector;
321
322#endif
323
324