1 : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Vladimir Vukicevic <vladimir@pobox.com>
19 : * Portions created by the Initial Developer are Copyright (C) 2009
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either the GNU General Public License Version 2 or later (the "GPL"), or
26 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 : #ifndef _CANVASUTILS_H_
39 : #define _CANVASUTILS_H_
40 :
41 : #include "prtypes.h"
42 :
43 : #include "CheckedInt.h"
44 :
45 : class nsHTMLCanvasElement;
46 : class nsIPrincipal;
47 :
48 : namespace mozilla {
49 :
50 : namespace gfx {
51 : class Matrix;
52 : }
53 :
54 : namespace CanvasUtils {
55 :
56 : using namespace gfx;
57 :
58 : // Check that the rectangle [x,y,w,h] is a subrectangle of [0,0,realWidth,realHeight]
59 :
60 0 : inline bool CheckSaneSubrectSize(PRInt32 x, PRInt32 y, PRInt32 w, PRInt32 h,
61 : PRInt32 realWidth, PRInt32 realHeight) {
62 0 : CheckedInt32 checked_xmost = CheckedInt32(x) + w;
63 0 : CheckedInt32 checked_ymost = CheckedInt32(y) + h;
64 :
65 : return w >= 0 && h >= 0 && x >= 0 && y >= 0 &&
66 0 : checked_xmost.valid() &&
67 0 : checked_xmost.value() <= realWidth &&
68 0 : checked_ymost.valid() &&
69 0 : checked_ymost.value() <= realHeight;
70 : }
71 :
72 : // Flag aCanvasElement as write-only if drawing an image with aPrincipal
73 : // onto it would make it such.
74 :
75 : void DoDrawImageSecurityCheck(nsHTMLCanvasElement *aCanvasElement,
76 : nsIPrincipal *aPrincipal,
77 : bool forceWriteOnly,
78 : bool CORSUsed);
79 :
80 : // Make a double out of |v|, treating undefined values as 0.0 (for
81 : // the sake of sparse arrays). Return true iff coercion
82 : // succeeded.
83 : bool CoerceDouble(jsval v, double* d);
84 :
85 : // Return true iff the conversion succeeded, false otherwise. *rv is
86 : // the value to return to script if this returns false.
87 : bool JSValToMatrix(JSContext* cx, const jsval& val,
88 : gfxMatrix* matrix, nsresult* rv);
89 : bool JSValToMatrix(JSContext* cx, const jsval& val,
90 : Matrix* matrix, nsresult* rv);
91 :
92 : nsresult MatrixToJSVal(const gfxMatrix& matrix,
93 : JSContext* cx, jsval* val);
94 : nsresult MatrixToJSVal(const Matrix& matrix,
95 : JSContext* cx, jsval* val);
96 :
97 : /* Float validation stuff */
98 : #define VALIDATE(_f) if (!NS_finite(_f)) return false
99 :
100 0 : inline bool FloatValidate (double f1) {
101 0 : VALIDATE(f1);
102 0 : return true;
103 : }
104 :
105 0 : inline bool FloatValidate (double f1, double f2) {
106 0 : VALIDATE(f1); VALIDATE(f2);
107 0 : return true;
108 : }
109 :
110 0 : inline bool FloatValidate (double f1, double f2, double f3) {
111 0 : VALIDATE(f1); VALIDATE(f2); VALIDATE(f3);
112 0 : return true;
113 : }
114 :
115 0 : inline bool FloatValidate (double f1, double f2, double f3, double f4) {
116 0 : VALIDATE(f1); VALIDATE(f2); VALIDATE(f3); VALIDATE(f4);
117 0 : return true;
118 : }
119 :
120 0 : inline bool FloatValidate (double f1, double f2, double f3, double f4, double f5) {
121 0 : VALIDATE(f1); VALIDATE(f2); VALIDATE(f3); VALIDATE(f4); VALIDATE(f5);
122 0 : return true;
123 : }
124 :
125 0 : inline bool FloatValidate (double f1, double f2, double f3, double f4, double f5, double f6) {
126 0 : VALIDATE(f1); VALIDATE(f2); VALIDATE(f3); VALIDATE(f4); VALIDATE(f5); VALIDATE(f6);
127 0 : return true;
128 : }
129 :
130 : #undef VALIDATE
131 :
132 : template<typename T>
133 : nsresult
134 : JSValToDashArray(JSContext* cx, const jsval& val,
135 : FallibleTArray<T>& dashArray);
136 :
137 : template<typename T>
138 : nsresult
139 : DashArrayToJSVal(FallibleTArray<T>& dashArray,
140 : JSContext* cx, jsval* val);
141 :
142 : template<typename T>
143 : nsresult
144 : JSValToDashArray(JSContext* cx, const jsval& patternArray,
145 0 : FallibleTArray<T>& dashes)
146 : {
147 : // The cap is pretty arbitrary. 16k should be enough for
148 : // anybody...
149 : static const uint32_t MAX_NUM_DASHES = 1 << 14;
150 :
151 0 : if (!JSVAL_IS_PRIMITIVE(patternArray)) {
152 0 : JSObject* obj = JSVAL_TO_OBJECT(patternArray);
153 : uint32_t length;
154 0 : if (!JS_GetArrayLength(cx, obj, &length)) {
155 : // Not an array-like thing
156 0 : return NS_ERROR_INVALID_ARG;
157 0 : } else if (length > MAX_NUM_DASHES) {
158 : // Too many dashes in the pattern
159 0 : return NS_ERROR_ILLEGAL_VALUE;
160 : }
161 :
162 0 : bool haveNonzeroElement = false;
163 0 : for (uint32 i = 0; i < length; ++i) {
164 : jsval elt;
165 : double d;
166 0 : if (!JS_GetElement(cx, obj, i, &elt)) {
167 0 : return NS_ERROR_FAILURE;
168 : }
169 0 : if (!(CoerceDouble(elt, &d) &&
170 : FloatValidate(d) &&
171 : d >= 0.0)) {
172 : // Pattern elements must be finite "numbers" >= 0.
173 0 : return NS_ERROR_INVALID_ARG;
174 0 : } else if (d > 0.0) {
175 0 : haveNonzeroElement = true;
176 : }
177 0 : if (!dashes.AppendElement(d)) {
178 0 : return NS_ERROR_OUT_OF_MEMORY;
179 : }
180 : }
181 :
182 0 : if (dashes.Length() > 0 && !haveNonzeroElement) {
183 : // An all-zero pattern makes no sense.
184 0 : return NS_ERROR_ILLEGAL_VALUE;
185 : }
186 0 : } else if (!(JSVAL_IS_VOID(patternArray) || JSVAL_IS_NULL(patternArray))) {
187 : // undefined and null mean "reset to no dash". Any other
188 : // random garbage is a type error.
189 0 : return NS_ERROR_INVALID_ARG;
190 : }
191 :
192 0 : return NS_OK;
193 : }
194 :
195 : template<typename T>
196 : nsresult
197 : DashArrayToJSVal(FallibleTArray<T>& dashes,
198 0 : JSContext* cx, jsval* val)
199 : {
200 0 : if (dashes.IsEmpty()) {
201 0 : *val = JSVAL_NULL;
202 : } else {
203 0 : JSObject* obj = JS_NewArrayObject(cx, dashes.Length(), nsnull);
204 0 : if (!obj) {
205 0 : return NS_ERROR_OUT_OF_MEMORY;
206 : }
207 0 : for (PRUint32 i = 0; i < dashes.Length(); ++i) {
208 0 : double d = dashes[i];
209 0 : jsval elt = DOUBLE_TO_JSVAL(d);
210 0 : if (!JS_SetElement(cx, obj, i, &elt)) {
211 0 : return NS_ERROR_FAILURE;
212 : }
213 : }
214 0 : *val = OBJECT_TO_JSVAL(obj);
215 : }
216 0 : return NS_OK;
217 : }
218 :
219 : }
220 : }
221 :
222 : #endif /* _CANVASUTILS_H_ */
|