/src/cairo/src/cairo-misc.c
Line | Count | Source |
1 | | /* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */ |
2 | | /* cairo - a vector graphics library with display and print output |
3 | | * |
4 | | * Copyright © 2002 University of Southern California |
5 | | * Copyright © 2005 Red Hat, Inc. |
6 | | * Copyright © 2007 Adrian Johnson |
7 | | * |
8 | | * This library is free software; you can redistribute it and/or |
9 | | * modify it either under the terms of the GNU Lesser General Public |
10 | | * License version 2.1 as published by the Free Software Foundation |
11 | | * (the "LGPL") or, at your option, under the terms of the Mozilla |
12 | | * Public License Version 1.1 (the "MPL"). If you do not alter this |
13 | | * notice, a recipient may use your version of this file under either |
14 | | * the MPL or the LGPL. |
15 | | * |
16 | | * You should have received a copy of the LGPL along with this library |
17 | | * in the file COPYING-LGPL-2.1; if not, write to the Free Software |
18 | | * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA |
19 | | * You should have received a copy of the MPL along with this library |
20 | | * in the file COPYING-MPL-1.1 |
21 | | * |
22 | | * The contents of this file are subject to the Mozilla Public License |
23 | | * Version 1.1 (the "License"); you may not use this file except in |
24 | | * compliance with the License. You may obtain a copy of the License at |
25 | | * http://www.mozilla.org/MPL/ |
26 | | * |
27 | | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY |
28 | | * OF ANY KIND, either express or implied. See the LGPL or the MPL for |
29 | | * the specific language governing rights and limitations. |
30 | | * |
31 | | * The Original Code is the cairo graphics library. |
32 | | * |
33 | | * The Initial Developer of the Original Code is University of Southern |
34 | | * California. |
35 | | * |
36 | | * Contributor(s): |
37 | | * Carl D. Worth <cworth@cworth.org> |
38 | | * Adrian Johnson <ajohnson@redneon.com> |
39 | | */ |
40 | | |
41 | | #include "cairoint.h" |
42 | | #include "cairo-error-private.h" |
43 | | |
44 | | #include <stdio.h> |
45 | | #include <stdlib.h> |
46 | | #include <errno.h> |
47 | | #include <locale.h> |
48 | | #ifdef HAVE_XLOCALE_H |
49 | | #include <xlocale.h> |
50 | | #endif |
51 | | #if HAVE_FCNTL_H |
52 | | #include <fcntl.h> |
53 | | #endif |
54 | | |
55 | | COMPILE_TIME_ASSERT ((int)CAIRO_STATUS_LAST_STATUS < (int)CAIRO_INT_STATUS_UNSUPPORTED); |
56 | | COMPILE_TIME_ASSERT (CAIRO_INT_STATUS_LAST_STATUS <= 127); |
57 | | |
58 | | /** |
59 | | * SECTION:cairo-status |
60 | | * @Title: Error handling |
61 | | * @Short_Description: Decoding cairo's status |
62 | | * @See_Also: cairo_status(), cairo_surface_status(), cairo_pattern_status(), |
63 | | * cairo_font_face_status(), cairo_scaled_font_status(), |
64 | | * cairo_region_status() |
65 | | * |
66 | | * Cairo uses a single status type to represent all kinds of errors. A status |
67 | | * value of %CAIRO_STATUS_SUCCESS represents no error and has an integer value |
68 | | * of zero. All other status values represent an error. |
69 | | * |
70 | | * Cairo's error handling is designed to be easy to use and safe. All major |
71 | | * cairo objects <firstterm>retain</firstterm> an error status internally which |
72 | | * can be queried anytime by the users using cairo*_status() calls. In |
73 | | * the mean time, it is safe to call all cairo functions normally even if the |
74 | | * underlying object is in an error status. This means that no error handling |
75 | | * code is required before or after each individual cairo function call. |
76 | | **/ |
77 | | |
78 | | /* Public stuff */ |
79 | | |
80 | | /** |
81 | | * cairo_status_to_string: |
82 | | * @status: a cairo status |
83 | | * |
84 | | * Provides a human-readable description of a #cairo_status_t. |
85 | | * |
86 | | * Returns: a string representation of the status |
87 | | * |
88 | | * Since: 1.0 |
89 | | **/ |
90 | | const char * |
91 | | cairo_status_to_string (cairo_status_t status) |
92 | 4 | { |
93 | 4 | switch (status) { |
94 | 0 | case CAIRO_STATUS_SUCCESS: |
95 | 0 | return "no error has occurred"; |
96 | 0 | case CAIRO_STATUS_NO_MEMORY: |
97 | 0 | return "out of memory"; |
98 | 0 | case CAIRO_STATUS_INVALID_RESTORE: |
99 | 0 | return "cairo_restore() without matching cairo_save()"; |
100 | 0 | case CAIRO_STATUS_INVALID_POP_GROUP: |
101 | 0 | return "no saved group to pop, i.e. cairo_pop_group() without matching cairo_push_group()"; |
102 | 0 | case CAIRO_STATUS_NO_CURRENT_POINT: |
103 | 0 | return "no current point defined"; |
104 | 0 | case CAIRO_STATUS_INVALID_MATRIX: |
105 | 0 | return "invalid matrix (not invertible)"; |
106 | 0 | case CAIRO_STATUS_INVALID_STATUS: |
107 | 0 | return "invalid value for an input cairo_status_t"; |
108 | 0 | case CAIRO_STATUS_NULL_POINTER: |
109 | 0 | return "NULL pointer"; |
110 | 0 | case CAIRO_STATUS_INVALID_STRING: |
111 | 0 | return "input string not valid UTF-8"; |
112 | 0 | case CAIRO_STATUS_INVALID_PATH_DATA: |
113 | 0 | return "input path data not valid"; |
114 | 0 | case CAIRO_STATUS_READ_ERROR: |
115 | 0 | return "error while reading from input stream"; |
116 | 0 | case CAIRO_STATUS_WRITE_ERROR: |
117 | 0 | return "error while writing to output stream"; |
118 | 0 | case CAIRO_STATUS_SURFACE_FINISHED: |
119 | 0 | return "the target surface has been finished"; |
120 | 0 | case CAIRO_STATUS_SURFACE_TYPE_MISMATCH: |
121 | 0 | return "the surface type is not appropriate for the operation"; |
122 | 0 | case CAIRO_STATUS_PATTERN_TYPE_MISMATCH: |
123 | 0 | return "the pattern type is not appropriate for the operation"; |
124 | 0 | case CAIRO_STATUS_INVALID_CONTENT: |
125 | 0 | return "invalid value for an input cairo_content_t"; |
126 | 0 | case CAIRO_STATUS_INVALID_FORMAT: |
127 | 0 | return "invalid value for an input cairo_format_t"; |
128 | 0 | case CAIRO_STATUS_INVALID_VISUAL: |
129 | 0 | return "invalid value for an input Visual*"; |
130 | 0 | case CAIRO_STATUS_FILE_NOT_FOUND: |
131 | 0 | return "file not found"; |
132 | 2 | case CAIRO_STATUS_INVALID_DASH: |
133 | 2 | return "invalid value for a dash setting"; |
134 | 0 | case CAIRO_STATUS_INVALID_DSC_COMMENT: |
135 | 0 | return "invalid value for a DSC comment"; |
136 | 0 | case CAIRO_STATUS_INVALID_INDEX: |
137 | 0 | return "invalid index passed to getter"; |
138 | 0 | case CAIRO_STATUS_CLIP_NOT_REPRESENTABLE: |
139 | 0 | return "clip region not representable in desired format"; |
140 | 0 | case CAIRO_STATUS_TEMP_FILE_ERROR: |
141 | 0 | return "error creating or writing to a temporary file"; |
142 | 0 | case CAIRO_STATUS_INVALID_STRIDE: |
143 | 0 | return "invalid value for stride"; |
144 | 0 | case CAIRO_STATUS_FONT_TYPE_MISMATCH: |
145 | 0 | return "the font type is not appropriate for the operation"; |
146 | 0 | case CAIRO_STATUS_USER_FONT_IMMUTABLE: |
147 | 0 | return "the user-font is immutable"; |
148 | 0 | case CAIRO_STATUS_USER_FONT_ERROR: |
149 | 0 | return "error occurred in a user-font callback function"; |
150 | 0 | case CAIRO_STATUS_NEGATIVE_COUNT: |
151 | 0 | return "negative number used where it is not allowed"; |
152 | 0 | case CAIRO_STATUS_INVALID_CLUSTERS: |
153 | 0 | return "input clusters do not represent the accompanying text and glyph arrays"; |
154 | 0 | case CAIRO_STATUS_INVALID_SLANT: |
155 | 0 | return "invalid value for an input cairo_font_slant_t"; |
156 | 0 | case CAIRO_STATUS_INVALID_WEIGHT: |
157 | 0 | return "invalid value for an input cairo_font_weight_t"; |
158 | 0 | case CAIRO_STATUS_INVALID_SIZE: |
159 | 0 | return "invalid value (typically too big) for the size of the input (surface, pattern, etc.)"; |
160 | 0 | case CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED: |
161 | 0 | return "user-font method not implemented"; |
162 | 0 | case CAIRO_STATUS_DEVICE_TYPE_MISMATCH: |
163 | 0 | return "the device type is not appropriate for the operation"; |
164 | 0 | case CAIRO_STATUS_DEVICE_ERROR: |
165 | 0 | return "an operation to the device caused an unspecified error"; |
166 | 0 | case CAIRO_STATUS_INVALID_MESH_CONSTRUCTION: |
167 | 0 | return "invalid operation during mesh pattern construction"; |
168 | 0 | case CAIRO_STATUS_DEVICE_FINISHED: |
169 | 0 | return "the target device has been finished"; |
170 | 0 | case CAIRO_STATUS_JBIG2_GLOBAL_MISSING: |
171 | 0 | return "CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID used but no CAIRO_MIME_TYPE_JBIG2_GLOBAL data provided"; |
172 | 0 | case CAIRO_STATUS_PNG_ERROR: |
173 | 0 | return "error occurred in libpng while reading from or writing to a PNG file"; |
174 | 2 | case CAIRO_STATUS_FREETYPE_ERROR: |
175 | 2 | return "error occurred in libfreetype"; |
176 | 0 | case CAIRO_STATUS_WIN32_GDI_ERROR: |
177 | 0 | return "error occurred in the Windows Graphics Device Interface"; |
178 | 0 | case CAIRO_STATUS_TAG_ERROR: |
179 | 0 | return "invalid tag name, attributes, or nesting"; |
180 | 0 | case CAIRO_STATUS_DWRITE_ERROR: |
181 | 0 | return "Window Direct Write error"; |
182 | 0 | case CAIRO_STATUS_SVG_FONT_ERROR: |
183 | 0 | return "error occured while rendering an OpenType-SVG font"; |
184 | 0 | default: |
185 | 0 | case CAIRO_STATUS_LAST_STATUS: |
186 | 0 | return "<unknown error status>"; |
187 | 4 | } |
188 | 4 | } |
189 | | |
190 | | /** |
191 | | * cairo_glyph_allocate: |
192 | | * @num_glyphs: number of glyphs to allocate |
193 | | * |
194 | | * Allocates an array of #cairo_glyph_t's. |
195 | | * This function is only useful in implementations of |
196 | | * #cairo_user_scaled_font_text_to_glyphs_func_t where the user |
197 | | * needs to allocate an array of glyphs that cairo will free. |
198 | | * For all other uses, user can use their own allocation method |
199 | | * for glyphs. |
200 | | * |
201 | | * This function returns %NULL if @num_glyphs is not positive, |
202 | | * or if out of memory. That means, the %NULL return value |
203 | | * signals out-of-memory only if @num_glyphs was positive. |
204 | | * |
205 | | * Returns: the newly allocated array of glyphs that should be |
206 | | * freed using cairo_glyph_free() |
207 | | * |
208 | | * Since: 1.8 |
209 | | **/ |
210 | | cairo_glyph_t * |
211 | | cairo_glyph_allocate (int num_glyphs) |
212 | 13.3k | { |
213 | 13.3k | if (num_glyphs <= 0) |
214 | 0 | return NULL; |
215 | | |
216 | 13.3k | return _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t)); |
217 | 13.3k | } |
218 | | |
219 | | /** |
220 | | * cairo_glyph_free: |
221 | | * @glyphs: array of glyphs to free, or %NULL |
222 | | * |
223 | | * Frees an array of #cairo_glyph_t's allocated using cairo_glyph_allocate(). |
224 | | * This function is only useful to free glyph array returned |
225 | | * by cairo_scaled_font_text_to_glyphs() where cairo returns |
226 | | * an array of glyphs that the user will free. |
227 | | * For all other uses, user can use their own allocation method |
228 | | * for glyphs. |
229 | | * |
230 | | * Since: 1.8 |
231 | | **/ |
232 | | void |
233 | | cairo_glyph_free (cairo_glyph_t *glyphs) |
234 | 131 | { |
235 | 131 | free (glyphs); |
236 | 131 | } |
237 | | |
238 | | /** |
239 | | * cairo_text_cluster_allocate: |
240 | | * @num_clusters: number of text_clusters to allocate |
241 | | * |
242 | | * Allocates an array of #cairo_text_cluster_t's. |
243 | | * This function is only useful in implementations of |
244 | | * #cairo_user_scaled_font_text_to_glyphs_func_t where the user |
245 | | * needs to allocate an array of text clusters that cairo will free. |
246 | | * For all other uses, user can use their own allocation method |
247 | | * for text clusters. |
248 | | * |
249 | | * This function returns %NULL if @num_clusters is not positive, |
250 | | * or if out of memory. That means, the %NULL return value |
251 | | * signals out-of-memory only if @num_clusters was positive. |
252 | | * |
253 | | * Returns: the newly allocated array of text clusters that should be |
254 | | * freed using cairo_text_cluster_free() |
255 | | * |
256 | | * Since: 1.8 |
257 | | **/ |
258 | | cairo_text_cluster_t * |
259 | | cairo_text_cluster_allocate (int num_clusters) |
260 | 0 | { |
261 | 0 | if (num_clusters <= 0) |
262 | 0 | return NULL; |
263 | | |
264 | 0 | return _cairo_malloc_ab (num_clusters, sizeof (cairo_text_cluster_t)); |
265 | 0 | } |
266 | | |
267 | | /** |
268 | | * cairo_text_cluster_free: |
269 | | * @clusters: array of text clusters to free, or %NULL |
270 | | * |
271 | | * Frees an array of #cairo_text_cluster's allocated using cairo_text_cluster_allocate(). |
272 | | * This function is only useful to free text cluster array returned |
273 | | * by cairo_scaled_font_text_to_glyphs() where cairo returns |
274 | | * an array of text clusters that the user will free. |
275 | | * For all other uses, user can use their own allocation method |
276 | | * for text clusters. |
277 | | * |
278 | | * Since: 1.8 |
279 | | **/ |
280 | | void |
281 | | cairo_text_cluster_free (cairo_text_cluster_t *clusters) |
282 | 0 | { |
283 | 0 | free (clusters); |
284 | 0 | } |
285 | | |
286 | | /* Private stuff */ |
287 | | |
288 | | /** |
289 | | * _cairo_validate_text_clusters: |
290 | | * @utf8: UTF-8 text |
291 | | * @utf8_len: length of @utf8 in bytes |
292 | | * @glyphs: array of glyphs |
293 | | * @num_glyphs: number of glyphs |
294 | | * @clusters: array of cluster mapping information |
295 | | * @num_clusters: number of clusters in the mapping |
296 | | * @cluster_flags: cluster flags |
297 | | * |
298 | | * Check that clusters cover the entire glyphs and utf8 arrays, |
299 | | * and that cluster boundaries are UTF-8 boundaries. |
300 | | * |
301 | | * Return value: %CAIRO_STATUS_SUCCESS upon success, or |
302 | | * %CAIRO_STATUS_INVALID_CLUSTERS on error. |
303 | | * The error is either invalid UTF-8 input, |
304 | | * or bad cluster mapping. |
305 | | **/ |
306 | | cairo_status_t |
307 | | _cairo_validate_text_clusters (const char *utf8, |
308 | | int utf8_len, |
309 | | const cairo_glyph_t *glyphs, |
310 | | int num_glyphs, |
311 | | const cairo_text_cluster_t *clusters, |
312 | | int num_clusters, |
313 | | cairo_text_cluster_flags_t cluster_flags) |
314 | 139k | { |
315 | 139k | cairo_status_t status; |
316 | 139k | unsigned int n_bytes = 0; |
317 | 139k | unsigned int n_glyphs = 0; |
318 | 139k | int i; |
319 | | |
320 | 381k | for (i = 0; i < num_clusters; i++) { |
321 | 241k | int cluster_bytes = clusters[i].num_bytes; |
322 | 241k | int cluster_glyphs = clusters[i].num_glyphs; |
323 | | |
324 | 241k | if (cluster_bytes < 0 || cluster_glyphs < 0) |
325 | 0 | goto BAD; |
326 | | |
327 | | /* A cluster should cover at least one character or glyph. |
328 | | * I can't see any use for a 0,0 cluster. |
329 | | * I can't see an immediate use for a zero-text cluster |
330 | | * right now either, but they don't harm. |
331 | | * Zero-glyph clusters on the other hand are useful for |
332 | | * things like U+200C ZERO WIDTH NON-JOINER */ |
333 | 241k | if (cluster_bytes == 0 && cluster_glyphs == 0) |
334 | 0 | goto BAD; |
335 | | |
336 | | /* Since n_bytes and n_glyphs are unsigned, but the rest of |
337 | | * values involved are signed, we can detect overflow easily */ |
338 | 241k | if (n_bytes+cluster_bytes > (unsigned int)utf8_len || n_glyphs+cluster_glyphs > (unsigned int)num_glyphs) |
339 | 0 | goto BAD; |
340 | | |
341 | | /* Make sure we've got valid UTF-8 for the cluster */ |
342 | 241k | status = _cairo_utf8_to_ucs4 (utf8+n_bytes, cluster_bytes, NULL, NULL); |
343 | 241k | if (unlikely (status)) |
344 | 0 | return _cairo_error (CAIRO_STATUS_INVALID_CLUSTERS); |
345 | | |
346 | 241k | n_bytes += cluster_bytes ; |
347 | 241k | n_glyphs += cluster_glyphs; |
348 | 241k | } |
349 | | |
350 | 139k | if (n_bytes != (unsigned int) utf8_len || n_glyphs != (unsigned int) num_glyphs) { |
351 | 0 | BAD: |
352 | 0 | return _cairo_error (CAIRO_STATUS_INVALID_CLUSTERS); |
353 | 0 | } |
354 | | |
355 | 139k | return CAIRO_STATUS_SUCCESS; |
356 | 139k | } |
357 | | |
358 | | /** |
359 | | * _cairo_operator_bounded_by_mask: |
360 | | * @op: a #cairo_operator_t |
361 | | * |
362 | | * A bounded operator is one where mask pixel |
363 | | * of zero results in no effect on the destination image. |
364 | | * |
365 | | * Unbounded operators often require special handling; if you, for |
366 | | * example, draw trapezoids with an unbounded operator, the effect |
367 | | * extends past the bounding box of the trapezoids. |
368 | | * |
369 | | * Return value: %TRUE if the operator is bounded by the mask operand |
370 | | **/ |
371 | | cairo_bool_t |
372 | | _cairo_operator_bounded_by_mask (cairo_operator_t op) |
373 | 811k | { |
374 | 811k | switch (op) { |
375 | 0 | case CAIRO_OPERATOR_CLEAR: |
376 | 608 | case CAIRO_OPERATOR_SOURCE: |
377 | 811k | case CAIRO_OPERATOR_OVER: |
378 | 811k | case CAIRO_OPERATOR_ATOP: |
379 | 811k | case CAIRO_OPERATOR_DEST: |
380 | 811k | case CAIRO_OPERATOR_DEST_OVER: |
381 | 811k | case CAIRO_OPERATOR_DEST_OUT: |
382 | 811k | case CAIRO_OPERATOR_XOR: |
383 | 811k | case CAIRO_OPERATOR_ADD: |
384 | 811k | case CAIRO_OPERATOR_SATURATE: |
385 | 811k | case CAIRO_OPERATOR_MULTIPLY: |
386 | 811k | case CAIRO_OPERATOR_SCREEN: |
387 | 811k | case CAIRO_OPERATOR_OVERLAY: |
388 | 811k | case CAIRO_OPERATOR_DARKEN: |
389 | 811k | case CAIRO_OPERATOR_LIGHTEN: |
390 | 811k | case CAIRO_OPERATOR_COLOR_DODGE: |
391 | 811k | case CAIRO_OPERATOR_COLOR_BURN: |
392 | 811k | case CAIRO_OPERATOR_HARD_LIGHT: |
393 | 811k | case CAIRO_OPERATOR_SOFT_LIGHT: |
394 | 811k | case CAIRO_OPERATOR_DIFFERENCE: |
395 | 811k | case CAIRO_OPERATOR_EXCLUSION: |
396 | 811k | case CAIRO_OPERATOR_HSL_HUE: |
397 | 811k | case CAIRO_OPERATOR_HSL_SATURATION: |
398 | 811k | case CAIRO_OPERATOR_HSL_COLOR: |
399 | 811k | case CAIRO_OPERATOR_HSL_LUMINOSITY: |
400 | 811k | return TRUE; |
401 | 0 | case CAIRO_OPERATOR_OUT: |
402 | 0 | case CAIRO_OPERATOR_IN: |
403 | 0 | case CAIRO_OPERATOR_DEST_IN: |
404 | 0 | case CAIRO_OPERATOR_DEST_ATOP: |
405 | 0 | return FALSE; |
406 | 0 | default: |
407 | 0 | ASSERT_NOT_REACHED; |
408 | 0 | return FALSE; /* squelch warning */ |
409 | 811k | } |
410 | 811k | } |
411 | | |
412 | | /** |
413 | | * _cairo_operator_bounded_by_source: |
414 | | * @op: a #cairo_operator_t |
415 | | * |
416 | | * A bounded operator is one where source pixels of zero |
417 | | * (in all four components, r, g, b and a) effect no change |
418 | | * in the resulting destination image. |
419 | | * |
420 | | * Unbounded operators often require special handling; if you, for |
421 | | * example, copy a surface with the SOURCE operator, the effect |
422 | | * extends past the bounding box of the source surface. |
423 | | * |
424 | | * Return value: %TRUE if the operator is bounded by the source operand |
425 | | **/ |
426 | | cairo_bool_t |
427 | | _cairo_operator_bounded_by_source (cairo_operator_t op) |
428 | 812k | { |
429 | 812k | switch (op) { |
430 | 811k | case CAIRO_OPERATOR_OVER: |
431 | 811k | case CAIRO_OPERATOR_ATOP: |
432 | 811k | case CAIRO_OPERATOR_DEST: |
433 | 811k | case CAIRO_OPERATOR_DEST_OVER: |
434 | 811k | case CAIRO_OPERATOR_DEST_OUT: |
435 | 811k | case CAIRO_OPERATOR_XOR: |
436 | 811k | case CAIRO_OPERATOR_ADD: |
437 | 811k | case CAIRO_OPERATOR_SATURATE: |
438 | 811k | case CAIRO_OPERATOR_MULTIPLY: |
439 | 811k | case CAIRO_OPERATOR_SCREEN: |
440 | 811k | case CAIRO_OPERATOR_OVERLAY: |
441 | 811k | case CAIRO_OPERATOR_DARKEN: |
442 | 811k | case CAIRO_OPERATOR_LIGHTEN: |
443 | 811k | case CAIRO_OPERATOR_COLOR_DODGE: |
444 | 811k | case CAIRO_OPERATOR_COLOR_BURN: |
445 | 811k | case CAIRO_OPERATOR_HARD_LIGHT: |
446 | 811k | case CAIRO_OPERATOR_SOFT_LIGHT: |
447 | 811k | case CAIRO_OPERATOR_DIFFERENCE: |
448 | 811k | case CAIRO_OPERATOR_EXCLUSION: |
449 | 811k | case CAIRO_OPERATOR_HSL_HUE: |
450 | 811k | case CAIRO_OPERATOR_HSL_SATURATION: |
451 | 811k | case CAIRO_OPERATOR_HSL_COLOR: |
452 | 811k | case CAIRO_OPERATOR_HSL_LUMINOSITY: |
453 | 811k | return TRUE; |
454 | 0 | case CAIRO_OPERATOR_CLEAR: |
455 | 608 | case CAIRO_OPERATOR_SOURCE: |
456 | 608 | case CAIRO_OPERATOR_OUT: |
457 | 608 | case CAIRO_OPERATOR_IN: |
458 | 608 | case CAIRO_OPERATOR_DEST_IN: |
459 | 608 | case CAIRO_OPERATOR_DEST_ATOP: |
460 | 608 | return FALSE; |
461 | 0 | default: |
462 | 0 | ASSERT_NOT_REACHED; |
463 | 0 | return FALSE; /* squelch warning */ |
464 | 812k | } |
465 | 812k | } |
466 | | |
467 | | uint32_t |
468 | | _cairo_operator_bounded_by_either (cairo_operator_t op) |
469 | 2.43M | { |
470 | 2.43M | switch (op) { |
471 | 2.43M | case CAIRO_OPERATOR_OVER: |
472 | 2.43M | case CAIRO_OPERATOR_ATOP: |
473 | 2.43M | case CAIRO_OPERATOR_DEST: |
474 | 2.43M | case CAIRO_OPERATOR_DEST_OVER: |
475 | 2.43M | case CAIRO_OPERATOR_DEST_OUT: |
476 | 2.43M | case CAIRO_OPERATOR_XOR: |
477 | 2.43M | case CAIRO_OPERATOR_ADD: |
478 | 2.43M | case CAIRO_OPERATOR_SATURATE: |
479 | 2.43M | case CAIRO_OPERATOR_MULTIPLY: |
480 | 2.43M | case CAIRO_OPERATOR_SCREEN: |
481 | 2.43M | case CAIRO_OPERATOR_OVERLAY: |
482 | 2.43M | case CAIRO_OPERATOR_DARKEN: |
483 | 2.43M | case CAIRO_OPERATOR_LIGHTEN: |
484 | 2.43M | case CAIRO_OPERATOR_COLOR_DODGE: |
485 | 2.43M | case CAIRO_OPERATOR_COLOR_BURN: |
486 | 2.43M | case CAIRO_OPERATOR_HARD_LIGHT: |
487 | 2.43M | case CAIRO_OPERATOR_SOFT_LIGHT: |
488 | 2.43M | case CAIRO_OPERATOR_DIFFERENCE: |
489 | 2.43M | case CAIRO_OPERATOR_EXCLUSION: |
490 | 2.43M | case CAIRO_OPERATOR_HSL_HUE: |
491 | 2.43M | case CAIRO_OPERATOR_HSL_SATURATION: |
492 | 2.43M | case CAIRO_OPERATOR_HSL_COLOR: |
493 | 2.43M | case CAIRO_OPERATOR_HSL_LUMINOSITY: |
494 | 2.43M | return CAIRO_OPERATOR_BOUND_BY_MASK | CAIRO_OPERATOR_BOUND_BY_SOURCE; |
495 | 0 | case CAIRO_OPERATOR_CLEAR: |
496 | 912 | case CAIRO_OPERATOR_SOURCE: |
497 | 912 | return CAIRO_OPERATOR_BOUND_BY_MASK; |
498 | 0 | case CAIRO_OPERATOR_OUT: |
499 | 0 | case CAIRO_OPERATOR_IN: |
500 | 0 | case CAIRO_OPERATOR_DEST_IN: |
501 | 0 | case CAIRO_OPERATOR_DEST_ATOP: |
502 | 0 | return 0; |
503 | 0 | default: |
504 | 0 | ASSERT_NOT_REACHED; |
505 | 0 | return FALSE; /* squelch warning */ |
506 | 2.43M | } |
507 | | |
508 | 2.43M | } |
509 | | |
510 | | #if DISABLE_SOME_FLOATING_POINT |
511 | | /* This function is identical to the C99 function lround(), except that it |
512 | | * performs arithmetic rounding (floor(d + .5) instead of away-from-zero rounding) and |
513 | | * has a valid input range of (INT_MIN, INT_MAX] instead of |
514 | | * [INT_MIN, INT_MAX]. It is much faster on both x86 and FPU-less systems |
515 | | * than other commonly used methods for rounding (lround, round, rint, lrint |
516 | | * or float (d + 0.5)). |
517 | | * |
518 | | * The reason why this function is much faster on x86 than other |
519 | | * methods is due to the fact that it avoids the fldcw instruction. |
520 | | * This instruction incurs a large performance penalty on modern Intel |
521 | | * processors due to how it prevents efficient instruction pipelining. |
522 | | * |
523 | | * The reason why this function is much faster on FPU-less systems is for |
524 | | * an entirely different reason. All common rounding methods involve multiple |
525 | | * floating-point operations. Each one of these operations has to be |
526 | | * emulated in software, which adds up to be a large performance penalty. |
527 | | * This function doesn't perform any floating-point calculations, and thus |
528 | | * avoids this penalty. |
529 | | */ |
530 | | int |
531 | | _cairo_lround (double d) |
532 | | { |
533 | | uint32_t top, shift_amount, output; |
534 | | union { |
535 | | double d; |
536 | | uint64_t ui64; |
537 | | uint32_t ui32[2]; |
538 | | } u; |
539 | | |
540 | | u.d = d; |
541 | | |
542 | | /* If the integer word order doesn't match the float word order, we swap |
543 | | * the words of the input double. This is needed because we will be |
544 | | * treating the whole double as a 64-bit unsigned integer. Notice that we |
545 | | * use WORDS_BIGENDIAN to detect the integer word order, which isn't |
546 | | * exactly correct because WORDS_BIGENDIAN refers to byte order, not word |
547 | | * order. Thus, we are making the assumption that the byte order is the |
548 | | * same as the integer word order which, on the modern machines that we |
549 | | * care about, is OK. |
550 | | */ |
551 | | #if ( defined(FLOAT_WORDS_BIGENDIAN) && !defined(WORDS_BIGENDIAN)) || \ |
552 | | (!defined(FLOAT_WORDS_BIGENDIAN) && defined(WORDS_BIGENDIAN)) |
553 | | { |
554 | | uint32_t temp = u.ui32[0]; |
555 | | u.ui32[0] = u.ui32[1]; |
556 | | u.ui32[1] = temp; |
557 | | } |
558 | | #endif |
559 | | |
560 | | #ifdef WORDS_BIGENDIAN |
561 | | #define MSW (0) /* Most Significant Word */ |
562 | | #define LSW (1) /* Least Significant Word */ |
563 | | #else |
564 | | #define MSW (1) |
565 | | #define LSW (0) |
566 | | #endif |
567 | | |
568 | | /* By shifting the most significant word of the input double to the |
569 | | * right 20 places, we get the very "top" of the double where the exponent |
570 | | * and sign bit lie. |
571 | | */ |
572 | | top = u.ui32[MSW] >> 20; |
573 | | |
574 | | /* Here, we calculate how much we have to shift the mantissa to normalize |
575 | | * it to an integer value. We extract the exponent "top" by masking out the |
576 | | * sign bit, then we calculate the shift amount by subtracting the exponent |
577 | | * from the bias. Notice that the correct bias for 64-bit doubles is |
578 | | * actually 1075, but we use 1053 instead for two reasons: |
579 | | * |
580 | | * 1) To perform rounding later on, we will first need the target |
581 | | * value in a 31.1 fixed-point format. Thus, the bias needs to be one |
582 | | * less: (1075 - 1: 1074). |
583 | | * |
584 | | * 2) To avoid shifting the mantissa as a full 64-bit integer (which is |
585 | | * costly on certain architectures), we break the shift into two parts. |
586 | | * First, the upper and lower parts of the mantissa are shifted |
587 | | * individually by a constant amount that all valid inputs will require |
588 | | * at the very least. This amount is chosen to be 21, because this will |
589 | | * allow the two parts of the mantissa to later be combined into a |
590 | | * single 32-bit representation, on which the remainder of the shift |
591 | | * will be performed. Thus, we decrease the bias by an additional 21: |
592 | | * (1074 - 21: 1053). |
593 | | */ |
594 | | shift_amount = 1053 - (top & 0x7FF); |
595 | | |
596 | | /* We are done with the exponent portion in "top", so here we shift it off |
597 | | * the end. |
598 | | */ |
599 | | top >>= 11; |
600 | | |
601 | | /* Before we perform any operations on the mantissa, we need to OR in |
602 | | * the implicit 1 at the top (see the IEEE-754 spec). We needn't mask |
603 | | * off the sign bit nor the exponent bits because these higher bits won't |
604 | | * make a bit of difference in the rest of our calculations. |
605 | | */ |
606 | | u.ui32[MSW] |= 0x100000; |
607 | | |
608 | | /* If the input double is negative, we have to decrease the mantissa |
609 | | * by a hair. This is an important part of performing arithmetic rounding, |
610 | | * as negative numbers must round towards positive infinity in the |
611 | | * halfwase case of -x.5. Since "top" contains only the sign bit at this |
612 | | * point, we can just decrease the mantissa by the value of "top". |
613 | | */ |
614 | | u.ui64 -= top; |
615 | | |
616 | | /* By decrementing "top", we create a bitmask with a value of either |
617 | | * 0x0 (if the input was negative) or 0xFFFFFFFF (if the input was positive |
618 | | * and thus the unsigned subtraction underflowed) that we'll use later. |
619 | | */ |
620 | | top--; |
621 | | |
622 | | /* Here, we shift the mantissa by the constant value as described above. |
623 | | * We can emulate a 64-bit shift right by 21 through shifting the top 32 |
624 | | * bits left 11 places and ORing in the bottom 32 bits shifted 21 places |
625 | | * to the right. Both parts of the mantissa are now packed into a single |
626 | | * 32-bit integer. Although we severely truncate the lower part in the |
627 | | * process, we still have enough significant bits to perform the conversion |
628 | | * without error (for all valid inputs). |
629 | | */ |
630 | | output = (u.ui32[MSW] << 11) | (u.ui32[LSW] >> 21); |
631 | | |
632 | | /* Next, we perform the shift that converts the X.Y fixed-point number |
633 | | * currently found in "output" to the desired 31.1 fixed-point format |
634 | | * needed for the following rounding step. It is important to consider |
635 | | * all possible values for "shift_amount" at this point: |
636 | | * |
637 | | * - {shift_amount < 0} Since shift_amount is an unsigned integer, it |
638 | | * really can't have a value less than zero. But, if the shift_amount |
639 | | * calculation above caused underflow (which would happen with |
640 | | * input > INT_MAX or input <= INT_MIN) then shift_amount will now be |
641 | | * a very large number, and so this shift will result in complete |
642 | | * garbage. But that's OK, as the input was out of our range, so our |
643 | | * output is undefined. |
644 | | * |
645 | | * - {shift_amount > 31} If the magnitude of the input was very small |
646 | | * (i.e. |input| << 1.0), shift_amount will have a value greater than |
647 | | * 31. Thus, this shift will also result in garbage. After performing |
648 | | * the shift, we will zero-out "output" if this is the case. |
649 | | * |
650 | | * - {0 <= shift_amount < 32} In this case, the shift will properly convert |
651 | | * the mantissa into a 31.1 fixed-point number. |
652 | | */ |
653 | | output >>= shift_amount; |
654 | | |
655 | | /* This is where we perform rounding with the 31.1 fixed-point number. |
656 | | * Since what we're after is arithmetic rounding, we simply add the single |
657 | | * fractional bit into the integer part of "output", and just keep the |
658 | | * integer part. |
659 | | */ |
660 | | output = (output >> 1) + (output & 1); |
661 | | |
662 | | /* Here, we zero-out the result if the magnitude if the input was very small |
663 | | * (as explained in the section above). Notice that all input out of the |
664 | | * valid range is also caught by this condition, which means we produce 0 |
665 | | * for all invalid input, which is a nice side effect. |
666 | | * |
667 | | * The most straightforward way to do this would be: |
668 | | * |
669 | | * if (shift_amount > 31) |
670 | | * output = 0; |
671 | | * |
672 | | * But we can use a little trick to avoid the potential branch. The |
673 | | * expression (shift_amount > 31) will be either 1 or 0, which when |
674 | | * decremented will be either 0x0 or 0xFFFFFFFF (unsigned underflow), |
675 | | * which can be used to conditionally mask away all the bits in "output" |
676 | | * (in the 0x0 case), effectively zeroing it out. Certain, compilers would |
677 | | * have done this for us automatically. |
678 | | */ |
679 | | output &= ((shift_amount > 31) - 1); |
680 | | |
681 | | /* If the input double was a negative number, then we have to negate our |
682 | | * output. The most straightforward way to do this would be: |
683 | | * |
684 | | * if (!top) |
685 | | * output = -output; |
686 | | * |
687 | | * as "top" at this point is either 0x0 (if the input was negative) or |
688 | | * 0xFFFFFFFF (if the input was positive). But, we can use a trick to |
689 | | * avoid the branch. Observe that the following snippet of code has the |
690 | | * same effect as the reference snippet above: |
691 | | * |
692 | | * if (!top) |
693 | | * output = 0 - output; |
694 | | * else |
695 | | * output = output - 0; |
696 | | * |
697 | | * Armed with the bitmask found in "top", we can condense the two statements |
698 | | * into the following: |
699 | | * |
700 | | * output = (output & top) - (output & ~top); |
701 | | * |
702 | | * where, in the case that the input double was negative, "top" will be 0, |
703 | | * and the statement will be equivalent to: |
704 | | * |
705 | | * output = (0) - (output); |
706 | | * |
707 | | * and if the input double was positive, "top" will be 0xFFFFFFFF, and the |
708 | | * statement will be equivalent to: |
709 | | * |
710 | | * output = (output) - (0); |
711 | | * |
712 | | * Which, as pointed out earlier, is equivalent to the original reference |
713 | | * snippet. |
714 | | */ |
715 | | output = (output & top) - (output & ~top); |
716 | | |
717 | | return output; |
718 | | #undef MSW |
719 | | #undef LSW |
720 | | } |
721 | | #endif |
722 | | |
723 | | /* Convert a 32-bit IEEE single precision floating point number to a |
724 | | * 'half' representation (s10.5) |
725 | | */ |
726 | | uint16_t |
727 | | _cairo_half_from_float (float f) |
728 | 0 | { |
729 | 0 | union { |
730 | 0 | uint32_t ui; |
731 | 0 | float f; |
732 | 0 | } u; |
733 | 0 | int s, e, m; |
734 | |
|
735 | 0 | u.f = f; |
736 | 0 | s = (u.ui >> 16) & 0x00008000; |
737 | 0 | e = ((u.ui >> 23) & 0x000000ff) - (127 - 15); |
738 | 0 | m = u.ui & 0x007fffff; |
739 | 0 | if (e <= 0) { |
740 | 0 | if (e < -10) { |
741 | | /* underflow */ |
742 | 0 | return 0; |
743 | 0 | } |
744 | | |
745 | 0 | m = (m | 0x00800000) >> (1 - e); |
746 | | |
747 | | /* round to nearest, round 0.5 up. */ |
748 | 0 | if (m & 0x00001000) |
749 | 0 | m += 0x00002000; |
750 | 0 | return s | (m >> 13); |
751 | 0 | } else if (e == 0xff - (127 - 15)) { |
752 | 0 | if (m == 0) { |
753 | | /* infinity */ |
754 | 0 | return s | 0x7c00; |
755 | 0 | } else { |
756 | | /* nan */ |
757 | 0 | m >>= 13; |
758 | 0 | return s | 0x7c00 | m | (m == 0); |
759 | 0 | } |
760 | 0 | } else { |
761 | | /* round to nearest, round 0.5 up. */ |
762 | 0 | if (m & 0x00001000) { |
763 | 0 | m += 0x00002000; |
764 | |
|
765 | 0 | if (m & 0x00800000) { |
766 | 0 | m = 0; |
767 | 0 | e += 1; |
768 | 0 | } |
769 | 0 | } |
770 | |
|
771 | 0 | if (e > 30) { |
772 | | /* overflow -> infinity */ |
773 | 0 | return s | 0x7c00; |
774 | 0 | } |
775 | | |
776 | 0 | return s | (e << 10) | (m >> 13); |
777 | 0 | } |
778 | 0 | } |
779 | | |
780 | | #ifndef __BIONIC__ |
781 | | # include <locale.h> |
782 | | |
783 | | const char * |
784 | | _cairo_get_locale_decimal_point (void) |
785 | 1.39M | { |
786 | 1.39M | struct lconv *locale_data = localeconv (); |
787 | 1.39M | return locale_data->decimal_point; |
788 | 1.39M | } |
789 | | |
790 | | #else |
791 | | /* Android's Bionic libc doesn't provide decimal_point */ |
792 | | const char * |
793 | | _cairo_get_locale_decimal_point (void) |
794 | | { |
795 | | return "."; |
796 | | } |
797 | | #endif |
798 | | |
799 | | #if defined (HAVE_NEWLOCALE) && defined (HAVE_STRTOD_L) |
800 | | |
801 | | static locale_t C_locale; |
802 | | |
803 | | static locale_t |
804 | | get_C_locale (void) |
805 | 0 | { |
806 | 0 | locale_t C; |
807 | |
|
808 | 0 | retry: |
809 | 0 | C = (locale_t) _cairo_atomic_ptr_get ((cairo_atomic_intptr_t *) &C_locale); |
810 | |
|
811 | 0 | if (unlikely (!C)) { |
812 | 0 | C = newlocale (LC_ALL_MASK, "C", NULL); |
813 | |
|
814 | 0 | if (!_cairo_atomic_ptr_cmpxchg ((cairo_atomic_intptr_t *) &C_locale, NULL, C)) { |
815 | 0 | freelocale (C_locale); |
816 | 0 | goto retry; |
817 | 0 | } |
818 | 0 | } |
819 | | |
820 | 0 | return C; |
821 | 0 | } |
822 | | |
823 | | double |
824 | | _cairo_strtod (const char *nptr, char **endptr) |
825 | 0 | { |
826 | 0 | return strtod_l (nptr, endptr, get_C_locale ()); |
827 | 0 | } |
828 | | |
829 | | #else |
830 | | |
831 | | /* strtod replacement that ignores locale and only accepts decimal points */ |
832 | | double |
833 | | _cairo_strtod (const char *nptr, char **endptr) |
834 | | { |
835 | | const char *decimal_point; |
836 | | int decimal_point_len; |
837 | | const char *p; |
838 | | char buf[100]; |
839 | | char *bufptr; |
840 | | char *bufend = buf + sizeof(buf) - 1; |
841 | | double value; |
842 | | char *end; |
843 | | int delta; |
844 | | cairo_bool_t have_dp; |
845 | | |
846 | | decimal_point = _cairo_get_locale_decimal_point (); |
847 | | decimal_point_len = strlen (decimal_point); |
848 | | assert (decimal_point_len != 0); |
849 | | |
850 | | p = nptr; |
851 | | bufptr = buf; |
852 | | delta = 0; |
853 | | have_dp = FALSE; |
854 | | while (*p && _cairo_isspace (*p)) { |
855 | | p++; |
856 | | delta++; |
857 | | } |
858 | | |
859 | | while (*p && (bufptr + decimal_point_len < bufend)) { |
860 | | if (_cairo_isdigit (*p)) { |
861 | | *bufptr++ = *p; |
862 | | } else if (*p == '.') { |
863 | | if (have_dp) |
864 | | break; |
865 | | strncpy (bufptr, decimal_point, decimal_point_len); |
866 | | bufptr += decimal_point_len; |
867 | | delta -= decimal_point_len - 1; |
868 | | have_dp = TRUE; |
869 | | } else if (bufptr == buf && (*p == '-' || *p == '+')) { |
870 | | *bufptr++ = *p; |
871 | | } else { |
872 | | break; |
873 | | } |
874 | | p++; |
875 | | } |
876 | | *bufptr = 0; |
877 | | |
878 | | value = strtod (buf, &end); |
879 | | if (endptr) { |
880 | | if (end == buf) |
881 | | *endptr = (char*)(nptr); |
882 | | else |
883 | | *endptr = (char*)(nptr + (end - buf) + delta); |
884 | | } |
885 | | |
886 | | return value; |
887 | | } |
888 | | #endif |
889 | | |
890 | | #ifndef HAVE_STRNDUP |
891 | | char * |
892 | | _cairo_strndup (const char *s, size_t n) |
893 | | { |
894 | | const char *end; |
895 | | size_t len; |
896 | | char *sdup; |
897 | | |
898 | | if (s == NULL) |
899 | | return NULL; |
900 | | |
901 | | end = memchr (s, 0, n); |
902 | | if (end) |
903 | | len = end - s; |
904 | | else |
905 | | len = n; |
906 | | |
907 | | sdup = (char *) _cairo_malloc (len + 1); |
908 | | if (sdup != NULL) { |
909 | | memcpy (sdup, s, len); |
910 | | sdup[len] = '\0'; |
911 | | } |
912 | | |
913 | | return sdup; |
914 | | } |
915 | | #endif |
916 | | |
917 | | /** |
918 | | * _cairo_fopen: |
919 | | * @filename: filename to open |
920 | | * @mode: mode string with which to open the file |
921 | | * @file_out: reference to file handle |
922 | | * |
923 | | * Exactly like the C library function, but possibly doing encoding |
924 | | * conversion on the filename. On all platforms, the filename is |
925 | | * passed directly to the system, but on Windows, the filename is |
926 | | * interpreted as UTF-8, rather than in a codepage that would depend |
927 | | * on system settings. |
928 | | * |
929 | | * Return value: CAIRO_STATUS_SUCCESS when the filename was converted |
930 | | * successfully to the native encoding, or the error reported by |
931 | | * _cairo_utf8_to_utf16 otherwise. To check if the file handle could |
932 | | * be obtained, dereference file_out and compare its value against |
933 | | * NULL |
934 | | **/ |
935 | | cairo_status_t |
936 | | _cairo_fopen (const char *filename, const char *mode, FILE **file_out) |
937 | 712 | { |
938 | 712 | FILE *result; |
939 | | #ifdef _WIN32 /* also defined on x86_64 */ |
940 | | uint16_t *filename_w; |
941 | | uint16_t *mode_w; |
942 | | cairo_status_t status; |
943 | | |
944 | | *file_out = NULL; |
945 | | |
946 | | if (filename == NULL || mode == NULL) { |
947 | | errno = EINVAL; |
948 | | return CAIRO_STATUS_SUCCESS; |
949 | | } |
950 | | |
951 | | if ((status = _cairo_utf8_to_utf16 (filename, -1, &filename_w, NULL)) != CAIRO_STATUS_SUCCESS) { |
952 | | errno = EINVAL; |
953 | | return status; |
954 | | } |
955 | | |
956 | | if ((status = _cairo_utf8_to_utf16 (mode, -1, &mode_w, NULL)) != CAIRO_STATUS_SUCCESS) { |
957 | | free (filename_w); |
958 | | errno = EINVAL; |
959 | | return status; |
960 | | } |
961 | | |
962 | | result = _wfopen (filename_w, mode_w); |
963 | | |
964 | | free (filename_w); |
965 | | free (mode_w); |
966 | | |
967 | | #else /* Use fopen directly */ |
968 | | |
969 | 712 | #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 7) |
970 | | /* Glibc 2.7 supports the "e" mode flag that opens the file with O_CLOEXEC. |
971 | | * this avoid the race condition in the fcntl fallback below. */ |
972 | | |
973 | 712 | char new_mode[20]; |
974 | 712 | snprintf (new_mode, sizeof (new_mode), "%s%s", mode, "e"); |
975 | 712 | result = fopen (filename, new_mode); |
976 | | |
977 | | #else /* fopen "e" not available */ |
978 | | |
979 | | result = fopen (filename, mode); |
980 | | |
981 | | #if defined(HAVE_FCNTL_H) && defined(FD_CLOEXEC) |
982 | | /* Manually set CLOEXEC */ |
983 | | if (result != NULL) { |
984 | | int fd = fileno (result); |
985 | | if (fd != -1) { |
986 | | int flags = fcntl (fd, F_GETFD); |
987 | | if (flags >= 0) |
988 | | flags = fcntl (fd, F_SETFD, flags | FD_CLOEXEC); |
989 | | } |
990 | | } |
991 | | #endif /* defined(HAVE_FCNTL_H) && defined(FD_CLOEXEC) */ |
992 | | |
993 | | #endif /* fopen "e" not available */ |
994 | | |
995 | 712 | #endif /* !_WIN32 */ |
996 | | |
997 | 712 | *file_out = result; |
998 | | |
999 | 712 | return CAIRO_STATUS_SUCCESS; |
1000 | 712 | } |
1001 | | |
1002 | | #ifdef _WIN32 |
1003 | | #include <windows.h> |
1004 | | #include <io.h> |
1005 | | |
1006 | | /* tmpfile() replacement for Windows. |
1007 | | * |
1008 | | * On Windows tmpfile() creates the file in the root directory. This |
1009 | | * may fail due to insufficient privileges. |
1010 | | */ |
1011 | | static FILE * |
1012 | | _cairo_win32_tmpfile (void) |
1013 | | { |
1014 | | DWORD path_len; |
1015 | | WCHAR path_name[MAX_PATH + 1]; |
1016 | | WCHAR file_name[MAX_PATH + 1]; |
1017 | | HANDLE handle; |
1018 | | int fd; |
1019 | | FILE *fp; |
1020 | | |
1021 | | path_len = GetTempPathW (MAX_PATH, path_name); |
1022 | | if (path_len <= 0 || path_len >= MAX_PATH) |
1023 | | return NULL; |
1024 | | |
1025 | | if (GetTempFileNameW (path_name, L"cairo_", 0, file_name) == 0) |
1026 | | return NULL; |
1027 | | |
1028 | | handle = CreateFileW (file_name, |
1029 | | GENERIC_READ | GENERIC_WRITE, |
1030 | | 0, |
1031 | | NULL, |
1032 | | CREATE_ALWAYS, |
1033 | | FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, |
1034 | | NULL); |
1035 | | if (handle == INVALID_HANDLE_VALUE) { |
1036 | | DeleteFileW (file_name); |
1037 | | return NULL; |
1038 | | } |
1039 | | |
1040 | | fd = _open_osfhandle((intptr_t) handle, 0); |
1041 | | if (fd < 0) { |
1042 | | CloseHandle (handle); |
1043 | | return NULL; |
1044 | | } |
1045 | | |
1046 | | fp = fdopen(fd, "w+b"); |
1047 | | if (fp == NULL) { |
1048 | | _close(fd); |
1049 | | return NULL; |
1050 | | } |
1051 | | |
1052 | | return fp; |
1053 | | } |
1054 | | #endif /* _WIN32 */ |
1055 | | |
1056 | | /** |
1057 | | * _cairo_tmpfile: |
1058 | | * |
1059 | | * Exactly like the C library function. On platforms that support |
1060 | | * O_CLOEXEC, the file will be opened with this flag. On Windows, the |
1061 | | * file is opened in the temp directory instead of the root directory. |
1062 | | * |
1063 | | * Return value: a file handle or NULL on error. |
1064 | | **/ |
1065 | | FILE * |
1066 | | _cairo_tmpfile (void) |
1067 | 0 | { |
1068 | | #ifdef _WIN32 |
1069 | | return _cairo_win32_tmpfile (); |
1070 | | #else /* !_WIN32 */ |
1071 | 0 | int fd; |
1072 | 0 | FILE *file; |
1073 | 0 | int flags; |
1074 | |
|
1075 | 0 | #ifdef O_TMPFILE |
1076 | 0 | fd = open(P_tmpdir, |
1077 | 0 | O_TMPFILE | O_EXCL | O_RDWR | O_NOATIME | O_CLOEXEC, |
1078 | 0 | 0600); |
1079 | 0 | if (fd == -1 && errno == ENOENT) { |
1080 | 0 | fd = open("/tmp", |
1081 | 0 | O_TMPFILE | O_EXCL | O_RDWR | O_NOATIME | O_CLOEXEC, |
1082 | 0 | 0600); |
1083 | 0 | } |
1084 | 0 | if (fd != -1) |
1085 | 0 | return fdopen (fd, "wb+"); |
1086 | | |
1087 | | /* Fallback */ |
1088 | 0 | #endif /* O_TMPFILE */ |
1089 | | |
1090 | 0 | file = tmpfile(); |
1091 | |
|
1092 | 0 | #if defined(HAVE_FCNTL_H) && defined(FD_CLOEXEC) |
1093 | | /* Manually set CLOEXEC */ |
1094 | 0 | if (file != NULL) { |
1095 | 0 | fd = fileno(file); |
1096 | 0 | if (fd != -1) { |
1097 | 0 | flags = fcntl(fd, F_GETFD); |
1098 | 0 | if (flags >= 0 && !(flags & FD_CLOEXEC)) |
1099 | 0 | fcntl(fd, F_SETFD, flags | FD_CLOEXEC); |
1100 | 0 | } |
1101 | 0 | } |
1102 | 0 | #endif /* defined(HAVE_FCNTL_H) && defined(FD_CLOEXEC) */ |
1103 | |
|
1104 | 0 | return file; |
1105 | 0 | #endif /* !_WIN32 */ |
1106 | 0 | } |
1107 | | |
1108 | | typedef struct _cairo_intern_string { |
1109 | | cairo_hash_entry_t hash_entry; |
1110 | | int len; |
1111 | | char *string; |
1112 | | } cairo_intern_string_t; |
1113 | | |
1114 | | static cairo_hash_table_t *_cairo_intern_string_ht; |
1115 | | |
1116 | | unsigned long |
1117 | | _cairo_string_hash (const char *str, int len) |
1118 | 3.02k | { |
1119 | 3.02k | const signed char *p = (const signed char *) str; |
1120 | 3.02k | unsigned int h = *p; |
1121 | | |
1122 | 75.6k | for (p += 1; len > 0; len--, p++) |
1123 | 72.6k | h = (h << 5) - h + *p; |
1124 | | |
1125 | 3.02k | return h; |
1126 | 3.02k | } |
1127 | | |
1128 | | static cairo_bool_t |
1129 | | _intern_string_equal (const void *_a, const void *_b) |
1130 | 3.02k | { |
1131 | 3.02k | const cairo_intern_string_t *a = _a; |
1132 | 3.02k | const cairo_intern_string_t *b = _b; |
1133 | | |
1134 | 3.02k | if (a->len != b->len) |
1135 | 0 | return FALSE; |
1136 | | |
1137 | 3.02k | return memcmp (a->string, b->string, a->len) == 0; |
1138 | 3.02k | } |
1139 | | |
1140 | | cairo_status_t |
1141 | | _cairo_intern_string (const char **str_inout, int len) |
1142 | 3.02k | { |
1143 | 3.02k | char *str = (char *) *str_inout; |
1144 | 3.02k | cairo_intern_string_t tmpl, *istring; |
1145 | 3.02k | cairo_status_t status = CAIRO_STATUS_SUCCESS; |
1146 | | |
1147 | 3.02k | if (CAIRO_INJECT_FAULT ()) |
1148 | 0 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1149 | | |
1150 | 3.02k | if (len < 0) |
1151 | 3.02k | len = strlen (str); |
1152 | 3.02k | tmpl.hash_entry.hash = _cairo_string_hash (str, len); |
1153 | 3.02k | tmpl.len = len; |
1154 | 3.02k | tmpl.string = (char *) str; |
1155 | | |
1156 | 3.02k | CAIRO_MUTEX_LOCK (_cairo_intern_string_mutex); |
1157 | 3.02k | if (_cairo_intern_string_ht == NULL) { |
1158 | 1 | _cairo_intern_string_ht = _cairo_hash_table_create (_intern_string_equal); |
1159 | 1 | if (unlikely (_cairo_intern_string_ht == NULL)) { |
1160 | 0 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1161 | 0 | goto BAIL; |
1162 | 0 | } |
1163 | 1 | } |
1164 | | |
1165 | 3.02k | istring = _cairo_hash_table_lookup (_cairo_intern_string_ht, |
1166 | 3.02k | &tmpl.hash_entry); |
1167 | 3.02k | if (istring == NULL) { |
1168 | 3 | istring = _cairo_malloc (sizeof (cairo_intern_string_t) + len + 1); |
1169 | 3 | if (likely (istring != NULL)) { |
1170 | 3 | istring->hash_entry.hash = tmpl.hash_entry.hash; |
1171 | 3 | istring->len = tmpl.len; |
1172 | 3 | istring->string = (char *) (istring + 1); |
1173 | 3 | memcpy (istring->string, str, len); |
1174 | 3 | istring->string[len] = '\0'; |
1175 | | |
1176 | 3 | status = _cairo_hash_table_insert (_cairo_intern_string_ht, |
1177 | 3 | &istring->hash_entry); |
1178 | 3 | if (unlikely (status)) { |
1179 | 0 | free (istring); |
1180 | 0 | goto BAIL; |
1181 | 0 | } |
1182 | 3 | } else { |
1183 | 0 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1184 | 0 | goto BAIL; |
1185 | 0 | } |
1186 | 3 | } |
1187 | | |
1188 | 3.02k | *str_inout = istring->string; |
1189 | | |
1190 | 3.02k | BAIL: |
1191 | 3.02k | CAIRO_MUTEX_UNLOCK (_cairo_intern_string_mutex); |
1192 | 3.02k | return status; |
1193 | 3.02k | } |
1194 | | |
1195 | | static void |
1196 | | _intern_string_pluck (void *entry, void *closure) |
1197 | 0 | { |
1198 | 0 | _cairo_hash_table_remove (closure, entry); |
1199 | 0 | free (entry); |
1200 | 0 | } |
1201 | | |
1202 | | void |
1203 | | _cairo_intern_string_reset_static_data (void) |
1204 | 0 | { |
1205 | 0 | CAIRO_MUTEX_LOCK (_cairo_intern_string_mutex); |
1206 | 0 | if (_cairo_intern_string_ht != NULL) { |
1207 | 0 | _cairo_hash_table_foreach (_cairo_intern_string_ht, |
1208 | 0 | _intern_string_pluck, |
1209 | 0 | _cairo_intern_string_ht); |
1210 | 0 | _cairo_hash_table_destroy(_cairo_intern_string_ht); |
1211 | 0 | _cairo_intern_string_ht = NULL; |
1212 | 0 | } |
1213 | 0 | CAIRO_MUTEX_UNLOCK (_cairo_intern_string_mutex); |
1214 | 0 | } |