Line data Source code
1 : /*
2 : +----------------------------------------------------------------------+
3 : | For PHP Version 8 |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 2015 Elizabeth M Smith |
6 : +----------------------------------------------------------------------+
7 : | http://www.opensource.org/licenses/mit-license.php MIT License |
8 : | Also available in LICENSE |
9 : +----------------------------------------------------------------------+
10 : | Authors: Elizabeth M Smith <auroraeosrose@gmail.com> |
11 : | Swen Zanon <swen.zanon@geoglis.de> |
12 : +----------------------------------------------------------------------+
13 : */
14 :
15 : #ifdef HAVE_CONFIG_H
16 : #include "config.h"
17 : #endif
18 :
19 : #include <cairo.h>
20 : #include <php.h>
21 : #include <zend_exceptions.h>
22 :
23 : #include "php_cairo.h"
24 : #include "php_cairo_internal.h"
25 : #include "ft_font_arginfo.h"
26 :
27 : #if defined(CAIRO_HAS_FT_FONT) && defined(HAVE_FREETYPE)
28 :
29 : php_cairo_ft_error php_cairo_ft_errors[] =
30 : #include FT_ERRORS_H
31 :
32 : #include <fontconfig/fontconfig.h>
33 :
34 :
35 : zend_class_entry *ce_cairo_ftfont;
36 :
37 : /* Functions for stream handling */
38 347 : static unsigned long php_cairo_ft_read_func(
39 : FT_Stream stream,
40 : unsigned long offset,
41 : unsigned char* buffer,
42 : unsigned long count
43 : ) {
44 : stream_closure *closure;
45 347 : closure = (stream_closure *)stream->descriptor.pointer;
46 347 : php_stream_seek(closure->stream, offset, SEEK_SET);
47 347 : return php_stream_read(closure->stream, (char *)buffer, count);
48 : }
49 :
50 5 : static void cairo_user_data_callback_ft_free(pecl_ft_container *ft_container) {
51 5 : if (ft_container->ft_face != NULL) {
52 5 : FT_Done_Face(ft_container->ft_face);
53 : }
54 :
55 5 : if (ft_container->ft_stream != NULL) {
56 5 : pefree(ft_container->ft_stream, 1);
57 : }
58 :
59 5 : if (ft_container->ft_lib != NULL) {
60 5 : FT_Done_FreeType(ft_container->ft_lib);
61 : }
62 :
63 5 : pefree(ft_container, 1);
64 5 : }
65 :
66 6 : static bool php_cairo_create_ft_font_face(
67 : pecl_ft_container *ft_container,
68 : cairo_font_face_object *font_face_object,
69 : php_stream *stream,
70 : bool owned_stream,
71 : int load_flags,
72 : bool throw_exceptions
73 : ) {
74 : FT_Stream ft_stream;
75 : stream_closure *closure;
76 : php_stream_statbuf ssbuf;
77 : FT_Open_Args open_args;
78 : int error;
79 :
80 6 : if (php_stream_stat(stream, &ssbuf) < 0) {
81 0 : return 1;
82 : }
83 :
84 6 : ft_container->ft_face = NULL;
85 6 : ft_container->ft_stream = NULL;
86 :
87 6 : font_face_object->closure = NULL;
88 :
89 6 : closure = ecalloc(1, sizeof(stream_closure));
90 6 : closure->stream = stream;
91 6 : closure->owned_stream = owned_stream;
92 :
93 6 : ft_stream = pecalloc(1, sizeof(*ft_stream), 1);
94 6 : ft_stream->descriptor.pointer = (void *)closure;
95 6 : ft_stream->pos = php_stream_tell(stream);
96 6 : ft_stream->size = ssbuf.sb.st_size;
97 6 : ft_stream->read = php_cairo_ft_read_func;
98 6 : open_args.flags = FT_OPEN_STREAM;
99 6 : open_args.stream = ft_stream;
100 :
101 6 : error = FT_Open_Face(ft_container->ft_lib, &open_args, 0, &ft_container->ft_face);
102 :
103 6 : if (error) {
104 1 : if (owned_stream) {
105 1 : php_stream_close(stream);
106 : }
107 1 : efree(closure);
108 1 : pefree(ft_stream, 1);
109 :
110 1 : return error;
111 : }
112 :
113 5 : font_face_object->closure = closure;
114 :
115 5 : ft_container->ft_stream = ft_stream;
116 5 : font_face_object->font_face = (cairo_font_face_t *)cairo_ft_font_face_create_for_ft_face(ft_container->ft_face, (int)load_flags);
117 :
118 : /* Set Cairo to automatically destroy the FT_Face when the cairo_font_face_t is destroyed */
119 10 : error = cairo_font_face_set_user_data(
120 : font_face_object->font_face,
121 5 : &font_face_object->key,
122 : ft_container,
123 : (cairo_destroy_func_t) cairo_user_data_callback_ft_free
124 : );
125 :
126 :
127 5 : if (error) {
128 0 : cairo_font_face_destroy (font_face_object->font_face);
129 0 : FT_Done_Face(ft_container->ft_face);
130 0 : pefree(ft_stream, 1);
131 0 : return error;
132 : }
133 :
134 5 : return 0;
135 : }
136 :
137 : /* ----------------------------------------------------------------
138 : \Cairo\FontFace\Ft Class API
139 : ------------------------------------------------------------------*/
140 :
141 : /* {{{ proto \Cairo\FontFace\Ft::__construct(string fontFilename, long load_flags)
142 : Creates a new font face for the FreeType font backend from a pre-opened FreeType face. */
143 9 : PHP_METHOD(Cairo_FontFace_Ft, __construct)
144 : {
145 9 : zend_long load_flags = 0;
146 9 : int error = 0;
147 9 : zval *stream_zval = NULL;
148 : cairo_font_face_object *font_face_object;
149 : pecl_ft_container *ft_container;
150 :
151 : php_stream *stream;
152 9 : bool owned_stream = 0;
153 : php_stream_statbuf ssbuf;
154 :
155 9 : ZEND_PARSE_PARAMETERS_START(1, 2)
156 8 : Z_PARAM_ZVAL(stream_zval)
157 8 : Z_PARAM_OPTIONAL
158 9 : Z_PARAM_LONG(load_flags)
159 9 : ZEND_PARSE_PARAMETERS_END();
160 :
161 16 : if (Z_TYPE_P(stream_zval) == IS_STRING) {
162 7 : stream = php_stream_open_wrapper(Z_STRVAL_P(stream_zval), "rb", REPORT_ERRORS, NULL);
163 7 : owned_stream = 1;
164 2 : } else if (Z_TYPE_P(stream_zval) == IS_RESOURCE) {
165 0 : php_stream_from_zval(stream, stream_zval);
166 : } else {
167 1 : zend_throw_exception(ce_cairo_exception,
168 : "Cairo\\FontFace\\Ft::__construct() expects parameter 1 to be a string or a stream resource",
169 : 0
170 : );
171 1 : RETURN_THROWS();
172 : }
173 :
174 7 : if (!stream) {
175 1 : RETURN_NULL();
176 : }
177 :
178 6 : if (php_stream_stat(stream, &ssbuf) != 0) {
179 0 : zend_throw_exception(ce_cairo_exception, "Cannot determine size of stream", 0);
180 0 : RETURN_THROWS();
181 : }
182 :
183 12 : font_face_object = Z_CAIRO_FONT_FACE_P(getThis());
184 6 : if (!font_face_object) {
185 0 : RETURN_NULL();
186 : }
187 :
188 6 : ft_container = pecalloc(1, sizeof(pecl_ft_container), 1);
189 :
190 6 : error = FT_Init_FreeType(&ft_container->ft_lib);
191 6 : if (error) {
192 0 : pefree(ft_container, 1);
193 0 : zend_throw_exception(ce_cairo_exception, "Failed to initalise FreeType library", 0);
194 0 : RETURN_THROWS();
195 : }
196 :
197 6 : error = php_cairo_create_ft_font_face(ft_container, font_face_object, stream, owned_stream, load_flags, 1);
198 :
199 6 : if (error) {
200 1 : const char *err_string = php_cairo_get_ft_error(error);
201 1 : zend_throw_exception_ex(ce_cairo_exception, error,
202 : "Cairo\\FontFace\\Ft::__construct(): An error occurred opening the file %s",
203 : err_string
204 : );
205 1 : pefree(ft_container, 1);
206 1 : RETURN_THROWS();
207 : }
208 :
209 5 : if (php_cairo_throw_exception(cairo_font_face_status(font_face_object->font_face))) {
210 0 : RETURN_THROWS();
211 : }
212 : }
213 : /* }}} */
214 :
215 7 : PHP_METHOD(Cairo_FontFace_Ft, getSynthesize)
216 : {
217 : cairo_font_face_object *font_face_object;
218 : zend_long synth_flags;
219 :
220 7 : ZEND_PARSE_PARAMETERS_NONE();
221 :
222 12 : font_face_object = Z_CAIRO_FONT_FACE_P(getThis());
223 6 : if (!font_face_object) {
224 0 : RETURN_NULL();
225 : }
226 :
227 6 : synth_flags = cairo_ft_font_face_get_synthesize(font_face_object->font_face);
228 :
229 6 : RETURN_LONG(synth_flags);
230 : }
231 :
232 6 : PHP_METHOD(Cairo_FontFace_Ft, setSynthesize)
233 : {
234 : cairo_font_face_object *font_face_object;
235 : zend_long synth_flags;
236 :
237 6 : ZEND_PARSE_PARAMETERS_START(1, 1)
238 8 : Z_PARAM_LONG(synth_flags);
239 6 : ZEND_PARSE_PARAMETERS_END();
240 :
241 6 : font_face_object = Z_CAIRO_FONT_FACE_P(getThis());
242 3 : if (!font_face_object) {
243 0 : RETURN_NULL();
244 : }
245 :
246 3 : cairo_ft_font_face_set_synthesize(
247 : font_face_object->font_face,
248 : synth_flags
249 : );
250 :
251 3 : if (php_cairo_throw_exception(cairo_font_face_status(font_face_object->font_face))) {
252 0 : RETURN_THROWS();
253 : }
254 : }
255 :
256 5 : PHP_METHOD(Cairo_FontFace_Ft, unsetSynthesize)
257 : {
258 : cairo_font_face_object *font_face_object;
259 : zend_long synth_flags;
260 :
261 5 : ZEND_PARSE_PARAMETERS_START(1, 1)
262 6 : Z_PARAM_LONG(synth_flags);
263 5 : ZEND_PARSE_PARAMETERS_END();
264 :
265 4 : font_face_object = Z_CAIRO_FONT_FACE_P(getThis());
266 2 : if (!font_face_object) {
267 0 : RETURN_NULL();
268 : }
269 :
270 2 : cairo_ft_font_face_unset_synthesize(
271 : font_face_object->font_face,
272 : synth_flags
273 : );
274 :
275 2 : if (php_cairo_throw_exception(cairo_font_face_status(font_face_object->font_face))) {
276 0 : RETURN_THROWS();
277 : }
278 : }
279 :
280 : /* ----------------------------------------------------------------
281 : \Cairo\FontFace\Ft Definition and registration
282 : ------------------------------------------------------------------*/
283 :
284 : /* {{{ PHP_MINIT_FUNCTION */
285 433 : PHP_MINIT_FUNCTION(cairo_ft_font)
286 : {
287 433 : ce_cairo_ftfont = register_class_Cairo_FontFace_Ft(php_cairo_get_fontface_ce());
288 :
289 433 : return SUCCESS;
290 : }
291 : /* }}} */
292 :
293 : #endif
|