Codebase list libimager-perl / upstream/0.95+dfsg
Imported Upstream version 0.95+dfsg gregor herrmann 11 years ago
148 changed file(s) with 7643 addition(s) and 3329 deletion(s). Raw diff Collapse all Expand all
00 Imager release history. Older releases can be found in Changes.old
1
2 Imager 0.95 - 19 Apr 2013
3 ===========
4
5 - handle the SVf_UTF8 flag correctly on magic strings passed to
6 Imager::IO's write() and raw_write() methods.
7 This may misbehave in perl 5.6.x since the UTF8 flag may not be
8 visible in the main SV after SvGETMAGIC().
9 https://rt.cpan.org/Ticket/Display.html?id=83438
10
11 - document that bounding_box() ignores the transformation matrix
12 supplied to tranform() for fonts.
13 https://rt.cpan.org/Ticket/Display.html?id=84106
14
15 Imager 0.94_02 - 5 Apr 2013
16 ==============
17
18 - enable debug logging for the standard font tests
19
20 - skip the overloaded UTF-8 text output checks on 5.6.x and earlier,
21 due to a bug in that version of perl.
22
23 - don't test for read() failing on a write-only handle in 5.8.x and
24 earlier, this was fixed in change 862083f7e4 in perl.
25
26 - report the version of Inline found during testing (an attempt to
27 diagnose some intermittent failures.)
28
29 Imager 0.94_01 - 2 Mar 2013
30 ==============
31
32 - NOTE: possibly backward incompatible:
33 support reading from/writing to perl filehandes that aren't raw
34 files.
35
36 This allows Imager's I/O to honour handles with layers such as
37 gzip, scalar file handles or tied file handles.
38
39 This is backward incompatible in that previous Imager would simply
40 use fileno() to retrieve the fd for the file and call write(2) etc
41 on it directly.
42 https://rt.cpan.org/Ticket/Display.html?id=78843
43
44 - moved most of README to lib/Imager/Install.pod which should make it
45 more accessible to the "web" generation, also significantly updated
46 and re-worked it.
47
48 - updated README's for the separately distributed modules to refer to
49 Imager::Install, and that they need -dev versions of packages
50 https://rt.cpan.org/Ticket/Display.html?id=81265
51
52 - the JPEG test code now reports the compile-time library version
53
54 - avoid a possible compiler optimization issue on CentOS 5.9 i386 by
55 rearranging (and mildly optimizing) some code.
56 https://rt.cpan.org/Ticket/Display.html?id=83212
57
58 - fix a POD error in Imager::Fill (detected on new Pod-Simple)
59 https://rt.cpan.org/Ticket/Display.html?id=83434
60
61 - fix a broken link to Graphics::Magick
62 https://rt.cpan.org/Ticket/Display.html?id=82743
63
64 - drawing text to a channel with FT2 would draw with random coverage
65 due to an uninitialized alpha channel.
66
67 - marked the function pointer underlying the mm_log() API with the
68 correct gcc magic and fixed the resulting warnings.
69
70 - fixed some other compiler warnings
71
72 - Imager::Font::W32 now properly reports text drawing errors
73 https://rt.cpan.org/Ticket/Display.html?id=70098
74
75 - handle the SVf_UTF8 flag correctly on magic (eg. overloaded)
76 strings passed as text to draw(), bounding_box(), has_chars(),
77 glyph_names() (where supported) in each of the font drivers.
78 This may misbehave in perl 5.6.x since the UTF8 flag may not be
79 visible in the main SV after SvGETMAGIC().
80 https://rt.cpan.org/Ticket/Display.html?id=83438 (partial)
81
82 Imager 0.94 - 15 Dec 2012
83 =========================
84
85 Variations on some of these changes were included in development
86 releases.
87
88 - improved thread safety
89 - the internal error stack and log file handle are now in a per-thread
90 context object
91 - JPEG now captures IPTC information in a thread-safe way
92 - avoid globals where possible for warning capture in libtiff
93 - use a mutex to avoid re-entering thread-unsafe giflib
94 - use a mutex to avoid re-entering thread-unsafe tifflib
95 - use a mutex to avoid re-entering thread-unsafe T1Lib
96 - use a library handle per thread for freetype 2.
97 - use an engine handle per thread for freetype 1.x.
98 - originally these changes broke ABI compatibility, this has been
99 restored.
100
101 - clarify the return value of getpixel();
102 https://rt.cpan.org/Ticket/Display.html?id=81198
103
104 - fixed a race condition in parallel testing for T1
105
106 - fixed a bug in handling yoff for untransformed image-based fills
107
108 - documentation improvements for Imager::Fill
109
110 - FT2: report the library version while testing.
1111
2112 Imager 0.93 - 15 Oct 2012
3113 ===========
1717 */
1818
1919
20 static
2021 unsigned char
21 static
2222 saturate(int in) {
2323 if (in>255) { return 255; }
2424 else if (in>0) return in;
00 package Imager::Font::FT2;
11 use strict;
22 use Imager;
3 use Scalar::Util ();
34 use vars qw($VERSION @ISA);
45 @ISA = qw(Imager::Font);
56
67 BEGIN {
7 $VERSION = "0.86";
8 $VERSION = "0.91";
89
910 require XSLoader;
1011 XSLoader::load('Imager::Font::FT2', $VERSION);
4950
5051 sub _draw {
5152 my $self = shift;
53
54 $self->_valid
55 or return;
56
5257 my %input = @_;
5358 if (exists $input{channel}) {
5459 i_ft2_cp($self->{id}, $input{image}{IMG}, $input{'x'}, $input{'y'},
6873 my $self = shift;
6974 my %input = @_;
7075
71 return i_ft2_bbox($self->{id}, $input{size}, $input{sizew}, $input{string},
72 $input{utf8});
76 $self->_valid
77 or return;
78
79 my @result = i_ft2_bbox($self->{id}, $input{size}, $input{sizew},
80 $input{string}, $input{utf8});
81 unless (@result) {
82 Imager->_set_error(Imager->_error_as_msg);
83 return;
84 }
85
86 return @result;
7387 }
7488
7589 sub dpi {
7690 my $self = shift;
91
92 $self->_valid
93 or return;
94
7795 my @old = i_ft2_getdpi($self->{id});
7896 if (@_) {
7997 my %hsh = @_;
96114 sub hinting {
97115 my ($self, %opts) = @_;
98116
117 $self->_valid
118 or return;
119
99120 i_ft2_sethinting($self->{id}, $opts{hinting} || 0);
100121 }
101122
102123 sub _transform {
103124 my $self = shift;
125
126 $self->_valid
127 or return;
104128
105129 my %hsh = @_;
106130 my $matrix = $hsh{matrix} or return undef;
116140 sub has_chars {
117141 my ($self, %hsh) = @_;
118142
143 $self->_valid
144 or return;
145
119146 unless (defined $hsh{string} && length $hsh{string}) {
120147 $Imager::ERRSTR = "No string supplied to \$font->has_chars()";
121148 return;
122149 }
123 return i_ft2_has_chars($self->{id}, $hsh{string},
124 _first($hsh{'utf8'}, $self->{utf8}, 0));
150 if (wantarray) {
151 my @result = i_ft2_has_chars($self->{id}, $hsh{string},
152 _first($hsh{'utf8'}, $self->{utf8}, 0));
153 unless (@result) {
154 Imager->_set_error(Imager->_error_as_msg);
155 return;
156 }
157
158 return @result;
159 }
160 else {
161 my $result = i_ft2_has_chars($self->{id}, $hsh{string},
162 _first($hsh{'utf8'}, $self->{utf8}, 0));
163 unless (defined $result) {
164 Imager->_set_error(Imager->_error_as_msg);
165 return;
166 }
167 return $result;
168 }
125169 }
126170
127171 sub face_name {
128172 my ($self) = @_;
129173
174 $self->_valid
175 or return;
176
130177 i_ft2_face_name($self->{id});
131178 }
132179
133180 sub can_glyph_names {
134 i_ft2_can_do_glyph_names();
181 my ($self) = @_;
182
183 i_ft2_can_do_glyph_names()
184 or return;
185
186 if (ref $self) {
187 $self->_valid
188 or return;
189
190 i_ft2_face_has_glyph_names($self->{id})
191 or return;
192 }
193
194 return 1;
135195 }
136196
137197 sub glyph_names {
138198 my ($self, %input) = @_;
199
200 $self->_valid
201 or return;
139202
140203 my $string = $input{string};
141204 defined $string
153216 sub is_mm {
154217 my ($self) = @_;
155218
219 $self->_valid
220 or return;
221
156222 i_ft2_is_multiple_master($self->{id});
157223 }
158224
159225 sub mm_axes {
160226 my ($self) = @_;
227
228 $self->_valid
229 or return;
161230
162231 my ($num_axis, $num_design, @axes) =
163232 i_ft2_get_multiple_masters($self->{id})
168237
169238 sub set_mm_coords {
170239 my ($self, %opts) = @_;
240
241 $self->_valid
242 or return;
171243
172244 $opts{coords}
173245 or return Imager->_set_error("Missing coords parameter");
179251
180252 return 1;
181253 }
254
255 # objects may be invalidated on thread creation (or Win32 fork emulation)
256 sub _valid {
257 my $self = shift;
258
259 unless ($self->{id} && Scalar::Util::blessed($self->{id})) {
260 Imager->_set_error("font object was created in another thread");
261 return;
262 }
263
264 return 1;
265 }
266
182267 1;
183268
184269 __END__
3232 i_ft2_new(name, index)
3333 char *name
3434 int index
35
36 const char *
37 i_ft2_version(runtime)
38 int runtime
39 PREINIT:
40 char buf[100];
41 CODE:
42 if (!i_ft2_version(runtime, buf, sizeof(buf))) {
43 XSRETURN_EMPTY;
44 }
45 RETVAL = buf;
46 OUTPUT:
47 RETVAL
3548
3649 undef_int
3750 i_ft2_setdpi(font, xdpi, ydpi)
109122 }
110123
111124 void
112 i_ft2_bbox_r(font, cheight, cwidth, text, vlayout, utf8)
125 i_ft2_bbox_r(font, cheight, cwidth, text_sv, vlayout, utf8)
113126 Imager::Font::FT2x font
114127 double cheight
115128 double cwidth
116 char *text
129 SV *text_sv
117130 int vlayout
118131 int utf8
119132 PREINIT:
120133 i_img_dim bbox[8];
121134 int i;
122 PPCODE:
123 #ifdef SvUTF8
124 if (SvUTF8(ST(3)))
125 utf8 = 1;
126 #endif
127 if (i_ft2_bbox_r(font, cheight, cwidth, text, strlen(text), vlayout,
135 const char *text;
136 STRLEN len;
137 PPCODE:
138 text = SvPV(text_sv, len);
139 #ifdef SvUTF8
140 if (SvUTF8(text_sv))
141 utf8 = 1;
142 #endif
143 if (i_ft2_bbox_r(font, cheight, cwidth, text, len, vlayout,
128144 utf8, bbox)) {
129145 EXTEND(SP, 8);
130146 for (i = 0; i < 8; ++i)
132148 }
133149
134150 undef_int
135 i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text, align, aa, vlayout, utf8)
151 i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text_sv, align, aa, vlayout, utf8)
136152 Imager::Font::FT2x font
137153 Imager::ImgRaw im
138154 i_img_dim tx
140156 Imager::Color cl
141157 double cheight
142158 double cwidth
159 SV *text_sv
143160 int align
144161 int aa
145162 int vlayout
146163 int utf8
147164 PREINIT:
148 char *text;
165 const char *text;
149166 STRLEN len;
150167 CODE:
151 #ifdef SvUTF8
152 if (SvUTF8(ST(7))) {
153 utf8 = 1;
154 }
155 #endif
156 text = SvPV(ST(7), len);
168 text = SvPV(text_sv, len);
169 #ifdef SvUTF8
170 if (SvUTF8(text_sv)) {
171 utf8 = 1;
172 }
173 #endif
157174 RETVAL = i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text,
158175 len, align, aa, vlayout, utf8);
159176 OUTPUT:
177194 char const *text;
178195 STRLEN len;
179196 CODE:
180 #ifdef SvUTF8
181 if (SvUTF8(ST(7)))
182 utf8 = 1;
183 #endif
184197 text = SvPV(text_sv, len);
198 #ifdef SvUTF8
199 if (SvUTF8(text_sv))
200 utf8 = 1;
201 #endif
185202 RETVAL = i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text,
186 len, align, aa, vlayout, 1);
203 len, align, aa, vlayout, utf8);
187204 OUTPUT:
188205 RETVAL
189206
217234 size_t count;
218235 size_t i;
219236 PPCODE:
220 #ifdef SvUTF8
221 if (SvUTF8(text_sv))
222 utf8 = 1;
223 #endif
224237 text = SvPV(text_sv, len);
238 #ifdef SvUTF8
239 if (SvUTF8(text_sv))
240 utf8 = 1;
241 #endif
225242 work = mymalloc(len);
226243 count = i_ft2_has_chars(handle, text, len, utf8, work);
227244 if (GIMME_V == G_ARRAY) {
263280 STRLEN work_len;
264281 size_t len;
265282 char name[255];
266 PPCODE:
267 #ifdef SvUTF8
268 if (SvUTF8(text_sv))
269 utf8 = 1;
270 #endif
283 SSize_t count = 0;
284 PPCODE:
285 i_clear_error();
271286 text = SvPV(text_sv, work_len);
272287 len = work_len;
288 #ifdef SvUTF8
289 if (SvUTF8(text_sv))
290 utf8 = 1;
291 #endif
273292 while (len) {
274293 unsigned long ch;
275294 if (utf8) {
276295 ch = i_utf8_advance(&text, &len);
277296 if (ch == ~0UL) {
278297 i_push_error(0, "invalid UTF8 character");
279 break;
298 XSRETURN_EMPTY;
280299 }
281300 }
282301 else {
283302 ch = *text++;
284303 --len;
285304 }
286 EXTEND(SP, 1);
305 EXTEND(SP, count+1);
287306 if (i_ft2_glyph_name(handle, ch, name, sizeof(name),
288307 reliable_only)) {
289 PUSHs(sv_2mortal(newSVpv(name, 0)));
308 ST(count) = sv_2mortal(newSVpv(name, 0));
290309 }
291310 else {
292 PUSHs(&PL_sv_undef);
293 }
294 }
311 ST(count) = &PL_sv_undef;
312 }
313 ++count;
314 }
315 XSRETURN(count);
295316
296317 int
297318 i_ft2_can_do_glyph_names()
355376
356377 BOOT:
357378 PERL_INITIALIZE_IMAGER_CALLBACKS;
379 i_ft2_start();
3737 $opts{TYPEMAPS} = [ Imager::ExtUtils->typemap ];
3838
3939 # Imager required configure through use
40 my @Imager_req = ( Imager => "0.86" );
40 my @Imager_req = ( Imager => "0.95" );
4141 if ($MM_ver >= 6.46) {
4242 $opts{META_MERGE} =
4343 {
6060 $opts{PREREQ_PM} =
6161 {
6262 @Imager_req,
63 'Scalar::Util' => 1.00,
6364 XSLoader => 0,
6465 };
6566 }
33 It requires libfreetype and its development header files to be
44 installed.
55
6 This is currently shipped as part of Imager, but but Imager may
7 install with out installing Imager::Font::FT2, if your module or
8 application requires FreeType 2 support then add Imager::Font::FT2 as
9 a prerequisite.
6 For Linux distributions this typically requires installation of the
7 associated -dev or -devel package.
8
9 See Imager::Install for more information.
10
11 Imager::Font::FT2 is currently shipped as part of Imager, but but
12 Imager may install with out installing Imager::Font::FT2. If your
13 module or application requires FreeType 2 support then add
14 Imager::Font::FT2 as a prerequisite.
1616 i_img *im = ...;
1717 i_color cl;
1818 if (!i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text, length, align,
19 aa)) { error }
19 aa, vlayout, utf8)) { error }
2020 if (!i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text, length,
2121 align, aa)) { error }
2222 i_ft2_destroy(font);
3737 #include "imft2.h"
3838 #include <stdio.h>
3939 #include <math.h>
40 #include <string.h>
4041 #include <ft2build.h>
4142 #include FT_FREETYPE_H
4243 #ifdef FT_MULTIPLE_MASTERS_H
4849
4950 static void ft2_push_message(int code);
5051
51 static int ft2_initialized = 0;
52 static FT_Library library;
52 static void ft2_final(void *);
53
54 static im_slot_t slot = -1;
55
56 typedef struct {
57 int initialized;
58 FT_Library library;
59 im_context_t ctx;
60 } ft2_state;
61
62 static ft2_state *
63 i_ft2_init(void);
5364
5465 static i_img_dim i_min(i_img_dim a, i_img_dim b);
5566 static i_img_dim i_max(i_img_dim a, i_img_dim b);
5667
68 int
69 i_ft2_version(int runtime, char *buf, size_t buf_size) {
70 char work[100];
71
72 i_clear_error();
73
74 if (buf_size == 0) {
75 i_push_error(0, "zero size buffer supplied");
76 return 0;
77 }
78 if (runtime) {
79 ft2_state *ft2;
80 /* initialized to work around a bug in FT2
81 http://lists.nongnu.org/archive/html/freetype-devel/2002-09/msg00058.html
82 Though I don't know why I still see this in 2.4.2
83 */
84 FT_Int major = 1, minor = 1, patch = 1;
85
86 if ((ft2 = i_ft2_init()) == NULL)
87 return 0;
88
89 FT_Library_Version(ft2->library, &major, &minor, &patch);
90 sprintf(work, "%d.%d.%d", (int)major, (int)minor, (int)patch);
91 }
92 else {
93 sprintf(work, "%d.%d.%d", FREETYPE_MAJOR, FREETYPE_MINOR, FREETYPE_PATCH);
94 }
95 strncpy(buf, work, buf_size);
96 buf[buf_size-1] = '\0';
97
98 return 1;
99 }
100
101 void
102 i_ft2_start(void) {
103 if (slot == -1)
104 slot = im_context_slot_new(ft2_final);
105 }
106
57107 /*
58108 =item i_ft2_init(void)
59109
60110 Initializes the Freetype 2 library.
61111
62 Returns true on success, false on failure.
63
64 =cut
65 */
66 int
112 Returns ft2_state * on success or NULL on failure.
113
114 =cut
115 */
116
117 static ft2_state *
67118 i_ft2_init(void) {
68119 FT_Error error;
69
70 i_clear_error();
71 error = FT_Init_FreeType(&library);
72 if (error) {
73 ft2_push_message(error);
74 i_push_error(0, "Initializing Freetype2");
75 return 0;
76 }
77
78 ft2_initialized = 1;
79
80 return 1;
120 im_context_t ctx = im_get_context();
121 ft2_state *ft2 = im_context_slot_get(ctx, slot);
122
123 if (ft2 == NULL) {
124 ft2 = mymalloc(sizeof(ft2_state));
125 ft2->initialized = 0;
126 ft2->library = NULL;
127 ft2->ctx = ctx;
128 im_context_slot_set(ctx, slot, ft2);
129 mm_log((1, "created FT2 state %p for context %p\n", ft2, ctx));
130 }
131
132 i_clear_error();
133 if (!ft2->initialized) {
134 error = FT_Init_FreeType(&ft2->library);
135 if (error) {
136 ft2_push_message(error);
137 i_push_error(0, "Initializing Freetype2");
138 return NULL;
139 }
140 mm_log((1, "initialized FT2 state %p\n", ft2));
141
142 ft2->initialized = 1;
143 }
144
145 return ft2;
146 }
147
148 static void
149 ft2_final(void *state) {
150 ft2_state *ft2 = state;
151
152 if (ft2->initialized) {
153 mm_log((1, "finalizing FT2 state %p\n", state));
154 FT_Done_FreeType(ft2->library);
155 ft2->library = NULL;
156 ft2->initialized = 0;
157 }
158
159 mm_log((1, "freeing FT2 state %p\n", state));
160 myfree(state);
81161 }
82162
83163 struct FT2_Fonthandle {
84164 FT_Face face;
165 ft2_state *state;
85166 int xdpi, ydpi;
86167 int hint;
87168 FT_Encoding encoding;
137218 int i, j;
138219 FT_Encoding encoding;
139220 int score;
221 ft2_state *ft2;
140222
141223 mm_log((1, "i_ft2_new(name %p, index %d)\n", name, index));
142224
143 if (!ft2_initialized && !i_ft2_init())
225 if ((ft2 = i_ft2_init()) == NULL)
144226 return NULL;
145227
146228 i_clear_error();
147 error = FT_New_Face(library, name, index, &face);
229 error = FT_New_Face(ft2->library, name, index, &face);
148230 if (error) {
149231 ft2_push_message(error);
150232 i_push_error(error, "Opening face");
156238 score = 0;
157239 for (i = 0; i < face->num_charmaps; ++i) {
158240 FT_Encoding enc_entry = face->charmaps[i]->encoding;
159 mm_log((2, "i_ft2_new, encoding %lX platform %u encoding %u\n",
160 enc_entry, face->charmaps[i]->platform_id,
241 mm_log((2, "i_ft2_new, encoding %X platform %u encoding %u\n",
242 (unsigned)enc_entry, face->charmaps[i]->platform_id,
161243 face->charmaps[i]->encoding_id));
162244 for (j = 0; j < sizeof(enc_scores) / sizeof(*enc_scores); ++j) {
163245 if (enc_scores[j].encoding == enc_entry && enc_scores[j].score > score) {
168250 }
169251 }
170252 FT_Select_Charmap(face, encoding);
171 mm_log((2, "i_ft2_new, selected encoding %lX\n", encoding));
253 mm_log((2, "i_ft2_new, selected encoding %X\n", (unsigned)encoding));
172254
173255 result = mymalloc(sizeof(FT2_Fonthandle));
174256 result->face = face;
257 result->state = ft2;
175258 result->xdpi = result->ydpi = 72;
176259 result->encoding = encoding;
177260
243326 if (xdpi > 0 && ydpi > 0) {
244327 handle->xdpi = xdpi;
245328 handle->ydpi = ydpi;
246 return 0;
329 return 1;
247330 }
248331 else {
249332 i_push_error(0, "resolutions must be positive");
340423 int loadFlags = FT_LOAD_DEFAULT;
341424 int rightb = 0;
342425
343 mm_log((1, "i_ft2_bbox(handle %p, cheight %f, cwidth %f, text %p, len %d, bbox %p)\n",
344 handle, cheight, cwidth, text, len, bbox));
426 i_clear_error();
427
428 mm_log((1, "i_ft2_bbox(handle %p, cheight %f, cwidth %f, text %p, len %u, bbox %p)\n",
429 handle, cheight, cwidth, text, (unsigned)len, bbox));
345430
346431 error = FT_Set_Char_Size(handle->face, cwidth*64, cheight*64,
347432 handle->xdpi, handle->ydpi);
373458 error = FT_Load_Glyph(handle->face, index, loadFlags);
374459 if (error) {
375460 ft2_push_message(error);
376 i_push_errorf(0, "loading glyph for character \\x%02x (glyph 0x%04X)",
461 i_push_errorf(0, "loading glyph for character \\x%02lx (glyph 0x%04X)",
377462 c, index);
378463 return 0;
379464 }
415500 bbox[BBOX_ASCENT] = ascent;
416501 bbox[BBOX_ADVANCE_WIDTH] = width;
417502 bbox[BBOX_RIGHT_BEARING] = rightb;
418 mm_log((1, " bbox=> negw=%d glob_desc=%d pos_wid=%d glob_asc=%d desc=%d asc=%d adv_width=%d rightb=%d\n", bbox[0], bbox[1], bbox[2], bbox[3], bbox[4], bbox[5], bbox[6], bbox[7]));
503 mm_log((1, " bbox=> negw=%" i_DF " glob_desc=%" i_DF " pos_wid=%" i_DF
504 " glob_asc=%" i_DF " desc=%" i_DF " asc=%" i_DF " adv_width=%" i_DF
505 " rightb=%" i_DF "\n",
506 i_DFc(bbox[0]), i_DFc(bbox[1]), i_DFc(bbox[2]), i_DFc(bbox[3]),
507 i_DFc(bbox[4]), i_DFc(bbox[5]), i_DFc(bbox[6]), i_DFc(bbox[7])));
419508
420509 return BBOX_RIGHT_BEARING + 1;
421510 }
503592 int glyph_ascent, glyph_descent;
504593 FT_Glyph_Metrics *gm;
505594 i_img_dim work[4];
506 i_img_dim bounds[4];
595 i_img_dim bounds[4] = { 0 };
507596 double x = 0, y = 0;
508597 int i;
509598 FT_GlyphSlot slot;
541630 error = FT_Load_Glyph(handle->face, index, loadFlags);
542631 if (error) {
543632 ft2_push_message(error);
544 i_push_errorf(0, "loading glyph for character \\x%02x (glyph 0x%04X)",
633 i_push_errorf(0, "loading glyph for character \\x%02lx (glyph 0x%04X)",
545634 c, index);
546635 return 0;
547636 }
654743 char last_mode = ft_pixel_mode_none;
655744 int last_grays = -1;
656745 int loadFlags = FT_LOAD_DEFAULT;
657 i_render *render;
658
659 mm_log((1, "i_ft2_text(handle %p, im %p, tx %d, ty %d, cl %p, cheight %f, cwidth %f, text %p, len %d, align %d, aa %d)\n",
660 handle, im, tx, ty, cl, cheight, cwidth, text, align, aa));
746 i_render *render = NULL;
747
748 mm_log((1, "i_ft2_text(handle %p, im %p, (tx,ty) (" i_DFp "), cl %p, cheight %f, cwidth %f, text %p, len %u, align %d, aa %d, vlayout %d, utf8 %d)\n",
749 handle, im, i_DFcp(tx, ty), cl, cheight, cwidth, text, (unsigned)len, align, aa, vlayout, utf8));
750
751 i_clear_error();
661752
662753 if (vlayout) {
663754 if (!FT_HAS_VERTICAL(handle->face)) {
699790 error = FT_Load_Glyph(handle->face, index, loadFlags);
700791 if (error) {
701792 ft2_push_message(error);
702 i_push_errorf(0, "loading glyph for character \\x%02x (glyph 0x%04X)",
793 i_push_errorf(0, "loading glyph for character \\x%02lx (glyph 0x%04X)",
703794 c, index);
704 if (aa)
795 if (render)
705796 i_render_delete(render);
706797 return 0;
707798 }
712803 error = FT_Render_Glyph(slot, aa ? ft_render_mode_normal : ft_render_mode_mono);
713804 if (error) {
714805 ft2_push_message(error);
715 i_push_errorf(0, "rendering glyph 0x%04X (character \\x%02X)");
716 if (aa)
806 i_push_errorf(0, "rendering glyph 0x%04lX (character \\x%02X)", c, index);
807 if (render)
717808 i_render_delete(render);
718809 return 0;
719810 }
764855 ty -= slot->advance.y / 64;
765856 }
766857
767 if (aa)
858 if (render)
768859 i_render_delete(render);
769860
770861 return 1;
771862 }
772863
773864 /*
774 =item i_ft2_cp(FT2_Fonthandle *handle, i_img *im, int tx, int ty, int channel, double cheight, double cwidth, char *text, size_t len, int align, int aa)
865 =item i_ft2_cp(FT2_Fonthandle *handle, i_img *im, int tx, int ty, int channel, double cheight, double cwidth, char *text, size_t len, int align, int aa, int vlayout, int utf8)
775866
776867 Renders I<text> to (I<tx>, I<ty>) in I<im> to I<channel> at the given
777868 I<cheight> and I<cwidth>.
781872 is rendered with (I<tx>, I<ty>) aligned with the base-line of the
782873 characters.
783874
784 If aa is non-zero then the text is anti-aliased.
875 If C<utf8> is non-zero the text is treated as UTF-8 encoded
876
877 If C<aa> is non-zero then the text is drawn anti-aliased.
785878
786879 Returns non-zero on success.
787880
797890 i_color cl, cl2;
798891 int x, y;
799892
800 mm_log((1, "i_ft2_cp(handle %p, im %p, tx %d, ty %d, channel %d, cheight %f, cwidth %f, text %p, len %d, ...)\n",
801 handle, im, tx, ty, channel, cheight, cwidth, text, len));
893 mm_log((1, "i_ft2_cp(handle %p, im %p, (tx, ty) (" i_DFp "), channel %d, cheight %f, cwidth %f, text %p, len %u, align %d, aa %d, vlayout %d, utf8 %d)\n",
894 handle, im, i_DFcp(tx, ty), channel, cheight, cwidth, text, (unsigned)len, align, aa, vlayout, utf8));
895
896 i_clear_error();
802897
803898 if (vlayout && !FT_HAS_VERTICAL(handle->face)) {
804899 i_push_error(0, "face has no vertical metrics");
810905
811906 work = i_img_8_new(bbox[2]-bbox[0]+1, bbox[3]-bbox[1]+1, 1);
812907 cl.channel[0] = 255;
908 cl.channel[1] = 255;
813909 if (!i_ft2_text(handle, work, -bbox[0], -bbox[1], &cl, cheight, cwidth,
814910 text, len, 1, aa, vlayout, utf8))
815911 return 0;
846942 i_ft2_has_chars(FT2_Fonthandle *handle, char const *text, size_t len,
847943 int utf8, char *out) {
848944 int count = 0;
849 mm_log((1, "i_ft2_has_chars(handle %p, text %p, len %d, utf8 %d)\n",
850 handle, text, len, utf8));
945 mm_log((1, "i_ft2_has_chars(handle %p, text %p, len %u, utf8 %d)\n",
946 handle, text, (unsigned)len, utf8));
947
948 i_clear_error();
851949
852950 while (len) {
853951 unsigned long c;
10401138 *name_buf = '\0';
10411139 return 0;
10421140 }
1141 if (strcmp(name_buf, ".notdef") == 0) {
1142 *name_buf = 0;
1143 return 0;
1144 }
10431145 if (*name_buf) {
10441146 return strlen(name_buf) + 1;
10451147 }
10481150 }
10491151 }
10501152 else {
1051 i_push_error(0, "no glyph for that character");
10521153 *name_buf = 0;
10531154 return 0;
10541155 }
10691170 #ifdef FT_CONFIG_OPTION_NO_GLYPH_NAMES
10701171 return 0;
10711172 #else
1072 return FT_Has_PS_Glyph_Names(handle->face);
1173 return FT_HAS_GLYPH_NAMES(handle->face);
1174 /* return FT_Has_PS_Glyph_Names(handle->face);*/
10731175 #endif
10741176 }
10751177
66
77 typedef FT2_Fonthandle* Imager__Font__FT2x;
88
9 extern int i_ft2_init(void);
9 extern int i_ft2_version(int runtime, char *buf, size_t buf_size);
10 extern void i_ft2_start(void);
1011 extern FT2_Fonthandle * i_ft2_new(const char *name, int index);
1112 extern void i_ft2_destroy(FT2_Fonthandle *handle);
1213 extern int i_ft2_setdpi(FT2_Fonthandle *handle, int xdpi, int ydpi);
44
55 use Imager qw(:all);
66
7 use Imager::Test qw(diff_text_with_nul is_color3 is_color4 isnt_image);
7 use Imager::Test qw(diff_text_with_nul is_color3 is_color4 isnt_image is_image);
88
99 -d "testout" or mkdir "testout";
1010
2222
2323 -f $fontname or skip("cannot find fontfile $fontname", 189);
2424
25 print STDERR "FreeType2 runtime ", Imager::Font::FT2::i_ft2_version(1),
26 " compile-time ", Imager::Font::FT2::i_ft2_version(0), "\n";
2527
2628 my $bgcolor=i_color_new(255,0,0,0);
2729 my $overlay=Imager::ImgRaw::new(200,70,3);
134136 aa=>1), "drawn UTF natively")) {
135137 print "# ",$im->errstr,"\n";
136138 }
139
137140 }
138141
139142 # an attempt using emulation of UTF8
601604 color => $color);
602605
603606 }
607
608
0 #!perl -w
1 use strict;
2 use Imager;
3
4 use Config;
5 my $loaded_threads;
6 BEGIN {
7 if ($Config{useithreads} && $] > 5.008007) {
8 $loaded_threads =
9 eval {
10 require threads;
11 threads->import;
12 1;
13 };
14 }
15 }
16
17 use Test::More;
18
19 $Config{useithreads}
20 or plan skip_all => "can't test Imager's lack of threads support with no threads";
21 $] > 5.008007
22 or plan skip_all => "require a perl with CLONE_SKIP to test Imager's lack of threads support";
23 $loaded_threads
24 or plan skip_all => "couldn't load threads";
25
26 $INC{"Devel/Cover.pm"}
27 and plan skip_all => "threads and Devel::Cover don't get along";
28
29 # https://rt.cpan.org/Ticket/Display.html?id=65812
30 # https://github.com/schwern/test-more/issues/labels/Test-Builder2#issue/100
31 $Test::More::VERSION =~ /^2\.00_/
32 and plan skip_all => "threads are hosed in 2.00_06 and presumably all 2.00_*";
33
34 plan tests => 8;
35
36 Imager->open_log(log => "testout/t20thread.log");
37
38 my $ft1 = Imager::Font->new(file => "fontfiles/dodge.ttf", type => "ft2");
39 ok($ft1, "make a font");
40 ok($ft1->_valid, "and it's valid");
41 my $ft2;
42
43 my $thr = threads->create
44 (
45 sub {
46 ok(!$ft1->_valid, "first font no longer valid");
47 $ft2 = Imager::Font->new(file => "fontfiles/dodge.ttf", type => "ft2");
48 ok($ft2, "make a new font in thread");
49 ok($ft2->_valid, "and it's valid");
50 1;
51 },
52 );
53
54 ok($thr->join, "join the thread");
55 ok($ft1->_valid, "original font still valid in main thread");
56 is($ft2, undef, "font created in thread shouldn't be set in main thread");
57
58 Imager->close_log();
0 #!perl -w
1 use strict;
2 use Imager::Test qw(std_font_tests std_font_test_count);
3 use Imager::Font;
4 use Test::More tests => std_font_test_count();
5
6 Imager->open_log(log => "testout/t90std.log");
7
8 my $font = Imager::Font->new(file => "fontfiles/dodge.ttf",
9 type => "ft2");
10 my $name_font =
11 Imager::Font->new(file => "fontfiles/ImUgly.ttf",
12 type => "ft2");
13
14 SKIP:
15 {
16 $font
17 or skip "Cannot load font", std_font_test_count();
18 std_font_tests
19 ({
20 font => $font,
21 has_chars => [ 1, 1, 1 ],
22 files => 1,
23 glyph_name_font => $name_font,
24 glyph_names => [ "A", "uni2010", "A" ],
25 });
26 }
27
28 Imager->close_log;
33 use vars qw($VERSION @ISA);
44
55 BEGIN {
6 $VERSION = "0.85";
6 $VERSION = "0.87";
77
88 require XSLoader;
99 XSLoader::load('Imager::File::GIF', $VERSION);
146146 BOOT:
147147 PERL_INITIALIZE_IMAGER_CALLBACKS;
148148 PERL_INITIALIZE_IMAGER_PERL_CALLBACKS;
149 i_init_gif();
3737 $opts{TYPEMAPS} = [ Imager::ExtUtils->typemap ];
3838
3939 # Imager required configure through use
40 my @Imager_req = ( Imager => "0.86" );
40 my @Imager_req = ( Imager => "0.94" );
4141 if ($MM_ver >= 6.46) {
4242 $opts{META_MERGE} =
4343 {
11
22 It requires libgif to be installed, including development headers.
33
4 This is currently shipped as part of Imager, but Imager may install
5 with out installing Imager::File::GIF, so if you need GIF support, add
6 a dependency on Imager::File::GIF.
4 For Linux distributions this typically requires installation of the
5 associated -dev or -devel package.
6
7 See Imager::Install for more information.
8
9 Imager::File::GIF is currently shipped as part of Imager, but Imager
10 may install with out installing Imager::File::GIF, so if you need GIF
11 support, add a dependency on Imager::File::GIF.
12
13 Makefile.PL will reject libgif 4.2.0 and 5.0.0 due to bugs in those
14 releases.
6565 #define myGifError(gif) ((gif)->Error)
6666 #define MakeMapObject GifMakeMapObject
6767 #define FreeMapObject GifFreeMapObject
68
68 #define gif_mutex_lock(mutex)
69 #define gif_mutex_unlock(mutex)
6970 #else
7071 #define PRE_SET_VERSION
7172 static GifFileType *
8586 return result;
8687 }
8788 #define myGifError(gif) GifLastError()
89 #define gif_mutex_lock(mutex) i_mutex_lock(mutex)
90 #define gif_mutex_unlock(mutex) i_mutex_unlock(mutex)
8891
8992 #endif
9093
9699 static const int
97100 InterlacedOffset[] = { 0, 4, 2, 1 }, /* The way Interlaced image should. */
98101 InterlacedJumps[] = { 8, 8, 4, 2 }; /* be read - offsets and jumps... */
102
103 #if !defined(GIFLIB_MAJOR) || GIFLIB_MAJOR < 5
104 static i_mutex_t mutex;
105 #endif
106
107 void
108 i_init_gif(void) {
109 #if !defined(GIFLIB_MAJOR) || GIFLIB_MAJOR < 5
110 mutex = i_mutex_new();
111 #endif
112 }
99113
100114 static
101115 void
876890 i_readgif_multi_wiol(io_glue *ig, int *count) {
877891 GifFileType *GifFile;
878892 int gif_error;
893 i_img **result;
894
895 gif_mutex_lock(mutex);
879896
880897 i_clear_error();
881898
883900 gif_push_error(gif_error);
884901 i_push_error(0, "Cannot create giflib callback object");
885902 mm_log((1,"i_readgif_multi_wiol: Unable to open callback datasource.\n"));
903 gif_mutex_unlock(mutex);
886904 return NULL;
887905 }
888906
889 return i_readgif_multi_low(GifFile, count, -1);
907 result = i_readgif_multi_low(GifFile, count, -1);
908
909 gif_mutex_unlock(mutex);
910
911 return result;
890912 }
891913
892914 static int
900922 i_readgif_wiol(io_glue *ig, int **color_table, int *colors) {
901923 GifFileType *GifFile;
902924 int gif_error;
925 i_img *result;
926
927 gif_mutex_lock(mutex);
903928
904929 i_clear_error();
905930
907932 gif_push_error(gif_error);
908933 i_push_error(0, "Cannot create giflib callback object");
909934 mm_log((1,"i_readgif_wiol: Unable to open callback datasource.\n"));
935 gif_mutex_unlock(mutex);
910936 return NULL;
911937 }
912938
913 return i_readgif_low(GifFile, color_table, colors);
939 result = i_readgif_low(GifFile, color_table, colors);
940
941 gif_mutex_unlock(mutex);
942
943 return result;
914944 }
915945
916946 /*
956986 i_readgif_single_wiol(io_glue *ig, int page) {
957987 GifFileType *GifFile;
958988 int gif_error;
989 i_img *result;
959990
960991 i_clear_error();
961992 if (page < 0) {
963994 return NULL;
964995 }
965996
997 gif_mutex_lock(mutex);
966998
967999 if ((GifFile = myDGifOpen((void *)ig, io_glue_read_cb, &gif_error )) == NULL) {
9681000 gif_push_error(gif_error);
9691001 i_push_error(0, "Cannot create giflib callback object");
9701002 mm_log((1,"i_readgif_wiol: Unable to open callback datasource.\n"));
1003 gif_mutex_unlock(mutex);
9711004 return NULL;
9721005 }
9731006
974 return i_readgif_single_low(GifFile, page);
1007 result = i_readgif_single_low(GifFile, page);
1008
1009 gif_mutex_unlock(mutex);
1010
1011 return result;
9751012 }
9761013
9771014 /*
18291866 int gif_error;
18301867 int result;
18311868
1869 gif_mutex_lock(mutex);
1870
18321871 i_clear_error();
18331872
18341873 #ifdef PRE_SET_VERSION
18391878 gif_push_error(gif_error);
18401879 i_push_error(0, "Cannot create giflib callback object");
18411880 mm_log((1,"i_writegif_wiol: Unable to open callback datasource.\n"));
1881 gif_mutex_unlock(mutex);
18421882 return 0;
18431883 }
18441884
18481888
18491889 result = i_writegif_low(quant, GifFile, imgs, count);
18501890
1891 gif_mutex_unlock(mutex);
1892
18511893 if (i_io_close(ig))
18521894 return 0;
18531895
19692011
19702012 Arnar M. Hrafnkelsson, addi@umich.edu
19712013
2014 Tony Cook <tonyc@cpan.org>
2015
19722016 =head1 SEE ALSO
19732017
19742018 perl(1), Imager(3)
22
33 #include "imext.h"
44
5 void i_init_gif(void);
56 double i_giflib_version(void);
67 i_img *i_readgif_wiol(io_glue *ig, int **colour_table, int *colours);
78 i_img *i_readgif_single_wiol(io_glue *ig, int page);
22 use strict;
33 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS %formats $DEBUG %filters %DSOs $ERRSTR %OPCODES $I2P $FORMATGUESS $warn_obsolete);
44 use IO::File;
5
5 use Scalar::Util;
66 use Imager::Color;
77 use Imager::Font;
8 use Config;
89
910 @EXPORT_OK = qw(
1011 init
142143 if ($ex_version < 5.57) {
143144 @ISA = qw(Exporter);
144145 }
145 $VERSION = '0.93';
146 $VERSION = '0.95';
146147 require XSLoader;
147148 XSLoader::load(Imager => $VERSION);
148149 }
618619 sub _valid_image {
619620 my ($self, $method) = @_;
620621
621 $self->{IMG} and return 1;
622
623 my $msg = 'empty input image';
622 $self->{IMG} && Scalar::Util::blessed($self->{IMG}) and return 1;
623
624 my $msg = $self->{IMG} ? "images do not cross threads" : "empty input image";
624625 $msg = "$method: $msg" if $method;
625626 $self->_set_error($msg);
626627
686687
687688 sub copy {
688689 my $self = shift;
689 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
690
691 $self->_valid_image("copy")
692 or return;
690693
691694 unless (defined wantarray) {
692695 my @caller = caller;
704707 sub paste {
705708 my $self = shift;
706709
707 unless ($self->{IMG}) {
708 $self->_set_error('empty input image');
709 return;
710 }
710 $self->_valid_image("paste")
711 or return;
712
711713 my %input=(left=>0, top=>0, src_minx => 0, src_miny => 0, @_);
712714 my $src = $input{img} || $input{src};
713715 unless($src) {
714716 $self->_set_error("no source image");
717 return;
718 }
719 unless ($src->_valid_image("paste")) {
720 $self->{ERRSTR} = $src->{ERRSTR} . " (for src)";
715721 return;
716722 }
717723 $input{left}=0 if $input{left} <= 0;
772778
773779 sub crop {
774780 my $self=shift;
775 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
781
782 $self->_valid_image("crop")
783 or return;
776784
777785 unless (defined wantarray) {
778786 my @caller = caller;
860868 sub _sametype {
861869 my ($self, %opts) = @_;
862870
863 $self->{IMG} or return $self->_set_error("Not a valid image");
871 $self->_valid_image
872 or return;
864873
865874 my $x = $opts{xsize} || $self->getwidth;
866875 my $y = $opts{ysize} || $self->getheight;
923932 sub masked {
924933 my $self = shift;
925934
926 $self or return undef;
935 $self->_valid_image("masked")
936 or return;
937
927938 my %opts = (left => 0,
928939 top => 0,
929940 right => $self->getwidth,
964975 return;
965976 }
966977
967 $self->_valid_image
978 $self->_valid_image("to_paletted")
968979 or return;
969980
970981 my $result = Imager->new;
10051016 return;
10061017 }
10071018
1008 $self->_valid_image
1019 $self->_valid_image("to_rgb8")
10091020 or return;
10101021
10111022 my $result = Imager->new;
10271038 return;
10281039 }
10291040
1030 $self->_valid_image
1041 $self->_valid_image("to_rgb16")
10311042 or return;
10321043
10331044 my $result = Imager->new;
10491060 return;
10501061 }
10511062
1052 $self->_valid_image
1063 $self->_valid_image("to_rgb_double")
10531064 or return;
10541065
10551066 my $result = Imager->new;
10651076 my $self = shift;
10661077 my %opts = (colors=>[], @_);
10671078
1068 unless ($self->{IMG}) {
1069 $self->_set_error("empty input image");
1070 return;
1071 }
1079 $self->_valid_image("addcolors")
1080 or return -1;
10721081
10731082 my @colors = @{$opts{colors}}
10741083 or return undef;
10881097 my $self = shift;
10891098 my %opts = (start=>0, colors=>[], @_);
10901099
1091 unless ($self->{IMG}) {
1092 $self->_set_error("empty input image");
1093 return;
1094 }
1100 $self->_valid_image("setcolors")
1101 or return;
10951102
10961103 my @colors = @{$opts{colors}}
10971104 or return undef;
11101117 sub getcolors {
11111118 my $self = shift;
11121119 my %opts = @_;
1120
1121 $self->_valid_image("getcolors")
1122 or return;
1123
11131124 if (!exists $opts{start} && !exists $opts{count}) {
11141125 # get them all
11151126 $opts{start} = 0;
11211132 elsif (!exists $opts{start}) {
11221133 $opts{start} = 0;
11231134 }
1124
1125 $self->{IMG} and
1126 return i_getcolors($self->{IMG}, $opts{start}, $opts{count});
1135
1136 return i_getcolors($self->{IMG}, $opts{start}, $opts{count});
11271137 }
11281138
11291139 sub colorcount {
1130 i_colorcount($_[0]{IMG});
1140 my ($self) = @_;
1141
1142 $self->_valid_image("colorcount")
1143 or return -1;
1144
1145 return i_colorcount($self->{IMG});
11311146 }
11321147
11331148 sub maxcolors {
1134 i_maxcolors($_[0]{IMG});
1149 my $self = shift;
1150
1151 $self->_valid_image("maxcolors")
1152 or return -1;
1153
1154 i_maxcolors($self->{IMG});
11351155 }
11361156
11371157 sub findcolor {
11381158 my $self = shift;
11391159 my %opts = @_;
1140 $opts{color} or return undef;
1141
1142 $self->{IMG} and i_findcolor($self->{IMG}, $opts{color});
1160
1161 $self->_valid_image("findcolor")
1162 or return;
1163
1164 unless ($opts{color}) {
1165 $self->_set_error("findcolor: no color parameter");
1166 return;
1167 }
1168
1169 my $color = _color($opts{color})
1170 or return;
1171
1172 return i_findcolor($self->{IMG}, $color);
11431173 }
11441174
11451175 sub bits {
11461176 my $self = shift;
1147 my $bits = $self->{IMG} && i_img_bits($self->{IMG});
1177
1178 $self->_valid_image("bits")
1179 or return;
1180
1181 my $bits = i_img_bits($self->{IMG});
11481182 if ($bits && $bits == length(pack("d", 1)) * 8) {
11491183 $bits = 'double';
11501184 }
1151 $bits;
1185 return $bits;
11521186 }
11531187
11541188 sub type {
11551189 my $self = shift;
1156 if ($self->{IMG}) {
1157 return i_img_type($self->{IMG}) ? "paletted" : "direct";
1158 }
1190
1191 $self->_valid_image("type")
1192 or return;
1193
1194 return i_img_type($self->{IMG}) ? "paletted" : "direct";
11591195 }
11601196
11611197 sub virtual {
11621198 my $self = shift;
1163 $self->{IMG} and i_img_virtual($self->{IMG});
1199
1200 $self->_valid_image("virtual")
1201 or return;
1202
1203 return i_img_virtual($self->{IMG});
11641204 }
11651205
11661206 sub is_bilevel {
11671207 my ($self) = @_;
11681208
1169 $self->{IMG} or return;
1209 $self->_valid_image("is_bilevel")
1210 or return;
11701211
11711212 return i_img_is_monochrome($self->{IMG});
11721213 }
11741215 sub tags {
11751216 my ($self, %opts) = @_;
11761217
1177 $self->{IMG} or return;
1218 $self->_valid_image("tags")
1219 or return;
11781220
11791221 if (defined $opts{name}) {
11801222 my @result;
12101252 my $self = shift;
12111253 my %opts = @_;
12121254
1213 return -1 unless $self->{IMG};
1255 $self->_valid_image("addtag")
1256 or return;
1257
12141258 if ($opts{name}) {
12151259 if (defined $opts{value}) {
12161260 if ($opts{value} =~ /^\d+$/) {
12581302 my $self = shift;
12591303 my %opts = @_;
12601304
1261 return 0 unless $self->{IMG};
1305 $self->_valid_image("deltag")
1306 or return 0;
12621307
12631308 if (defined $opts{'index'}) {
12641309 return i_tags_delete($self->{IMG}, $opts{'index'});
12781323 sub settag {
12791324 my ($self, %opts) = @_;
12801325
1326 $self->_valid_image("settag")
1327 or return;
1328
12811329 if ($opts{name}) {
12821330 $self->deltag(name=>$opts{name});
12831331 return $self->addtag(name=>$opts{name}, value=>$opts{value});
13021350 return io_new_fd($input->{fd});
13031351 }
13041352 elsif ($input->{fh}) {
1305 my $fd = fileno($input->{fh});
1306 unless (defined $fd) {
1353 unless (Scalar::Util::openhandle($input->{fh})) {
13071354 $self->_set_error("Handle in fh option not opened");
13081355 return;
13091356 }
1310 return io_new_fd($fd);
1357 return Imager::IO->new_fh($input->{fh});
13111358 }
13121359 elsif ($input->{file}) {
13131360 my $file = IO::File->new($input->{file}, "r");
13571404 $io = io_new_fd($input->{fd});
13581405 }
13591406 elsif ($input->{fh}) {
1360 my $fd = fileno($input->{fh});
1361 unless (defined $fd) {
1407 unless (Scalar::Util::openhandle($input->{fh})) {
13621408 $self->_set_error("Handle in fh option not opened");
13631409 return;
13641410 }
1365 # flush it
1366 my $oldfh = select($input->{fh});
1367 # flush anything that's buffered, and make sure anything else is flushed
1368 $| = 1;
1369 select($oldfh);
1370 $io = io_new_fd($fd);
1411 $io = Imager::IO->new_fh($input->{fh});
13711412 }
13721413 elsif ($input->{file}) {
13731414 my $fh = new IO::File($input->{file},"w+");
17701811 fax_fine=>1, @_);
17711812 my $rc;
17721813
1814 $self->_valid_image("write")
1815 or return;
1816
17731817 $self->_set_opts(\%input, "i_", $self)
17741818 or return undef;
1775
1776 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
17771819
17781820 my $type = $input{'type'};
17791821 if (!$type and $input{file}) {
18671909 return;
18681910 }
18691911 # translate to ImgRaw
1870 if (grep !UNIVERSAL::isa($_, 'Imager') || !$_->{IMG}, @images) {
1871 $class->_set_error('Usage: Imager->write_multi({ options }, @images)');
1872 return 0;
1912 my $index = 1;
1913 for my $img (@images) {
1914 unless ($img->_valid_image("write_multi")) {
1915 $class->_set_error($img->errstr . " (image $index)");
1916 return;
1917 }
1918 ++$index;
18731919 }
18741920 $class->_set_opts($opts, "i_", @images)
18751921 or return;
20032049 my $self=shift;
20042050 my %input=@_;
20052051 my %hsh;
2006 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2052
2053 $self->_valid_image("filter")
2054 or return;
20072055
20082056 if (!$input{'type'}) { $self->{ERRSTR}='type parameter missing'; return undef; }
20092057
21782226 return;
21792227 }
21802228
2181 unless ($self->{IMG}) {
2182 $self->_set_error('empty input image');
2183 return undef;
2184 }
2229 $self->_valid_image("scale")
2230 or return;
21852231
21862232 my ($x_scale, $y_scale, $new_width, $new_height) =
21872233 $self->scale_calculate(%opts)
22352281 return;
22362282 }
22372283
2238 unless ($self->{IMG}) {
2239 $self->{ERRSTR} = 'empty input image';
2240 return undef;
2241 }
2284 $self->_valid_image("scaleX")
2285 or return;
22422286
22432287 my $img = Imager->new();
22442288
22752319 return;
22762320 }
22772321
2278 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2322 $self->_valid_image("scaleY")
2323 or return;
22792324
22802325 my $img = Imager->new();
22812326
23062351
23072352 sub transform {
23082353 my $self=shift;
2309 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
23102354 my %opts=@_;
23112355 my (@op,@ropx,@ropy,$iop,$or,@parm,$expr,@xt,@yt,@pt,$numre);
23122356
23132357 # print Dumper(\%opts);
23142358 # xopcopdes
2359
2360 $self->_valid_image("transform")
2361 or return;
23152362
23162363 if ( $opts{'xexpr'} and $opts{'yexpr'} ) {
23172364 if (!$I2P) {
24042451 $opts->{variables} = [ qw(x y) ];
24052452 my ($width, $height) = @{$opts}{qw(width height)};
24062453 if (@imgs) {
2454 my $index = 1;
2455 for my $img (@imgs) {
2456 unless ($img->_valid_image("transform2")) {
2457 Imager->_set_error($img->errstr . " (input image $index)");
2458 return;
2459 }
2460 ++$index;
2461 }
2462
24072463 $width ||= $imgs[0]->getwidth();
24082464 $height ||= $imgs[0]->getheight();
24092465 my $img_num = 1;
24582514 my $self=shift;
24592515 my %opts= @_;
24602516
2461 unless ($self->{IMG}) {
2462 $self->{ERRSTR}='empty input image';
2463 return undef;
2464 }
2465 unless ($opts{src} && $opts{src}->{IMG}) {
2466 $self->{ERRSTR}='empty input image for src';
2467 return undef;
2517 $self->_valid_image("rubthrough")
2518 or return;
2519
2520 unless ($opts{src} && $opts{src}->_valid_image("rubthrough")) {
2521 $self->{ERRSTR} = $opts{src}{ERRSTR} . ' (for src)';
2522 return;
24682523 }
24692524
24702525 %opts = (src_minx => 0,
25012556 @_
25022557 );
25032558
2504 unless ($self->{IMG}) {
2505 $self->_set_error("compose: empty input image");
2506 return;
2507 }
2559 $self->_valid_image("compose")
2560 or return;
25082561
25092562 unless ($opts{src}) {
25102563 $self->_set_error("compose: src parameter missing");
25112564 return;
25122565 }
25132566
2514 unless ($opts{src}{IMG}) {
2515 $self->_set_error("compose: src parameter empty image");
2567 unless ($opts{src}->_valid_image("compose")) {
2568 $self->_set_error($opts{src}->errstr . " (for src)");
25162569 return;
25172570 }
25182571 my $src = $opts{src};
25482601 my $combine = $self->_combine($opts{combine}, 'normal');
25492602
25502603 if ($opts{mask}) {
2551 unless ($opts{mask}{IMG}) {
2552 $self->_set_error("compose: mask parameter empty image");
2604 unless ($opts{mask}->_valid_image("compose")) {
2605 $self->_set_error($opts{mask}->errstr . " (for mask)");
25532606 return;
25542607 }
25552608
25832636 sub flip {
25842637 my $self = shift;
25852638 my %opts = @_;
2639
2640 $self->_valid_image("flip")
2641 or return;
2642
25862643 my %xlate = (h=>0, v=>1, hv=>2, vh=>2);
25872644 my $dir;
25882645 return () unless defined $opts{'dir'} and defined $xlate{$opts{'dir'}};
26002657 warn "rotate() called in void context - rotate() returns the rotated image at $caller[1] line $caller[2]\n";
26012658 return;
26022659 }
2660
2661 $self->_valid_image("rotate")
2662 or return;
26032663
26042664 if (defined $opts{right}) {
26052665 my $degrees = $opts{right};
26602720 my $self = shift;
26612721 my %opts = @_;
26622722
2723 $self->_valid_image("matrix_transform")
2724 or return;
2725
26632726 unless (defined wantarray) {
26642727 my @caller = caller;
26652728 warn "copy() called in void context - copy() returns the copied image at $caller[1] line $caller[2]\n";
27082771 my $self=shift;
27092772 my $raw = $self->{IMG};
27102773
2711 unless ($raw) {
2712 $self->{ERRSTR}='empty input image';
2713 return undef;
2714 }
2774 $self->_valid_image("box")
2775 or return;
27152776
27162777 my %opts = @_;
27172778
27892850
27902851 sub arc {
27912852 my $self=shift;
2792 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2853
2854 $self->_valid_image("arc")
2855 or return;
2856
27932857 my $dflcl= [ 255, 255, 255, 255];
27942858 my $good = 1;
27952859 my %opts=
28912955 my %opts=(color=>$dflcl,
28922956 endp => 1,
28932957 @_);
2894 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2958
2959 $self->_valid_image("line")
2960 or return;
28952961
28962962 unless (exists $opts{x1} and exists $opts{y1}) { $self->{ERRSTR}='missing begining coord'; return undef; }
28972963 unless (exists $opts{x2} and exists $opts{y2}) { $self->{ERRSTR}='missing ending coord'; return undef; }
29222988 my $dflcl=i_color_new(0,0,0,0);
29232989 my %opts=(color=>$dflcl,@_);
29242990
2925 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
2991 $self->_valid_image("polyline")
2992 or return;
29262993
29272994 if (exists($opts{points})) { @points=@{$opts{points}}; }
29282995 if (!exists($opts{points}) and exists($opts{'x'}) and exists($opts{'y'}) ) {
29613028 my $dflcl = i_color_new(0,0,0,0);
29623029 my %opts = (color=>$dflcl, @_);
29633030
2964 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
3031 $self->_valid_image("polygon")
3032 or return;
29653033
29663034 if (exists($opts{points})) {
29673035 $opts{'x'} = [ map { $_->[0] } @{$opts{points}} ];
30083076 my $dflcl=i_color_new(0,0,0,0);
30093077 my %opts=(color=>$dflcl,@_);
30103078
3011 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
3079 $self->_valid_image("polybezier")
3080 or return;
30123081
30133082 if (exists $opts{points}) {
30143083 $opts{'x'}=map { $_->[0]; } @{$opts{'points'}};
30333102 my $self = shift;
30343103 my %opts = ( color=>Imager::Color->new(255, 255, 255), @_ );
30353104 my $rc;
3105
3106 $self->_valid_image("flood_fill")
3107 or return;
30363108
30373109 unless (exists $opts{'x'} && exists $opts{'y'}) {
30383110 $self->{ERRSTR} = "missing seed x and y parameters";
32513323 my $self = shift;
32523324 my %opts = ( type => '8bit', x=>0, @_);
32533325
3254 $self->_valid_image or return;
3326 $self->_valid_image("getscanline")
3327 or return;
32553328
32563329 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
32573330
32863359 my $self = shift;
32873360 my %opts = ( x=>0, @_);
32883361
3289 $self->_valid_image or return;
3362 $self->_valid_image("setscanline")
3363 or return;
32903364
32913365 unless (defined $opts{'y'}) {
32923366 $self->_set_error("missing y parameter");
33463420 sub getsamples {
33473421 my $self = shift;
33483422 my %opts = ( type => '8bit', x=>0, offset => 0, @_);
3423
3424 $self->_valid_image("getsamples")
3425 or return;
33493426
33503427 defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
33513428
34173494 sub setsamples {
34183495 my $self = shift;
34193496
3420 unless ($self->{IMG}) {
3421 $self->_set_error('setsamples: empty input image');
3422 return;
3423 }
3497 $self->_valid_image("setsamples")
3498 or return;
34243499
34253500 my %opts = ( x => 0, offset => 0 );
34263501 my $data_index;
35013576 sub convert {
35023577 my ($self, %opts) = @_;
35033578 my $matrix;
3579
3580 $self->_valid_image("convert")
3581 or return;
35043582
35053583 unless (defined wantarray) {
35063584 my @caller = caller;
36203698 $class->_set_error("src must contain image objects");
36213699 return;
36223700 }
3623 unless ($img->{IMG}) {
3624 $class->_set_error("empty input image");
3701 unless ($img->_valid_image("combine")) {
3702 $Imager::ERRSTR = $img->{ERRSTR} . " (src->[$index])";
36253703 return;
36263704 }
36273705 push @imgs, $img->{IMG};
36503728 sub map {
36513729 my ($self, %opts) = @_;
36523730 my @chlist = qw( red green blue alpha );
3731
3732 $self->_valid_image("map")
3733 or return;
36533734
36543735 if (!exists($opts{'maps'})) {
36553736 # make maps from channel maps
36713752 sub difference {
36723753 my ($self, %opts) = @_;
36733754
3755 $self->_valid_image("difference")
3756 or return;
3757
36743758 defined $opts{mindist} or $opts{mindist} = 0;
36753759
36763760 defined $opts{other}
36773761 or return $self->_set_error("No 'other' parameter supplied");
3678 defined $opts{other}{IMG}
3679 or return $self->_set_error("No image data in 'other' image");
3680
3681 $self->{IMG}
3682 or return $self->_set_error("No image data");
3762 unless ($opts{other}->_valid_image("difference")) {
3763 $self->_set_error($opts{other}->errstr . " (other image)");
3764 return;
3765 }
36833766
36843767 my $result = Imager->new;
36853768 $result->{IMG} = i_diff_image($self->{IMG}, $opts{other}{IMG},
37033786 sub getwidth {
37043787 my $self = shift;
37053788
3706 if (my $raw = $self->{IMG}) {
3707 return i_img_get_width($raw);
3708 }
3709 else {
3710 $self->{ERRSTR} = 'image is empty'; return undef;
3711 }
3789 $self->_valid_image("getwidth")
3790 or return;
3791
3792 return i_img_get_width($self->{IMG});
37123793 }
37133794
37143795 # Get the height of an image
37163797 sub getheight {
37173798 my $self = shift;
37183799
3719 if (my $raw = $self->{IMG}) {
3720 return i_img_get_height($raw);
3721 }
3722 else {
3723 $self->{ERRSTR} = 'image is empty'; return undef;
3724 }
3800 $self->_valid_image("getheight")
3801 or return;
3802
3803 return i_img_get_height($self->{IMG});
37253804 }
37263805
37273806 # Get number of channels in an image
37283807
37293808 sub getchannels {
37303809 my $self = shift;
3731 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3810
3811 $self->_valid_image("getchannels")
3812 or return;
3813
37323814 return i_img_getchannels($self->{IMG});
37333815 }
37343816
37363818
37373819 sub getmask {
37383820 my $self = shift;
3739 if (!defined($self->{IMG})) { $self->{ERRSTR} = 'image is empty'; return undef; }
3821
3822 $self->_valid_image("getmask")
3823 or return;
3824
37403825 return i_img_getmask($self->{IMG});
37413826 }
37423827
37453830 sub setmask {
37463831 my $self = shift;
37473832 my %opts = @_;
3748 if (!defined($self->{IMG})) {
3749 $self->{ERRSTR} = 'image is empty';
3750 return undef;
3751 }
3833
3834 $self->_valid_image("setmask")
3835 or return;
3836
37523837 unless (defined $opts{mask}) {
37533838 $self->_set_error("mask parameter required");
37543839 return;
37553840 }
3841
37563842 i_img_setmask( $self->{IMG} , $opts{mask} );
37573843
37583844 1;
37633849 sub getcolorcount {
37643850 my $self=shift;
37653851 my %opts=('maxcolors'=>2**30,@_);
3766 if (!defined($self->{IMG})) { $self->{ERRSTR}='image is empty'; return undef; }
3852
3853 $self->_valid_image("getcolorcount")
3854 or return;
3855
37673856 my $rc=i_count_colors($self->{IMG},$opts{'maxcolors'});
37683857 return ($rc==-1? undef : $rc);
37693858 }
37723861 # values are the number of pixels in this colour.
37733862 sub getcolorusagehash {
37743863 my $self = shift;
3775
3864
3865 $self->_valid_image("getcolorusagehash")
3866 or return;
3867
37763868 my %opts = ( maxcolors => 2**30, @_ );
37773869 my $max_colors = $opts{maxcolors};
37783870 unless (defined $max_colors && $max_colors > 0) {
37793871 $self->_set_error('maxcolors must be a positive integer');
3780 return;
3781 }
3782
3783 unless (defined $self->{IMG}) {
3784 $self->_set_error('empty input image');
37853872 return;
37863873 }
37873874
38083895 sub getcolorusage {
38093896 my $self = shift;
38103897
3898 $self->_valid_image("getcolorusage")
3899 or return;
3900
38113901 my %opts = ( maxcolors => 2**30, @_ );
38123902 my $max_colors = $opts{maxcolors};
38133903 unless (defined $max_colors && $max_colors > 0) {
38153905 return;
38163906 }
38173907
3818 unless (defined $self->{IMG}) {
3819 $self->_set_error('empty input image');
3820 return undef;
3821 }
3822
38233908 return i_get_anonymous_color_histo($self->{IMG}, $max_colors);
38243909 }
38253910
38273912
38283913 sub string {
38293914 my $self = shift;
3830 unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
3915
3916 $self->_valid_image("string")
3917 or return;
38313918
38323919 my %input=('x'=>0, 'y'=>0, @_);
38333920 defined($input{string}) or $input{string} = $input{text};
38543941
38553942 my $img;
38563943 if (ref $self) {
3857 unless ($self->{IMG}) {
3858 $self->{ERRSTR}='empty input image';
3859 return;
3860 }
3944 $self->_valid_image("align_string")
3945 or return;
3946
38613947 $img = $self;
38623948 }
38633949 else {
41224208 eval { require Imager::Font::T1 };
41234209 }
41244210
4211 package Imager::IO;
4212 use IO::Seekable;
4213
4214 sub new_fh {
4215 my ($class, $fh) = @_;
4216
4217 if (tied(*$fh)) {
4218 return $class->new_cb
4219 (
4220 sub {
4221 local $\;
4222
4223 return print $fh $_[0];
4224 },
4225 sub {
4226 my $tmp;
4227 my $count = CORE::read $fh, $tmp, $_[1];
4228 defined $count
4229 or return undef;
4230 $count
4231 or return "";
4232 return $tmp;
4233 },
4234 sub {
4235 if ($_[1] != SEEK_CUR || $_[0] != 0) {
4236 unless (CORE::seek $fh, $_[0], $_[1]) {
4237 return -1;
4238 }
4239 }
4240
4241 return tell $fh;
4242 },
4243 undef,
4244 );
4245 }
4246 else {
4247 return $class->_new_perlio($fh);
4248 }
4249 }
4250
41254251 # backward compatibility for %formats
41264252 package Imager::FORMATS;
41274253 use strict;
42964422
42974423 =item *
42984424
4425 L<Imager::Install> - installation notes for Imager.
4426
4427 =item *
4428
42994429 L<Imager::Tutorial> - a brief introduction to Imager.
43004430
43014431 =item *
43624492
43634493 =item *
43644494
4495 L<Imager::IO> - Imager I/O abstraction.
4496
4497 =item *
4498
43654499 L<Imager::API> - using Imager's C API
43664500
43674501 =item *
43794513 =item *
43804514
43814515 L<Imager::Security> - brief security notes.
4516
4517 =item *
4518
4519 L<Imager::Threads> - brief information on working with threads.
43824520
43834521 =back
43844522
48214959
48224960 text, measuring - L<Imager::Font/bounding_box()>, L<Imager::Font::BBox>
48234961
4962 threads - L<Imager::Threads>
4963
48244964 tiles, color - L<Imager::Filters/mosaic>
48254965
48264966 transparent images - L<Imager::ImageTypes>,
48334973 watermark - L<Imager::Filters/watermark>
48344974
48354975 writing an image to a file - L<Imager::Files>
4836
4837 =head1 THREADS
4838
4839 Imager doesn't support perl threads.
4840
4841 Imager has limited code to prevent double frees if you create images,
4842 colors etc, and then create a thread, but has no code to prevent two
4843 threads entering Imager's error handling code, and none is likely to
4844 be added.
48454976
48464977 =head1 SUPPORT
48474978
49685099
49695100 Other perl imaging modules include:
49705101
4971 L<GD>(3), L<Image::Magick>(3), L<Graphics::Magick>(3),
5102 L<GD>(3), L<Image::Magick>(3),
5103 L<Graphics::Magick|http://www.graphicsmagick.org/perl.html>(3),
49725104 L<Prima::Image>, L<IPA>.
49735105
49745106 For manipulating image metadata see L<Image::ExifTool>.
2020 #include "regmach.h"
2121 #include "imextdef.h"
2222 #include "imextpltypes.h"
23 #include "imperlio.h"
2324 #include <float.h>
2425
2526 #if i_int_hlines_testing()
2728 #endif
2829
2930 #include "imperl.h"
31
32 /*
33
34 Context object management
35
36 */
37
38 typedef im_context_t Imager__Context;
39
40 #define im_context_DESTROY(ctx) im_context_refdec((ctx), "DESTROY")
41
42 #ifdef PERL_IMPLICIT_CONTEXT
43
44 #define MY_CXT_KEY "Imager::_context" XS_VERSION
45
46 typedef struct {
47 im_context_t ctx;
48 } my_cxt_t;
49
50 START_MY_CXT
51
52 im_context_t fallback_context;
53
54 static void
55 start_context(pTHX) {
56 dMY_CXT;
57 MY_CXT.ctx = im_context_new();
58 sv_setref_pv(get_sv("Imager::_context", GV_ADD), "Imager::Context", MY_CXT.ctx);
59
60 /* Ideally we'd free this reference, but the error message memory
61 was never released on exit, so the associated memory here is reasonable
62 to keep.
63 With logging enabled we always need at least one context, since
64 objects may be released fairly late and attempt to get the log file.
65 */
66 im_context_refinc(MY_CXT.ctx, "start_context");
67 fallback_context = MY_CXT.ctx;
68 }
69
70 static im_context_t
71 perl_get_context(void) {
72 dTHX;
73 dMY_CXT;
74
75 return MY_CXT.ctx ? MY_CXT.ctx : fallback_context;
76 }
77
78 #else
79
80 static im_context_t perl_context;
81
82 static void
83 start_context(pTHX) {
84 perl_context = im_context_new();
85 im_context_refinc(perl_context, "start_context");
86 }
87
88 static im_context_t
89 perl_get_context(void) {
90 return perl_context;
91 }
92
93 #endif
3094
3195 /* used to represent channel lists parameters */
3296 typedef struct i_channel_list_tag {
726790 }
727791 }
728792
729
730793 /* I don't think ICLF_* names belong at the C interface
731794 this makes the XS code think we have them, to let us avoid
732795 putting function bodies in the XS code
11021165 OUTPUT:
11031166 RETVAL
11041167
1168 Imager::IO
1169 io__new_perlio(class, io)
1170 PerlIO *io
1171 CODE:
1172 RETVAL = im_io_new_perlio(aTHX_ io);
1173 OUTPUT:
1174 RETVAL
1175
11051176 SV *
11061177 io_slurp(class, ig)
11071178 Imager::IO ig
11261197 void *data;
11271198 STRLEN size;
11281199 CODE:
1129 #ifdef SvUTF8
1130 if (SvUTF8(data_sv)) {
1131 data_sv = sv_2mortal(newSVsv(data_sv));
1132 /* yes, we want this to croak() if the SV can't be downgraded */
1133 sv_utf8_downgrade(data_sv, FALSE);
1134 }
1135 #endif
1136 data = SvPV(data_sv, size);
1200 data = SvPVbyte(data_sv, size);
11371201 RETVAL = i_io_raw_write(ig, data, size);
11381202 OUTPUT:
11391203 RETVAL
13581422 void *data;
13591423 STRLEN size;
13601424 CODE:
1361 #ifdef SvUTF8
1362 if (SvUTF8(data_sv)) {
1363 data_sv = sv_2mortal(newSVsv(data_sv));
1364 /* yes, we want this to croak() if the SV can't be downgraded */
1365 sv_utf8_downgrade(data_sv, FALSE);
1366 }
1367 #endif
1368 data = SvPV(data_sv, size);
1425 data = SvPVbyte(data_sv, size);
13691426 RETVAL = i_io_write(ig, data, size);
13701427 OUTPUT:
13711428 RETVAL
20592116 RETVAL
20602117
20612118
2062 void
2119 undef_int
20632120 i_map(im, pmaps)
20642121 Imager::ImgRaw im
20652122 PREINIT:
20972154 }
20982155 i_map(im, maps, mask);
20992156 myfree(maps);
2157 RETVAL = 1;
2158 OUTPUT:
2159 RETVAL
21002160
21012161
21022162
21602220
21612221
21622222 undef_int
2163 i_tt_text(handle,im,xb,yb,cl,points,str_sv,len_ignored,smooth,utf8,align=1)
2223 i_tt_text(handle,im,xb,yb,cl,points,str_sv,smooth,utf8,align=1)
21642224 Imager::Font::TT handle
21652225 Imager::ImgRaw im
21662226 i_img_dim xb
21752235 char *str;
21762236 STRLEN len;
21772237 CODE:
2238 str = SvPV(str_sv, len);
21782239 #ifdef SvUTF8
21792240 if (SvUTF8(str_sv))
21802241 utf8 = 1;
21812242 #endif
2182 str = SvPV(str_sv, len);
21832243 RETVAL = i_tt_text(handle, im, xb, yb, cl, points, str,
21842244 len, smooth, utf8, align);
21852245 OUTPUT:
21872247
21882248
21892249 undef_int
2190 i_tt_cp(handle,im,xb,yb,channel,points,str_sv,len_ignored,smooth,utf8,align=1)
2250 i_tt_cp(handle,im,xb,yb,channel,points,str_sv,smooth,utf8,align=1)
21912251 Imager::Font::TT handle
21922252 Imager::ImgRaw im
21932253 i_img_dim xb
22022262 char *str;
22032263 STRLEN len;
22042264 CODE:
2265 str = SvPV(str_sv, len);
22052266 #ifdef SvUTF8
22062267 if (SvUTF8(str_sv))
22072268 utf8 = 1;
22082269 #endif
2209 str = SvPV(str_sv, len);
22102270 RETVAL = i_tt_cp(handle, im, xb, yb, channel, points, str, len,
22112271 smooth, utf8, align);
22122272 OUTPUT:
22142274
22152275
22162276 void
2217 i_tt_bbox(handle,point,str_sv,len_ignored, utf8)
2277 i_tt_bbox(handle,point,str_sv,utf8)
22182278 Imager::Font::TT handle
22192279 double point
22202280 SV* str_sv
22262286 STRLEN len;
22272287 int i;
22282288 PPCODE:
2289 str = SvPV(str_sv, len);
22292290 #ifdef SvUTF8
22302291 if (SvUTF8(ST(2)))
22312292 utf8 = 1;
22322293 #endif
2233 str = SvPV(str_sv, len);
22342294 if ((rc=i_tt_bbox(handle,point,str,len,cords, utf8))) {
22352295 EXTEND(SP, rc);
22362296 for (i = 0; i < rc; ++i) {
22502310 size_t count;
22512311 size_t i;
22522312 PPCODE:
2313 i_clear_error();
2314 text = SvPV(text_sv, len);
22532315 #ifdef SvUTF8
22542316 if (SvUTF8(text_sv))
22552317 utf8 = 1;
22562318 #endif
2257 text = SvPV(text_sv, len);
22582319 work = mymalloc(len);
22592320 count = i_tt_has_chars(handle, text, len, utf8, work);
22602321 if (GIMME_V == G_ARRAY) {
22972358 size_t len;
22982359 size_t outsize;
22992360 char name[255];
2361 SSize_t count = 0;
23002362 PPCODE:
2363 i_clear_error();
2364 text = SvPV(text_sv, work_len);
23012365 #ifdef SvUTF8
23022366 if (SvUTF8(text_sv))
23032367 utf8 = 1;
23042368 #endif
2305 text = SvPV(text_sv, work_len);
23062369 len = work_len;
23072370 while (len) {
23082371 unsigned long ch;
23102373 ch = i_utf8_advance(&text, &len);
23112374 if (ch == ~0UL) {
23122375 i_push_error(0, "invalid UTF8 character");
2313 break;
2376 XSRETURN_EMPTY;
23142377 }
23152378 }
23162379 else {
23172380 ch = *text++;
23182381 --len;
23192382 }
2320 EXTEND(SP, 1);
2383 EXTEND(SP, count+1);
23212384 if ((outsize = i_tt_glyph_name(handle, ch, name, sizeof(name))) != 0) {
2322 PUSHs(sv_2mortal(newSVpv(name, 0)));
2385 ST(count) = sv_2mortal(newSVpv(name, 0));
23232386 }
23242387 else {
2325 PUSHs(&PL_sv_undef);
2326 }
2327 }
2388 ST(count) = &PL_sv_undef;
2389 }
2390 ++count;
2391 }
2392 XSRETURN(count);
23282393
23292394 #endif
23302395
39924057
39934058 #endif
39944059
4060 MODULE = Imager PACKAGE = Imager::Context PREFIX=im_context_
4061
4062 void
4063 im_context_DESTROY(ctx)
4064 Imager::Context ctx
4065
4066 #ifdef PERL_IMPLICIT_CONTEXT
4067
4068 void
4069 im_context_CLONE(...)
4070 CODE:
4071 MY_CXT_CLONE;
4072 (void)items;
4073 /* the following sv_setref_pv() will free this inc */
4074 im_context_refinc(MY_CXT.ctx, "CLONE");
4075 MY_CXT.ctx = im_context_clone(MY_CXT.ctx, "CLONE");
4076 sv_setref_pv(get_sv("Imager::_context", GV_ADD), "Imager::Context", MY_CXT.ctx);
4077
4078 #endif
4079
39954080 BOOT:
39964081 PERL_SET_GLOBAL_CALLBACKS;
39974082 PERL_PL_SET_GLOBAL_CALLBACKS;
4083 #ifdef PERL_IMPLICIT_CONTEXT
4084 {
4085 MY_CXT_INIT;
4086 (void)MY_CXT;
4087 }
4088 #endif
4089 start_context(aTHX);
4090 im_get_context = perl_get_context;
4091 #ifdef HAVE_LIBTT
4092 i_tt_start();
4093 #endif
33 use vars qw($VERSION @ISA);
44
55 BEGIN {
6 $VERSION = "0.85";
6 $VERSION = "0.87";
77
88 require XSLoader;
99 XSLoader::load('Imager::File::JPEG', $VERSION);
1111 DEFINE_IMAGER_CALLBACKS;
1212
1313 MODULE = Imager::File::JPEG PACKAGE = Imager::File::JPEG
14
15 const char *
16 i_libjpeg_version()
1417
1518 undef_int
1619 i_writejpeg_wiol(im, ig, qfactor)
00 Imager::File::JPEG provides JPEG file format support for Imager.
11
2 It requires libjpeg to be installed.
2 It requires libjpeg to be installed, any version from jpeg6b or later.
3 libjpeg-turbo is also supported.
4
5 For Linux distributions this typically requires installation of the
6 associated -dev or -devel package.
7
8 See Imager::Install for more information.
39
410 This is currently shipped as part of Imager, but Imager may install
511 with out installing Imager::File::JPEG, so if you need JPEG support,
919919
920920 /* rough check count + 1 entry + next offset */
921921 if (offset + (2+12+4) > tiff->size) {
922 mm_log((2, "offset %uld beyond end off Exif block"));
922 mm_log((2, "offset %lu beyond end off Exif block", offset));
923923 return 0;
924924 }
925925
928928 /* check we can fit the whole thing */
929929 ifd_size = 2 + count * 12 + 4; /* count + count entries + next offset */
930930 if (offset + ifd_size > tiff->size) {
931 mm_log((2, "offset %uld beyond end off Exif block"));
931 mm_log((2, "offset %lu beyond end off Exif block", offset));
932932 return 0;
933933 }
934934
14191419 static unsigned
14201420 tiff_get16(imtiff *tiff, unsigned long offset) {
14211421 if (offset + 2 > tiff->size) {
1422 mm_log((3, "attempt to get16 at %uld in %uld image", offset, tiff->size));
1422 mm_log((3, "attempt to get16 at %lu in %lu image", offset,
1423 (unsigned long)tiff->size));
14231424 return 0;
14241425 }
14251426
14401441 static unsigned
14411442 tiff_get32(imtiff *tiff, unsigned long offset) {
14421443 if (offset + 4 > tiff->size) {
1443 mm_log((3, "attempt to get16 at %uld in %uld image", offset, tiff->size));
1444 mm_log((3, "attempt to get16 at %lu in %lu image", offset,
1445 (unsigned long)tiff->size));
14441446 return 0;
14451447 }
14461448
14911493 int result;
14921494
14931495 if (offset + 2 > tiff->size) {
1494 mm_log((3, "attempt to get16 at %uld in %uld image", offset, tiff->size));
1496 mm_log((3, "attempt to get16 at %lu in %lu image", offset,
1497 (unsigned long)tiff->size));
14951498 return 0;
14961499 }
14971500
15191522 unsigned work;
15201523
15211524 if (offset + 4 > tiff->size) {
1522 mm_log((3, "attempt to get16 at %uld in %uld image", offset, tiff->size));
1525 mm_log((3, "attempt to get16 at %lu in %lu image", offset,
1526 (unsigned long)tiff->size));
15231527 return 0;
15241528 }
15251529
15491553 tiff_get_rat(imtiff *tiff, unsigned long offset) {
15501554 unsigned long numer, denom;
15511555 if (offset + 8 > tiff->size) {
1552 mm_log((3, "attempt to get_rat at %lu in %lu image", offset, tiff->size));
1556 mm_log((3, "attempt to get_rat at %lu in %lu image", offset,
1557 (unsigned long)tiff->size));
15531558 return 0;
15541559 }
15551560
15751580 tiff_get_rats(imtiff *tiff, unsigned long offset) {
15761581 long numer, denom;
15771582 if (offset + 8 > tiff->size) {
1578 mm_log((3, "attempt to get_rat at %lu in %lu image", offset, tiff->size));
1583 mm_log((3, "attempt to get_rat at %lu in %lu image", offset,
1584 (unsigned long)tiff->size));
15791585 return 0;
15801586 }
15811587
4040 #define JPGS 16384
4141
4242 #define JPEG_DIM_MAX JPEG_MAX_DIMENSION
43
44 #define _STRINGIFY(x) #x
45 #define STRINGIFY(x) _STRINGIFY(x)
4346
4447 static unsigned char fake_eoi[]={(JOCTET) 0xFF,(JOCTET) JPEG_EOI};
4548
214217
215218 if (rc != JPGS) { /* XXX: Should raise some jpeg error */
216219 myfree(dest->buffer);
217 mm_log((1, "wiol_empty_output_buffer: Error: nbytes = %d != rc = %d\n", JPGS, rc));
220 mm_log((1, "wiol_empty_output_buffer: Error: nbytes = %d != rc = %d\n", JPGS, (int)rc));
218221 ERREXIT(cinfo, JERR_FILE_WRITE);
219222 }
220223 dest->pub.free_in_buffer = JPGS;
335338 }
336339
337340 typedef void (*transfer_function_t)(i_color *out, JSAMPARRAY in, int width);
341
342 static const char version_string[] =
343 #ifdef LIBJPEG_TURBO_VERSION
344 "libjpeg-turbo " STRINGIFY(LIBJPEG_TURBO_VERSION) " api " STRINGIFY(JPEG_LIB_VERSION)
345 #else
346 "libjpeg " STRINGIFY(JPEG_LIB_VERSION)
347 #endif
348 ;
349
350 /*
351 =item i_libjpeg_version()
352
353 =cut
354 */
355
356 const char *
357 i_libjpeg_version(void) {
358 return version_string;
359 }
338360
339361 /*
340362 =item i_readjpeg_wiol(data, length, iptc_itext, itlength)
524546
525547 i_tags_set(&im->tags, "i_format", "jpeg", 4);
526548
527 mm_log((1,"i_readjpeg_wiol -> (0x%x)\n",im));
549 mm_log((1,"i_readjpeg_wiol -> (%p)\n",im));
528550 return im;
529551 }
530552
88 undef_int
99 i_writejpeg_wiol(i_img *im, io_glue *ig, int qfactor);
1010
11 extern const char *
12 i_libjpeg_version(void);
13
1114 #endif
1111 or plan skip_all => "no jpeg support";
1212
1313 plan tests => 103;
14
15 print STDERR "libjpeg version: ", Imager::File::JPEG::i_libjpeg_version(), "\n";
1416
1517 my $green=i_color_new(0,255,0,255);
1618 my $blue=i_color_new(0,0,255,255);
55 color.c Color translation and handling
66 combine.im Channel combine
77 compose.im
8 context.c
89 conv.im
910 convert.im
1011 CountColor/CountColor.pm sample XS access to API
4748 Flines/Makefile.PL
4849 Flines/t/t00flines.t
4950 flip.im
50 font.c
5151 fontfiles/dodge.ttf
5252 fontfiles/ExistenceTest.ttf generated using pfaedit
5353 fontfiles/ImUgly.ttf
5454 fontfiles/NameTest.ttf test glyph_names() - see FT2/t/t10ft2.t
55 fontft1.c
5556 FT2/fontfiles/dodge.ttf
5657 FT2/fontfiles/ExistenceTest.afm
5758 FT2/fontfiles/ExistenceTest.pfb
6566 FT2/Makefile.PL
6667 FT2/README
6768 FT2/t/t10ft2.t
69 FT2/t/t20thread.t
70 FT2/t/t90std.t Standard font tests for FT2
6871 FT2/typemap
6972 gaussian.im
7073 GIF/GIF.pm
141144 imio.h
142145 immacros.h
143146 imperl.h
147 imperlio.h
144148 imrender.h Buffer rending engine function declarations
145149 inc/Devel/CheckLib.pm David Cantrell's Devel::CheckLib
146150 io.c
180184 lib/Imager/Font/BBox.pm
181185 lib/Imager/Font/FreeType2.pm
182186 lib/Imager/Font/Image.pm
187 lib/Imager/Font/Test.pm Font for testing (outputs boxes only)
183188 lib/Imager/Font/Truetype.pm
184189 lib/Imager/Font/Type1.pm Compatibility wrapper for Imager::Font::T1
185190 lib/Imager/Font/Wrap.pm
187192 lib/Imager/Handy.pod
188193 lib/Imager/ImageTypes.pod
189194 lib/Imager/Inline.pod Using Imager with Inline::C
195 lib/Imager/Install.pod Installation notes
190196 lib/Imager/interface.pod
191197 lib/Imager/IO.pod Document Imager::IO objects
192198 lib/Imager/LargeSamples.pod Track large sample support
197203 lib/Imager/Regops.pm
198204 lib/Imager/Security.pod
199205 lib/Imager/Test.pm
206 lib/Imager/Threads.pod
200207 lib/Imager/Transform.pm
201208 lib/Imager/Transformations.pod
202209 lib/Imager/Tutorial.pod
213220 MANIFEST.SKIP
214221 map.c
215222 maskimg.c
223 mutexnull.c
224 mutexpthr.c
225 mutexwin.c
216226 palimg.c
217227 paste.im
228 perlio.c
218229 plug.h
219230 PNG/impng.c
220231 PNG/impng.h
308319 t/t03test.t Test Imager::Test
309320 t/t05error.t
310321 t/t07iolayer.t
322 t/t080log.t
323 t/t081error.t
324 t/t082limit.t
311325 t/t1000files.t Format independent file tests
312326 t/t1000lib/Imager/File/BAD.pm Test failing to load a file handler
313327 t/t101nojpeg.t Test handling when jpeg not available
326340 t/t31font.t General font interface tests
327341 t/t35ttfont.t
328342 t/t36oofont.t
343 t/t37std.t Standard font tests for TT
329344 t/t40scale.t
330345 t/t50basicoo.t
331346 t/t55trans.t
347362 t/t81hlines.t Test hlines.c
348363 t/t82inline.t Test Inline::C integration
349364 t/t83extutil.t Test Imager::ExtUtils
365 t/t84inlinectx.t
350366 t/t90cc.t
351367 t/t91pod.t Test POD with Test::Pod
352368 t/t92samples.t
367383 T1/README
368384 T1/t/t10type1.t
369385 T1/t/t20oo.t
386 T1/t/t30thread.t
387 T1/t/t90std.t Standard font tests for T1
370388 T1/T1.pm
371389 T1/T1.xs
390 T1/typemap
372391 tags.c
373392 testimg/alpha16.tga 16-bit/pixel TGA with alpha "channel" RT 32926
374393 testimg/bad1oflow.bmp 1-bit/pixel, overflow integer on 32-bit machines
490509 W32/Makefile.PL
491510 W32/README
492511 W32/t/t10win32.t Tests Win32 GDI font support
512 W32/t/t90std.t Standard font tests for W32
493513 W32/W32.pm
494514 W32/W32.xs
495515 W32/win32.c Implements font support through Win32 GDI
133133
134134 # sub-module build junk
135135 \.bak$
136 MYMETA.json
00 --- #YAML:1.0
11 name: Imager
2 version: 0.93
2 version: 0.95
33 abstract: Perl extension for Generating 24 bit Images
44 author:
55 - Tony Cook <tonyc@cpan.org>, Arnar M. Hrafnkelsson
4747 my @libpaths; # places to look for libraries
4848 my $coverage; # build for coverage testing
4949 my $assert; # build with assertions
50 my $trace_context; # trace context management to stderr
5051 GetOptions("help" => \$help,
5152 "enable=s" => \@enable,
5253 "disable=s" => \@disable,
5556 "verbose|v" => \$VERBOSE,
5657 "nolog" => \$NOLOG,
5758 'coverage' => \$coverage,
58 "assert|a" => \$assert);
59 "assert|a" => \$assert,
60 "tracecontext" => \$trace_context);
5961
6062 setenv();
6163
158160 if ($^O eq 'hpux') { $OSLIBS .= ' -ldld'; }
159161 if (defined $Config{'d_dlsymun'}) { $OSDEF .= ' -DDLSYMUN'; }
160162
161 my @objs = qw(Imager.o draw.o polygon.o image.o io.o iolayer.o
162 log.o gaussian.o conv.o pnm.o raw.o feat.o font.o combine.o
163 my @objs = qw(Imager.o context.o draw.o polygon.o image.o io.o iolayer.o
164 log.o gaussian.o conv.o pnm.o raw.o feat.o combine.o
163165 filters.o dynaload.o stackmach.o datatypes.o
164166 regmach.o trans2.o quant.o error.o convert.o
165167 map.o tags.o palimg.o maskimg.o img8.o img16.o rotate.o
166168 bmp.o tga.o color.o fills.o imgdouble.o limits.o hlines.o
167 imext.o scale.o rubthru.o render.o paste.o compose.o flip.o);
169 imext.o scale.o rubthru.o render.o paste.o compose.o flip.o
170 perlio.o);
171
172 if ($Config{useithreads}) {
173 if ($Config{i_pthread}) {
174 print "POSIX threads\n";
175 push @objs, "mutexpthr.o";
176 }
177 elsif ($^O eq 'MSWin32') {
178 print "Win32 threads\n";
179 push @objs, "mutexwin.o";
180 }
181 else {
182 print "Unsupported threading model\n";
183 push @objs, "mutexnull.o";
184 if ($ENV{AUTOMATED_TESTING}) {
185 die "OS unsupported: no threading support code for this platform\n";
186 }
187 }
188 }
189 else {
190 print "No threads\n";
191 push @objs, "mutexnull.o";
192 }
168193
169194 my @typemaps = qw(typemap.local typemap);
170195 if ($] < 5.008) {
171196 unshift @typemaps, "typemap.oldperl";
197 }
198
199 if ($trace_context) {
200 $CFLAGS .= " -DIMAGER_TRACE_CONTEXT";
172201 }
173202
174203 my %opts=
520549 && !-e catfile($_[0], 'fterrors.h') },
521550 libcheck=>sub { $_[0] eq "libttf$aext" or $_[0] eq "libttf.$lext" },
522551 libfiles=>'-lttf',
523 objfiles=>'',
552 objfiles=>'fontft1.o',
524553 code => \&freetype1_probe,
525554 docs=>q{
526555 Truetype fonts are scalable fonts. They can include
33 use vars qw($VERSION @ISA);
44
55 BEGIN {
6 $VERSION = "0.86";
6 $VERSION = "0.87";
77
88 require XSLoader;
99 XSLoader::load('Imager::File::PNG', $VERSION);
00 Imager::File::PNG provides PNG file format support for Imager.
11
2 It requires libpng to be installed.
2 It requires libpng, including development files, to be installed.
33
4 This is currently shipped as part of Imager, but Imager may install
5 with out installing Imager::File::PNG, so if you need PNG support,
6 add a dependency on Imager::File::PNG.
4 For Linux distributions this typically requires installation of the
5 associated -dev or -devel package.
6
7 See Imager::Install for more information.
8
9 Imager::File::PNG is currently shipped as part of Imager, but Imager
10 may install without installing Imager::File::PNG, so if you need PNG
11 support, add a dependency on Imager::File::PNG.
315315 png_read_info(png_ptr, info_ptr);
316316 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL);
317317
318 mm_log((1,
319 "png_get_IHDR results: width %d, height %d, bit_depth %d, color_type %d, interlace_type %d\n",
320 width,height,bit_depth,color_type,interlace_type));
318 mm_log((1, "png_get_IHDR results: width %u, height %u, bit_depth %d, color_type %d, interlace_type %d\n",
319 (unsigned)width, (unsigned)height, bit_depth,color_type,interlace_type));
321320
322321 CC2C[PNG_COLOR_TYPE_GRAY]=1;
323322 CC2C[PNG_COLOR_TYPE_PALETTE]=3;
686685
687686 i_tags_set(&im->tags, "i_format", "png", -1);
688687 if (png_get_pHYs(png_ptr, info_ptr, &xres, &yres, &unit_type)) {
689 mm_log((1,"pHYs (%d, %d) %d\n", xres, yres, unit_type));
688 mm_log((1,"pHYs (%u, %u) %d\n", (unsigned)xres, (unsigned)yres, unit_type));
690689 if (unit_type == PNG_RESOLUTION_METER) {
691690 i_tags_set_float2(&im->tags, "i_xres", 0, xres * 0.0254, 5);
692691 i_tags_set_float2(&im->tags, "i_yres", 0, yres * 0.0254, 5);
+13
-390
README less more
00 ================================================================
11 Copyright (c) 1999-2004 Arnar M. Hrafnkelsson. All rights reserved.
2 Copyright (c) 2004-2012 Anthony Cook.
2 Copyright (c) 2004-2013 Anthony Cook.
33 This program is free software; you can redistribute it and/or
44 modify it under the same terms as Perl itself.
55
2929 2. Compiling and testing
3030 ========================
3131
32 Some care has been taken to make the installation as smooth as
33 possible. This is rather hard due to the difference between operating
34 systems and site setups. To get started just type
32 For details on the this process, including library and platform
33 specific details, see Imager::Install, either by using:
3534
36 $ perl Makefile.PL
35 perldoc lib/Imager/Install.pod
3736
38 It should blurb out a list of which libraries were found and which
39 not. If you add a library to the machine after installing Imager it
40 does not automatically become available in Imager. It only uses the
41 libraries that are found. If the list of found libraries is not what
42 you expected, then the Makefile.PL is either not searching in the
43 right directories or your box does not have the libraries you think it
44 does. For a list of where to get the libraries have a look at
45 3. External dependencies. To widen the search path for libraries and
46 include files set the IM_INCPATH and IM_LIBPATH variables. The
47 environment variables that matter when Makefile.PL is run are
37 or at:
4838
49 IM_INCPATH colon separated list of paths to extra include files
50 IM_LIBPATH colon separated list of paths to extra library files
39 http://imager.perl.org/docs/Imager/Install.html
5140
52 IM_VERBOSE turns on verbose mode for the library scanning and such
53 IM_MANUAL to manually select which libraries are used and which not
54 IM_NOLOG if true logging will not be compiled into the module
55 IM_DEBUG_MALLOC if true malloc debugging will be compiled into the module
56 do not use IM_DEBUG_MALLOC in production - this slows
57 everything down
41 The basic installation process is similar to most other CPAN modules:
5842
59 IM_CFLAGS Extra flags to pass to the compiler
60 IM_LFLAGS Extra flags to pass to the linker
61 IM_DFLAGS Extra flags to pass to the preprocessor
43 perl Makefile.PL
44 make
45 make test
46 make install
6247
63
64
65 When finding the libraries has been sorted out it's time for
66
67 $ make
68
69 and if that works then do
70
71 $ make test
72
73 If either fails do take a peek at the file errep.perl. It's creates a
74 file report.txt. This is some information which will help me discover
75 where the problem is so I can try to fix it in future releases. If
76 you find running it ok (just remember - no warranty!) please send the
77 report.txt via email to tonyc@cpan.org.
78
79 Troubleshooting tips:
80
81 A common problem is that libgif/libungif are sometimes linked to the X
82 libraries and then running the tests fails. In that case something
83 like:
84
85 $ IM_LFLAGS="-L/usr/X11R6/lib -lX11" perl Makefile.PL
86
87 Which simply sets the environment variables for the extra libraries
88 to include the X libraries (which we do not use at all, but must
89 included since libgif has been linked with it).
90
91 Otherwise you could just build giflib without any X11 dependencies:
92
93 # must be a clean tree
94 cd giflib-4.1.4
95 ./configure --without-x ...
96
97 Also note that libgif has a few bugs: You can run something like
98
99 $ perl -Iblib/lib -Iblib/arch t/t105gif.t
100
101 This way you can see what comments the test script prints out.
102 t/t105gif.t checks for an bug in libgif and prints out a patch
103 if that bug is present, note that this bug only affects the more
104 "advanced" features of libgif.
105
106 If for some reason you have libungif-devel package installed but
107 not libungif on RedHat then you will probably get lots of errors
108 like undefined symbol: FreeSavedImages when running make test.
109 Install libungif package to fix it.
110
111 Stock libungif 4.1.4 or later seems to fix all of the bugs, if you
112 have a problem that version of linungif (or later), let us know and
113 we'll look into it.
114
115 Imager needs to have a libtiff version of at least 3.5.5, but you
116 should use a later version since some noticable bugs have been fixed.
117
118 For now you can either configure Imager manually (by setting the
119 IM_MANUAL environment variable to 1, in sh:
120
121 $ IM_MANUAL=1 perl Makefile.PL
122
123 and simply say no to tiff support when asked if you want it, the same thing
124 can be used to circumvent problems in gifs to get Imager going.
125
126 If it worked just continue with the installation as normally
127 (with make install).
128
129 Freetype 1.x vs Freetype 2.x
130 ----------------------------
131
132 These two libraries have some conflicting include file names, but as
133 long as you don't put the Freetype 2.x freetype.h directory in the
134 include path it should all work.
135
136 Put the directory containing ft2build.h in the include path, but not
137 the directory containing the freetype 2.x freetype.h.
138
139 If you see compilation errors from font.c you've probably made the
140 mistake of putting the Freetype 2.x freetype.h directory into the
141 include path.
142
143 To see which directories should be in the include path, try:
144
145 freetype-config --cflags
146
147 Ideally, freetype-config should be in the PATH when building Imager
148 with freetype 2.x support.
149
150
151 Macintosh dfont and suitcase font support
152 -----------------------------------------
153
154 Through Freetype 2.1, Imager can use Macintosh DFON (.dfont) fonts and
155 suitcase font files.
156
157 If you want to be able to use more than just the first face in the
158 font file though, you will need to configure freetype2 with the
159 --with-old-mac-fonts option:
160
161 ./configure --with-old-mac-fonts
162
163 You can use the index option to get to the other font faces in the
164 file:
165
166 # get the second face from $file
167 my $font = Imager::Font->new(file=>$file, index=>1)
168 or die Imager->errstr;
169
170 If you're using a suitcase font, you will also need to force the use
171 of freetype 2 with the type argument:
172
173 my $font = Imager::Font->new(file=>$suitcase, type=>'ft2', index=>$index)
174 or die Imager->errstr;
175
176
177 ========================
178 3. External dependencies
179 ========================
180
181 Some hints about getting the Imager module to find the libraries it
182 needs for specific features.
183
184 Most Linux distributions pre-package these. For each library I've
185 listed the Debian and Redhat package names.
186
187 For Debian or Debian based system, such as Ubuntu, you would run:
188
189 aptitude install package-name
190
191 or:
192
193 apt-get install package-name
194
195 at a root shell (or via sudo).
196
197 eg.
198
199 apt-get install libjpeg62-dev
200
201 For a Redhat based system such as CentOS or Fedora you would run:
202
203 yum install package-name
204
205 at a root shell.
206
207 eg.
208
209 yum install libjpeg-devel
210
211 I strongly recommend using your distribution's packages if possible,
212 this will mean any security updates to those packages will be applied
213 when you install security updates.
214
215 3.1 libjpeg
216 -----------
217
218 http://www.ijg.org/files/
219 ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz
220
221 Provides read and write access to JPEG images.
222
223 Make sure you run:
224
225 make install-lib
226
227 to install the development headers and libraries before attempting to
228 build Imager.
229
230 Debian: libjpeg62-dev
231 Redhat: libjpeg-devel
232
233 3.2 libpng
234 ----------
235
236 http://www.libpng.org/pub/png/libpng.html
237
238 Provides read and write access to PNG images.
239
240 You also need zlib to use png: http://www.gzip.org/zlib/ We have
241 encountered problems with libpng 1.0.1, which were fixed in 1.0.5
242 Note: you should probably be using zlib 1.1.4, since 1.1.3 has a
243 potential security problem.
244
245 Debian: libpng12-dev
246 Redhat: libpng-devel
247
248 3.3 giflib
249 ----------
250
251 http://sourceforge.net/projects/giflib/
252
253 Provides read and write access to GIF images.
254
255 giflib/libungif has come a long way since the buggy versions available
256 when Imager's gif support code was written. Preferably you should get
257 at least version 4.1.4. If you have a recent Linux distribution you
258 should be safe with whatever giflib it provides, but if you're
259 building from source, please try to use the latest version.
260
261 With the expiration of the LZW patent there's no reason to use
262 libungif.
263
264 libgif 4.1.4 has no problems known to me at this point.
265
266 Debian: libgif-dev
267 Redhat: giflib-devel
268
269 3.4 libtiff
270 -----------
271
272 http://www.remotesensing.org/libtiff/
273
274 Provides read and write access to TIFF images.
275
276 Note: libtiff 3.9.0 shouldn't be used due to a bug in
277 TIFFWriteDirectory().
278
279 Debian: libtiff4-dev
280 Redhat: libtiff-devel
281
282 3.5 T1Lib
283 ---------
284
285 http://www.t1lib.org/
286 ftp://sunsite.unc.edu/pub/Linux/libs/graphics/
287
288 Support for text drawing with Type 1 Postscript fonts.
289
290 Debian: libt1-dev
291 Redhat: t1lib-devel
292
293 3.6 Freetype 2.x (libfreetype)
294 ------------------------------
295
296 http://www.freetype.org/
297
298 Support for text drawing with a large number of font formats,
299 including Truetype, Type 1, Opentype and some bitmap formats.
300
301 Debian: libfreetype6-dev
302 Redhat: freetype-devel
303
304 3.7 Freetype 1.x (libttf)
305 -------------------------
306
307 http://www.freetype.org/
308
309 Support for text drawing with Truetype fonts.
310
311 This library has been superceded by Freetype 2, and some Linux
312 distributions are phasing it out.
313
314 Debian: libttf-dev
315 Redhat: freetype1-devel
316
317 3.8 Binaries
318 ------------
319
320 Precompiled versions of some of the libraries might be found at:
321
322 AIX:
323
324 http://www.bullfreeware.com/
325
326 Solaris:
327
328 http://www.sunfreeware.com/
329
330 ========================
331 4. Logging and debugging
332 ========================
333
334 Logging is compiled in by default - if you should want to get of it
335 from the binaries you can do so by setting the env IMAGER_NOLOG
336 to something. If you want to enable malloc debugging to check for leaks
337 then set IMAGER_DEBUG_MALLOC to something. Needless to say it is
338 pretty pointless to have malloc debug enabled with no logging since you
339 can never see the malloc information that way.
340
341
342 =================
343 5. Win32 Support
344 =================
345
346 Imager can be installed on Win32 systems. This was ported and tested
347 with Microsoft Visual C++ 6.0 with build 623 of ActivePerl. You can
348 use all of the features of Imager. You can also use Win32 GDI fonts
349 directly by supplying the 'face' parameter to Imager::Font->new(...).
350
351 I've tested with MSVC++ 6.0, cygwin (perl 5.6.1) and gcc (MinGW).
352
353 If you see an error under cygwin during testing along the lines of:
354
355 C:\cygwin\bin\perl.exe: *** unable to remap C:\cygwin\...some dll to the
356 same address as parent (0x...) != 0x....
357
358 you will need to install the cygwin rebase package and run:
359
360 $ rebaseall -v
361
362 If you get errors from your make tool, make sure you're using the same
363 make that was used to build your perl - generally GNU make for cygwin,
364 nmake for Visual C/C++ and dmake for MinGW.
365
366 Imager and all of the libraries it requires are supplied with
367 Strawberry Perl.
368
369 ============
370 6. Mac OS X
371 ============
372
373 Building Imager under OS X is generally straightforward. There are
374 some exceptions though:
375
376 a) you may find to need to ranlib library files in place after you've
377 installed them, for example:
378
379 ranlib /usr/local/lib/libgif.a
380
381 b) the version of GCC enabled by default on OS X 10.4 generates
382 incorrect code for some functions. To work around this run:
383
384 gcc_select 3
385
386 before building Imager and:
387
388 gcc_select 4
389
390 after building Imager.
391
392 This problem exhibits itself as test failures in t/t20fill.t
393
394 Imager 0.56 includes a workaround for this problem, but I wasn't
395 able to test it.
396
397 c) if you want to build GCC 4.0 from scratch and use that you will
398 need to adjust the command-line supplied during the link stage, so
399 that there is some other option before the -bundle option.
400
401 For example:
402
403 perl Makefile.PL LDDLFLAGS="`perl -MConfig -e 'print "-g $Config{lddlflags}"'`"
404
405 d) The default perl build in Snow Leopard and Lion is a fat binary,
406 and default builds of giflib, libpng and libjpeg (and maybe other
407 libraries) will produce link failures.
408
409 To avoid this you need to supply a CFLAGS parameter to the
410 library's configure script, but since the -arch flag conflicts with
411 the options used to build the dependency files, you need to supply
412 another flag to disable dependency tracking.
413
414 Snow Leopard fat binaries include i386, x86_64 and PPC objects,
415 hence you would run configure like:
416
417 ./configure --disable-dependency-tracking CFLAGS='-arch x86_64 -arch i386 -arch ppc'
418
419 Lion doesn't support PPC, so there you run configure like:
420
421 ./configure --disable-dependency-tracking CFLAGS='-arch x86_64 -arch i386'
422
423 For libgif you might also want to supply the --without-x option.
424
42548 =======================
426 7. General information
49 3. General information
42750 =======================
42851
42952 The Imager module homepage is currently at:
43558 https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Imager
43659
43760 ========================
438 8. Thanks
61 4. Thanks
43962 ========================
44063
44164 Thanks go to:
460460
461461 mm_log((3, "Offset/length table:\n"));
462462 for(i=0; i < height * channels; i++)
463 mm_log((3, "%d: %d/%d\n", i, start_tab[i], length_tab[i]));
463 mm_log((3, "%d: %lu/%lu\n", i, start_tab[i], length_tab[i]));
464464
465465 *pstart_tab = start_tab;
466466 *plength_tab = length_tab;
499499 return NULL;
500500 }
501501
502 mm_log((1, "maxlen for an rle buffer: %d\n", max_length));
502 mm_log((1, "maxlen for an rle buffer: %lu\n", max_length));
503503
504504 if (max_length > (img->xsize + 1) * 2) {
505505 i_push_errorf(0, "SGI image: ridiculous RLE line length %lu", max_length);
575575 /* RLE run */
576576 if (count > pixels_left) {
577577 i_push_error(0, "SGI image: RLE run overflows scanline");
578 mm_log((2, "RLE run overflows scanline (y %d chan %d offset %ld len %ld)\n", y, c, start_tab[ci], length_tab[ci]));
578 mm_log((2, "RLE run overflows scanline (y %" i_DF " chan %d offset %lu len %lu)\n", i_DFc(y), c, start_tab[ci], length_tab[ci]));
579579 goto ErrorReturn;
580580 }
581581 if (data_left < 1) {
3737 $opts{TYPEMAPS} = [ Imager::ExtUtils->typemap ];
3838
3939 # Imager required configure through use
40 my @Imager_req = ( Imager => "0.86" );
40 my @Imager_req = ( Imager => "0.95" );
4141 if ($MM_ver >= 6.46) {
4242 $opts{META_MERGE} =
4343 {
0 This module provides Type 1 font support for Imager via T1Lib.
0 Imager::Font::T1 provides Type 1 font support for Imager via T1Lib.
11
22 http://imager.perl.org/
33 http://www.t1lib.org/
4
5 This requires that t1lib is installed, including any development files.
6
7 For Linux distributions this typically requires installation of the
8 associated -dev or -devel package.
9
10 See Imager::Install for more information.
11
12 Imager::Font::T1 is shipped as part of Imager, but if the libraries
13 required aren't found it won't be installed. If you require T1
14 support via libt1 then add a dependency on Imager::Font::T1.
15
16 Imager::Font::FT2 provides most of the functionality of
17 Imager::Font::T1 and more.
22 use Imager::Color;
33 use vars qw(@ISA $VERSION);
44 @ISA = qw(Imager::Font);
5 use Scalar::Util ();
56
67 BEGIN {
7 $VERSION = "1.018";
8 $VERSION = "1.022";
89
910 require XSLoader;
1011 XSLoader::load('Imager::Font::T1', $VERSION);
1314
1415 *_first = \&Imager::Font::_first;
1516
16 my $t1aa;
17
18 # $T1AA is in there because for some reason (probably cache related) antialiasing
19 # is a system wide setting in t1 lib.
20
21 sub t1_set_aa_level {
22 if (!defined $t1aa or $_[0] != $t1aa) {
23 i_t1_set_aa($_[0]);
24 $t1aa=$_[0];
25 }
26 }
17 my $t1aa = 2;
2718
2819 sub new {
2920 my $class = shift;
6455 $hsh{afm} = 0;
6556 }
6657
67 my $id = i_t1_new($hsh{file},$hsh{afm});
68 unless ($id >= 0) { # the low-level code may miss some error handling
58 my $font = Imager::Font::T1xs->new($hsh{file},$hsh{afm});
59 unless ($font) { # the low-level code may miss some error handling
6960 Imager->_set_error(Imager->_error_as_msg);
7061 return;
7162 }
7263 return bless {
73 id => $id,
64 t1font => $font,
7465 aa => $hsh{aa} || 0,
7566 file => $hsh{file},
7667 type => 't1',
7768 size => $hsh{size},
7869 color => $hsh{color},
70 t1aa => $t1aa,
7971 }, $class;
8072 }
8173
8274 sub _draw {
8375 my $self = shift;
84 my %input = @_;
85 t1_set_aa_level($input{aa});
86 my $flags = '';
87 $flags .= 'u' if $input{underline};
88 $flags .= 's' if $input{strikethrough};
89 $flags .= 'o' if $input{overline};
90 if (exists $input{channel}) {
91 i_t1_cp($input{image}{IMG}, $input{'x'}, $input{'y'},
92 $input{channel}, $self->{id}, $input{size},
93 $input{string}, length($input{string}), $input{align},
94 $input{utf8}, $flags);
95 } else {
96 i_t1_text($input{image}{IMG}, $input{'x'}, $input{'y'},
97 $input{color}, $self->{id}, $input{size},
98 $input{string}, length($input{string}),
99 $input{align}, $input{utf8}, $flags);
100 }
101
102 return $self;
103 }
104
105 sub _bounding_box {
106 my $self = shift;
76
77 $self->_valid
78 or return;
79
10780 my %input = @_;
10881 my $flags = '';
10982 $flags .= 'u' if $input{underline};
11083 $flags .= 's' if $input{strikethrough};
11184 $flags .= 'o' if $input{overline};
112 return i_t1_bbox($self->{id}, $input{size}, $input{string},
113 length($input{string}), $input{utf8}, $flags);
85 my $aa = $input{aa} ? $self->{t1aa} : 0;
86 if (exists $input{channel}) {
87 $self->{t1font}->cp($input{image}{IMG}, $input{'x'}, $input{'y'},
88 $input{channel}, $input{size},
89 $input{string}, $input{align},
90 $input{utf8}, $flags, $aa)
91 or return;
92 } else {
93 $self->{t1font}->text($input{image}{IMG}, $input{'x'}, $input{'y'},
94 $input{color}, $input{size},
95 $input{string}, $input{align}, $input{utf8}, $flags, $aa)
96 or return;
97 }
98
99 return $self;
100 }
101
102 sub _bounding_box {
103 my $self = shift;
104
105 $self->_valid
106 or return;
107
108 my %input = @_;
109 my $flags = '';
110 $flags .= 'u' if $input{underline};
111 $flags .= 's' if $input{strikethrough};
112 $flags .= 'o' if $input{overline};
113 my @bbox = $self->{t1font}->bbox($input{size}, $input{string},
114 $input{utf8}, $flags);
115 unless (@bbox) {
116 Imager->_set_error(Imager->_error_as_msg);
117 return;
118 }
119
120 return @bbox;
114121 }
115122
116123 # check if the font has the characters in the given string
117124 sub has_chars {
118125 my ($self, %hsh) = @_;
119126
120 unless (defined $hsh{string} && length $hsh{string}) {
127 $self->_valid
128 or return;
129
130 unless (defined $hsh{string}) {
121131 $Imager::ERRSTR = "No string supplied to \$font->has_chars()";
122132 return;
123133 }
124 return i_t1_has_chars($self->{id}, $hsh{string},
125 _first($hsh{'utf8'}, $self->{utf8}, 0));
134 if (wantarray) {
135 my @result = $self->{t1font}
136 ->has_chars($hsh{string}, _first($hsh{'utf8'}, $self->{utf8}, 0));
137 unless (@result) {
138 Imager->_set_error(Imager->_error_as_msg);
139 return;
140 }
141
142 return @result;
143 }
144 else {
145 my $result = $self->{t1font}
146 ->has_chars($hsh{string}, _first($hsh{'utf8'}, $self->{utf8}, 0));
147 unless (defined $result) {
148 Imager->_set_error(Imager->_error_as_msg);
149 return;
150 }
151 return $result;
152 }
126153 }
127154
128155 sub utf8 {
129156 1;
130157 }
131158
159 sub can_glyph_names {
160 1;
161 }
162
132163 sub face_name {
133164 my ($self) = @_;
134165
135 i_t1_face_name($self->{id});
166 $self->_valid
167 or return;
168
169 return $self->{t1font}->face_name();
136170 }
137171
138172 sub glyph_names {
139173 my ($self, %input) = @_;
174
175 $self->_valid
176 or return;
140177
141178 my $string = $input{string};
142179 defined $string
143180 or return Imager->_set_error("no string parameter passed to glyph_names");
144181 my $utf8 = _first($input{utf8} || 0);
145182
146 i_t1_glyph_name($self->{id}, $string, $utf8);
147 }
148
183 my @result = $self->{t1font}->glyph_names($string, $utf8);
184 unless (@result) {
185 Imager->_set_error(Imager->_error_as_msg);
186 return;
187 }
188
189 return @result;
190 }
191
192 sub set_aa_level {
193 my ($self, $new_t1aa) = @_;
194
195 if (!defined $new_t1aa ||
196 ($new_t1aa != 1 && $new_t1aa != 2)) {
197 Imager->_set_error("set_aa_level: parameter must be 1 or 2");
198 return;
199 }
200
201 if (ref $self) {
202 $self->_valid
203 or return;
204
205 $self->{t1aa} = $new_t1aa;
206 }
207 else {
208 $t1aa = $new_t1aa;
209 }
210
211 return 1;
212 }
213
214 sub _valid {
215 my $self = shift;
216
217 unless ($self->{t1font} && Scalar::Util::blessed($self->{t1font})) {
218 Imager->_set_error("font object was created in another thread");
219 return;
220 }
221
222 return 1;
223 }
149224
150225 1;
151226
196271 Obviously, if you're calculating the bounding box the size of the line
197272 is included in the box, and the line isn't drawn :)
198273
274 =head2 Anti-aliasing
275
276 T1Lib supports multiple levels of anti-aliasing, by default, if you
277 request anti-aliased output, Imager::Font::T1 will use the maximum
278 level.
279
280 You can override this with the set_t1_aa() method:
281
282 =over
283
284 =item set_aa_level()
285
286 Usage:
287
288 $font->set_aa_level(1);
289 Imager::Font::T1->set_aa_level(2);
290
291 Sets the T1Lib anti-aliasing level either for the specified font, or
292 for new font objects.
293
294 The only parameter must be 1 or 2.
295
296 Returns true on success.
297
298 =back
299
199300 =head1 AUTHOR
200301
201302 Addi, Tony
1010
1111 DEFINE_IMAGER_CALLBACKS;
1212
13 typedef i_t1_font_t Imager__Font__T1xs;
14
15 #define i_t1_DESTROY(font) i_t1_destroy(font)
16
1317 MODULE = Imager::Font::T1 PACKAGE = Imager::Font::T1
1418
1519 undef_int
1620 i_init_t1(t1log)
1721 int t1log
1822
19 void
20 i_t1_set_aa(st)
21 int st
22
23 int
24 i_t1_new(pfb,afm)
23 MODULE = Imager::Font::T1 PACKAGE = Imager::Font::T1xs PREFIX = i_t1_
24
25 Imager::Font::T1xs
26 i_t1_new(class,pfb,afm)
2527 char* pfb
2628 char* afm
27
28 int
29 i_t1_destroy(font_id)
30 int font_id
29 C_ARGS:
30 pfb, afm
31
32 void
33 i_t1_DESTROY(font)
34 Imager::Font::T1xs font
3135
3236
3337 undef_int
34 i_t1_cp(im,xb,yb,channel,fontnum,points,str_sv,len_ignored,align,utf8=0,flags="")
38 i_t1_cp(font,im,xb,yb,channel,points,str_sv,align,utf8=0,flags="",aa=1)
39 Imager::Font::T1xs font
3540 Imager::ImgRaw im
3641 i_img_dim xb
3742 i_img_dim yb
3843 int channel
39 int fontnum
4044 double points
4145 SV* str_sv
4246 int align
4347 int utf8
4448 char* flags
49 int aa
4550 PREINIT:
4651 char *str;
4752 STRLEN len;
4853 CODE:
54 str = SvPV(str_sv, len);
4955 #ifdef SvUTF8
5056 if (SvUTF8(str_sv))
5157 utf8 = 1;
5258 #endif
53 str = SvPV(str_sv, len);
54 RETVAL = i_t1_cp(im, xb,yb,channel,fontnum,points,str,len,align,
55 utf8,flags);
59 RETVAL = i_t1_cp(font, im, xb,yb,channel,points,str,len,align,
60 utf8,flags,aa);
5661 OUTPUT:
5762 RETVAL
5863
5964
6065 void
61 i_t1_bbox(fontnum,point,str_sv,len_ignored,utf8=0,flags="")
62 int fontnum
66 i_t1_bbox(fontnum,point,str_sv,utf8=0,flags="")
67 Imager::Font::T1xs fontnum
6368 double point
6469 SV* str_sv
6570 int utf8
6671 char* flags
6772 PREINIT:
68 char *str;
73 const char *str;
6974 STRLEN len;
7075 i_img_dim cords[BOUNDING_BOX_COUNT];
7176 int i;
7277 int rc;
7378 PPCODE:
79 str = SvPV(str_sv, len);
7480 #ifdef SvUTF8
7581 if (SvUTF8(str_sv))
7682 utf8 = 1;
7783 #endif
78 str = SvPV(str_sv, len);
7984 rc = i_t1_bbox(fontnum,point,str,len,cords,utf8,flags);
8085 if (rc > 0) {
8186 EXTEND(SP, rc);
8691
8792
8893 undef_int
89 i_t1_text(im,xb,yb,cl,fontnum,points,str_sv,len_ignored,align,utf8=0,flags="")
94 i_t1_text(font,im,xb,yb,cl,points,str_sv,align,utf8=0,flags="",aa=1)
95 Imager::Font::T1xs font
9096 Imager::ImgRaw im
9197 i_img_dim xb
9298 i_img_dim yb
9399 Imager::Color cl
94 int fontnum
95100 double points
96101 SV* str_sv
97102 int align
98103 int utf8
99 char* flags
104 const char* flags
105 int aa
100106 PREINIT:
101107 char *str;
102108 STRLEN len;
103109 CODE:
110 str = SvPV(str_sv, len);
104111 #ifdef SvUTF8
105112 if (SvUTF8(str_sv))
106113 utf8 = 1;
107114 #endif
108 str = SvPV(str_sv, len);
109 RETVAL = i_t1_text(im, xb,yb,cl,fontnum,points,str,len,align,
110 utf8,flags);
115 RETVAL = i_t1_text(font,im, xb,yb,cl,points,str,len,align,
116 utf8,flags,aa);
111117 OUTPUT:
112118 RETVAL
113119
114120 void
115 i_t1_has_chars(handle, text_sv, utf8 = 0)
116 int handle
121 i_t1_has_chars(font, text_sv, utf8 = 0)
122 Imager::Font::T1xs font
117123 SV *text_sv
118124 int utf8
119125 PREINIT:
123129 int count;
124130 int i;
125131 PPCODE:
132 text = SvPV(text_sv, len);
126133 #ifdef SvUTF8
127134 if (SvUTF8(text_sv))
128135 utf8 = 1;
129136 #endif
130 text = SvPV(text_sv, len);
131137 work = mymalloc(len);
132 count = i_t1_has_chars(handle, text, len, utf8, work);
138 count = i_t1_has_chars(font, text, len, utf8, work);
133139 if (GIMME_V == G_ARRAY) {
134140 EXTEND(SP, count);
141
135142 for (i = 0; i < count; ++i) {
136143 PUSHs(boolSV(work[i]));
137144 }
143150 myfree(work);
144151
145152 void
146 i_t1_face_name(handle)
147 int handle
153 i_t1_face_name(font)
154 Imager::Font::T1xs font
148155 PREINIT:
149156 char name[255];
150157 int len;
151158 PPCODE:
152 len = i_t1_face_name(handle, name, sizeof(name));
159 len = i_t1_face_name(font, name, sizeof(name));
153160 if (len) {
154161 EXTEND(SP, 1);
155162 PUSHs(sv_2mortal(newSVpv(name, strlen(name))));
156163 }
157164
158165 void
159 i_t1_glyph_name(handle, text_sv, utf8 = 0)
160 int handle
166 i_t1_glyph_names(font, text_sv, utf8 = 0)
167 Imager::Font::T1xs font
161168 SV *text_sv
162169 int utf8
163170 PREINIT:
165172 STRLEN work_len;
166173 size_t len;
167174 char name[255];
175 SSize_t count = 0;
168176 PPCODE:
177 text = SvPV(text_sv, work_len);
169178 #ifdef SvUTF8
170179 if (SvUTF8(text_sv))
171180 utf8 = 1;
172181 #endif
173 text = SvPV(text_sv, work_len);
182 i_clear_error();
174183 len = work_len;
175184 while (len) {
176185 unsigned long ch;
178187 ch = i_utf8_advance(&text, &len);
179188 if (ch == ~0UL) {
180189 i_push_error(0, "invalid UTF8 character");
181 break;
190 XSRETURN(0);
182191 }
183192 }
184193 else {
185194 ch = *text++;
186195 --len;
187196 }
188 EXTEND(SP, 1);
189 if (i_t1_glyph_name(handle, ch, name, sizeof(name))) {
190 PUSHs(sv_2mortal(newSVpv(name, 0)));
197 EXTEND(SP, count+1);
198 if (i_t1_glyph_name(font, ch, name, sizeof(name))) {
199 ST(count) = sv_2mortal(newSVpv(name, 0));
191200 }
192201 else {
193 PUSHs(&PL_sv_undef);
194 }
195 }
202 ST(count) = &PL_sv_undef;
203 }
204 ++count;
205 }
206 XSRETURN(count);
207
208 int
209 i_t1_CLONE_SKIP(...)
210 CODE:
211 (void)items; /* avoid unused warning */
212 RETVAL = 1;
213 OUTPUT:
214 RETVAL
196215
197216 BOOT:
198217 PERL_INITIALIZE_IMAGER_CALLBACKS;
218 i_t1_start();
44
55 static int t1_get_flags(char const *flags);
66 static char *t1_from_utf8(char const *in, size_t len, int *outlen);
7
7 static undef_int i_init_t1_low(int t1log);
88 static void t1_push_error(void);
9 static void i_t1_set_aa(int st);
910
1011 static int t1_active_fonts = 0;
1112 static int t1_initialized = 0;
13 static int t1_aa = 0;
14
15 struct i_t1_font_tag {
16 int font_id;
17 };
18
19 static i_mutex_t mutex;
20
21 /*
22 =item i_t1_start()
23
24 Initialize the font driver. This does not actually initialize T1Lib,
25 it just allocates the mutex we use to gate access to it.
26
27 =cut
28 */
29
30 void
31 i_t1_start(void) {
32 mutex = i_mutex_new();
33 }
1234
1335 /*
1436 =item i_init_t1(t1log)
2042
2143 undef_int
2244 i_init_t1(int t1log) {
45 undef_int result;
46 i_mutex_lock(mutex);
47
48 result = i_init_t1_low(t1log);
49
50 i_mutex_unlock(mutex);
51
52 return result;
53 }
54
55 static undef_int
56 i_init_t1_low(int t1log) {
2357 int init_flags = IGNORE_CONFIGFILE|IGNORE_FONTDATABASE;
24 mm_log((1,"init_t1()\n"));
58
59 mm_log((1,"init_t1(%d)\n", t1log));
2560
2661 i_clear_error();
2762
4479 return(1);
4580 }
4681 T1_SetLogLevel(T1LOG_DEBUG);
47 i_t1_set_aa(1); /* Default Antialias value */
4882
4983 ++t1_initialized;
5084
6397
6498 void
6599 i_close_t1(void) {
100 i_mutex_lock(mutex);
66101 T1_CloseLib();
67102 t1_initialized = 0;
103 i_mutex_unlock(mutex);
68104 }
69105
70106
79115 =cut
80116 */
81117
82 int
118 i_t1_font_t
83119 i_t1_new(char *pfb,char *afm) {
84120 int font_id;
121 i_t1_font_t font;
122
123 i_mutex_lock(mutex);
85124
86125 i_clear_error();
87126
88 if (!t1_initialized && i_init_t1(0))
89 return -1;
127 if (!t1_initialized && i_init_t1_low(0)) {
128 i_mutex_unlock(mutex);
129 return NULL;
130 }
90131
91132 mm_log((1,"i_t1_new(pfb %s,afm %s)\n",pfb,(afm?afm:"NULL")));
92133 font_id = T1_AddFont(pfb);
93134 if (font_id<0) {
94135 mm_log((1,"i_t1_new: Failed to load pfb file '%s' - return code %d.\n",pfb,font_id));
95136 t1_push_error();
96 return font_id;
137 i_mutex_unlock(mutex);
138 return NULL;
97139 }
98140
99141 if (afm != NULL) {
106148 t1_push_error();
107149 i_push_error(0, "loading font");
108150 T1_DeleteFont(font_id);
109 return -1;
151 i_mutex_unlock(mutex);
152 return NULL;
110153 }
111154
112155 ++t1_active_fonts;
113156
114 mm_log((1, "i_t1_new() -> %d\n", font_id));
115
116 return font_id;
117 }
118
119 /*
120 =item i_t1_destroy(font_id)
157 i_mutex_unlock(mutex);
158
159 font = mymalloc(sizeof(*font));
160 font->font_id = font_id;
161
162 mm_log((1, "i_t1_new() -> %p (%d)\n", font, font_id));
163
164 return font;
165 }
166
167 /*
168 =item i_t1_destroy(font)
121169
122170 Frees resources for a t1 font with given font id.
123171
124 font_id - number of the font to free
172 font - font to free
125173
126174 =cut
127175 */
128176
129177 int
130 i_t1_destroy(int font_id) {
131 mm_log((1,"i_t1_destroy(font_id %d)\n",font_id));
178 i_t1_destroy(i_t1_font_t font) {
179 int result;
180
181 i_mutex_lock(mutex);
182
183 mm_log((1,"i_t1_destroy(font %p (%d))\n", font, font->font_id));
132184
133185 --t1_active_fonts;
134186
135 return T1_DeleteFont(font_id);
187 result = T1_DeleteFont(font->font_id);
188 myfree(font);
189
190 i_mutex_unlock(mutex);
191
192 return result;
136193 }
137194
138195
143200
144201 st - 0 = NONE, 1 = LOW, 2 = HIGH.
145202
146 =cut
147 */
148
149 void
203 Must be called with the mutex locked.
204
205 =cut
206 */
207
208 static void
150209 i_t1_set_aa(int st) {
151210 int i;
152211 unsigned long cst[17];
212
213 if (t1_aa == st)
214 return;
215
153216 switch(st) {
154217 case 0:
155218 T1_AASetBitsPerPixel( 8 );
170233 T1_AAHSetGrayValues( cst );
171234 mm_log((1,"setting T1 antialias to high\n"));
172235 }
236
237 t1_aa = st;
173238 }
174239
175240
176241 /*
177 =item i_t1_cp(im, xb, yb, channel, fontnum, points, str, len, align)
242 =item i_t1_cp(im, xb, yb, channel, fontnum, points, str, len, align,aa)
178243
179244 Interface to text rendering into a single channel in an image
180245
187252 str - string to render
188253 len - string length
189254 align - (0 - top of font glyph | 1 - baseline )
255 aa - anti-aliasing level
190256
191257 =cut
192258 */
193259
194260 undef_int
195 i_t1_cp(i_img *im,i_img_dim xb,i_img_dim yb,int channel,int fontnum,double points,char* str,size_t len,int align, int utf8, char const *flags) {
261 i_t1_cp(i_t1_font_t font, i_img *im,i_img_dim xb,i_img_dim yb,int channel,double points,char* str,size_t len,int align, int utf8, char const *flags, int aa) {
196262 GLYPH *glyph;
197263 int xsize,ysize,x,y;
198264 i_color val;
199265 int mod_flags = t1_get_flags(flags);
266 int fontnum = font->font_id;
200267
201268 unsigned int ch_mask_store;
202269
203 if (im == NULL) { mm_log((1,"i_t1_cp: Null image in input\n")); return(0); }
270 i_clear_error();
271
272 mm_log((1, "i_t1_cp(font %p (%d), im %p, (xb,yb)=" i_DFp ", channel %d, points %g, str %p, len %u, align %d, utf8 %d, flags '%s', aa %d)\n",
273 font, fontnum, im, i_DFcp(xb, yb), channel, points, str, (unsigned)len, align, utf8, flags, aa));
274
275 if (im == NULL) {
276 mm_log((1,"i_t1_cp: Null image in input\n"));
277 i_push_error(0, "null image");
278 return(0);
279 }
280
281 i_mutex_lock(mutex);
282
283 i_t1_set_aa(aa);
204284
205285 if (utf8) {
206286 int worklen;
207287 char *work = t1_from_utf8(str, len, &worklen);
288 if (work == NULL) {
289 i_mutex_unlock(mutex);
290 return 0;
291 }
208292 glyph=T1_AASetString( fontnum, work, worklen, 0, mod_flags, points, NULL);
209293 myfree(work);
210294 }
211295 else {
212296 glyph=T1_AASetString( fontnum, str, len, 0, mod_flags, points, NULL);
213297 }
214 if (glyph == NULL)
298 if (glyph == NULL) {
299 t1_push_error();
300 i_push_error(0, "i_t1_cp: T1_AASetString failed");
301 i_mutex_unlock(mutex);
215302 return 0;
303 }
216304
217305 mm_log((1,"metrics: ascent: %d descent: %d\n",glyph->metrics.ascent,glyph->metrics.descent));
218306 mm_log((1," leftSideBearing: %d rightSideBearing: %d\n",glyph->metrics.leftSideBearing,glyph->metrics.rightSideBearing));
219307 mm_log((1," advanceX: %d advanceY: %d\n",glyph->metrics.advanceX,glyph->metrics.advanceY));
220 mm_log((1,"bpp: %d\n",glyph->bpp));
308 mm_log((1,"bpp: %lu\n", (unsigned long)glyph->bpp));
221309
222310 xsize=glyph->metrics.rightSideBearing-glyph->metrics.leftSideBearing;
223311 ysize=glyph->metrics.ascent-glyph->metrics.descent;
235323 }
236324
237325 im->ch_mask=ch_mask_store;
326
327 i_mutex_unlock(mutex);
328
238329 return 1;
239330 }
240331
266357 */
267358
268359 int
269 i_t1_bbox(int fontnum, double points,const char *str,size_t len, i_img_dim cords[6], int utf8,char const *flags) {
360 i_t1_bbox(i_t1_font_t font, double points,const char *str,size_t len, i_img_dim cords[6], int utf8,char const *flags) {
270361 BBox bbox;
271362 BBox gbbox;
272363 int mod_flags = t1_get_flags(flags);
273364 i_img_dim advance;
274 int space_position = T1_GetEncodingIndex(fontnum, "space");
275
276 mm_log((1,"i_t1_bbox(fontnum %d,points %.2f,str '%.*s', len %d)\n",fontnum,points,len,str,len));
277 T1_LoadFont(fontnum); /* FIXME: Here a return code is ignored - haw haw haw */
365 int fontnum = font->font_id;
366 int space_position;
367
368 i_clear_error();
369
370 i_mutex_lock(mutex);
371
372 space_position = T1_GetEncodingIndex(fontnum, "space");
373
374 mm_log((1,"i_t1_bbox(font %p (%d),points %.2f,str '%.*s', len %u)\n",
375 font, fontnum,points,(int)len,str,(unsigned)len));
376 if (T1_LoadFont(fontnum) == -1) {
377 t1_push_error();
378 i_mutex_unlock(mutex);
379 return 0;
380 }
278381
279382 if (len == 0) {
280383 /* len == 0 has special meaning to T1lib, but it means there's
286389 if (utf8) {
287390 int worklen;
288391 char *work = t1_from_utf8(str, len, &worklen);
392 if (!work) {
393 i_mutex_unlock(mutex);
394 return 0;
395 }
289396 advance = T1_GetStringWidth(fontnum, work, worklen, 0, mod_flags);
290397 bbox = T1_GetStringBBox(fontnum,work,worklen,0,mod_flags);
291398 t1_fix_bbox(&bbox, work, worklen, advance, space_position);
299406 }
300407 gbbox = T1_GetFontBBox(fontnum);
301408
302 mm_log((1,"bbox: (%d,%d,%d,%d)\n",
409 mm_log((1,"bbox: (%d, %d, %d, %d, %d, %d)\n",
303410 (int)(bbox.llx*points/1000),
304411 (int)(gbbox.lly*points/1000),
305412 (int)(bbox.urx*points/1000),
321428 cords[BBOX_RIGHT_BEARING] =
322429 cords[BBOX_ADVANCE_WIDTH] - cords[BBOX_POS_WIDTH];
323430
431 i_mutex_unlock(mutex);
432
324433 return BBOX_RIGHT_BEARING+1;
325434 }
326435
327436
328437 /*
329 =item i_t1_text(im, xb, yb, cl, fontnum, points, str, len, align)
438 =item i_t1_text(im, xb, yb, cl, fontnum, points, str, len, align, utf8, flags, aa)
330439
331440 Interface to text rendering in a single color onto an image
332441
339448 str - char pointer to string to render
340449 len - string length
341450 align - (0 - top of font glyph | 1 - baseline )
451 utf8 - str is utf8
452 flags - formatting flags
453 aa - anti-aliasing level
342454
343455 =cut
344456 */
345457
346458 undef_int
347 i_t1_text(i_img *im, i_img_dim xb, i_img_dim yb,const i_color *cl,int fontnum, double points,const char* str,size_t len,int align, int utf8, char const *flags) {
459 i_t1_text(i_t1_font_t font, i_img *im, i_img_dim xb, i_img_dim yb,const i_color *cl, double points,const char* str,size_t len,int align, int utf8, char const *flags, int aa) {
348460 GLYPH *glyph;
349461 int xsize,ysize,y;
350462 int mod_flags = t1_get_flags(flags);
351463 i_render *r;
352
353 if (im == NULL) { mm_log((1,"i_t1_cp: Null image in input\n")); return(0); }
464 int fontnum = font->font_id;
465
466 mm_log((1, "i_t1_text(font %p (%d), im %p, (xb,yb)=" i_DFp ", cl (%d,%d,%d,%d), points %g, str %p, len %u, align %d, utf8 %d, flags '%s', aa %d)\n",
467 font, fontnum, im, i_DFcp(xb, yb), cl->rgba.r, cl->rgba.g, cl->rgba.b, cl->rgba.a, points, str, (unsigned)len, align, utf8, flags, aa));
468
469 i_clear_error();
470
471 if (im == NULL) {
472 i_push_error(0, "null image");
473 mm_log((1,"i_t1_text: Null image in input\n"));
474 return(0);
475 }
476
477 i_mutex_lock(mutex);
478
479 i_t1_set_aa(aa);
354480
355481 if (utf8) {
356482 int worklen;
357483 char *work = t1_from_utf8(str, len, &worklen);
484 if (!work) {
485 i_mutex_unlock(mutex);
486 return 0;
487 }
358488 glyph=T1_AASetString( fontnum, work, worklen, 0, mod_flags, points, NULL);
359489 myfree(work);
360490 }
362492 /* T1_AASetString() accepts a char * not a const char */
363493 glyph=T1_AASetString( fontnum, (char *)str, len, 0, mod_flags, points, NULL);
364494 }
365 if (glyph == NULL)
495 if (glyph == NULL) {
496 mm_log((1, "T1_AASetString failed\n"));
497 t1_push_error();
498 i_push_error(0, "i_t1_text(): T1_AASetString failed");
499 i_mutex_unlock(mutex);
366500 return 0;
501 }
367502
368503 mm_log((1,"metrics: ascent: %d descent: %d\n",glyph->metrics.ascent,glyph->metrics.descent));
369504 mm_log((1," leftSideBearing: %d rightSideBearing: %d\n",glyph->metrics.leftSideBearing,glyph->metrics.rightSideBearing));
370505 mm_log((1," advanceX: %d advanceY: %d\n",glyph->metrics.advanceX,glyph->metrics.advanceY));
371 mm_log((1,"bpp: %d\n",glyph->bpp));
506 mm_log((1,"bpp: %lu\n",(unsigned long)glyph->bpp));
372507
373508 xsize=glyph->metrics.rightSideBearing-glyph->metrics.leftSideBearing;
374509 ysize=glyph->metrics.ascent-glyph->metrics.descent;
382517 i_render_color(r, xb, yb+y, xsize, (unsigned char *)glyph->bits+y*xsize, cl);
383518 }
384519 i_render_delete(r);
520
521 i_mutex_unlock(mutex);
385522
386523 return 1;
387524 }
466603 */
467604
468605 int
469 i_t1_has_chars(int font_num, const char *text, size_t len, int utf8,
606 i_t1_has_chars(i_t1_font_t font, const char *text, size_t len, int utf8,
470607 char *out) {
471608 int count = 0;
472
473 mm_log((1, "i_t1_has_chars(font_num %d, text %p, len %d, utf8 %d)\n",
474 font_num, text, len, utf8));
609 int font_num = font->font_id;
610
611 i_mutex_lock(mutex);
612
613 mm_log((1, "i_t1_has_chars(font_num %d, text %p, len %u, utf8 %d)\n",
614 font_num, text, (unsigned)len, utf8));
475615
476616 i_clear_error();
477617 if (T1_LoadFont(font_num)) {
478618 t1_push_error();
619 i_mutex_unlock(mutex);
479620 return 0;
480621 }
481622
485626 c = i_utf8_advance(&text, &len);
486627 if (c == ~0UL) {
487628 i_push_error(0, "invalid UTF8 character");
629 i_mutex_unlock(mutex);
488630 return 0;
489631 }
490632 }
511653 ++count;
512654 }
513655
656 i_mutex_unlock(mutex);
657
514658 return count;
515659 }
516660
517661 /*
518 =item i_t1_face_name(font_num, name_buf, name_buf_size)
662 =item i_t1_face_name(font, name_buf, name_buf_size)
519663
520664 Copies the face name of the given C<font_num> to C<name_buf>. Returns
521665 the number of characters required to store the name (which can be
529673 */
530674
531675 int
532 i_t1_face_name(int font_num, char *name_buf, size_t name_buf_size) {
676 i_t1_face_name(i_t1_font_t font, char *name_buf, size_t name_buf_size) {
533677 char *name;
678 int font_num = font->font_id;
679
680 i_mutex_lock(mutex);
534681
535682 T1_errno = 0;
536683 if (T1_LoadFont(font_num)) {
537684 t1_push_error();
685 i_mutex_unlock(mutex);
538686 return 0;
539687 }
540688 name = T1_GetFontName(font_num);
541689
542690 if (name) {
691 size_t len = strlen(name);
543692 strncpy(name_buf, name, name_buf_size);
544693 name_buf[name_buf_size-1] = '\0';
545 return strlen(name) + 1;
694 i_mutex_unlock(mutex);
695 return len + 1;
546696 }
547697 else {
548698 t1_push_error();
699 i_mutex_unlock(mutex);
549700 return 0;
550701 }
551702 }
552703
553704 int
554 i_t1_glyph_name(int font_num, unsigned long ch, char *name_buf,
705 i_t1_glyph_name(i_t1_font_t font, unsigned long ch, char *name_buf,
555706 size_t name_buf_size) {
556707 char *name;
708 int font_num = font->font_id;
557709
558710 i_clear_error();
559711 if (ch > 0xFF) {
560712 return 0;
561713 }
714
715 i_mutex_lock(mutex);
716
562717 if (T1_LoadFont(font_num)) {
563718 t1_push_error();
719 i_mutex_unlock(mutex);
564720 return 0;
565721 }
566722 name = T1_GetCharName(font_num, (unsigned char)ch);
567723 if (name) {
568724 if (strcmp(name, ".notdef")) {
725 size_t len = strlen(name);
569726 strncpy(name_buf, name, name_buf_size);
570727 name_buf[name_buf_size-1] = '\0';
571 return strlen(name) + 1;
728 i_mutex_unlock(mutex);
729 return len + 1;
572730 }
573731 else {
732 i_mutex_unlock(mutex);
574733 return 0;
575734 }
576735 }
577736 else {
578737 t1_push_error();
738 i_mutex_unlock(mutex);
579739 return 0;
580740 }
581741 }
11 #define IMAGER_IMT1_H
22
33 #include "imdatatypes.h"
4
5 typedef struct i_t1_font_tag *i_t1_font_t;
6
7 extern void
8 i_t1_start(void);
49
510 extern undef_int
611 i_init_t1(int t1log);
813 extern void
914 i_close_t1(void);
1015
11 extern int
16 extern i_t1_font_t
1217 i_t1_new(char *pfb,char *afm);
1318
1419 extern int
15 i_t1_destroy(int font_id);
16
17 extern void
18 i_t1_set_aa(int st);
20 i_t1_destroy(i_t1_font_t font);
1921
2022 extern undef_int
21 i_t1_cp(i_img *im,i_img_dim xb,i_img_dim yb,int channel,int fontnum,double points,char* str,size_t len,int align, int utf8, char const *flags);
23 i_t1_cp(i_t1_font_t font, i_img *im,i_img_dim xb,i_img_dim yb,int channel,double points,char* str,size_t len,int align, int utf8, char const *flags, int aa);
2224
2325 extern int
24 i_t1_bbox(int fontnum,double points,const char *str,size_t len,i_img_dim *cords, int utf8,char const *flags);
26 i_t1_bbox(i_t1_font_t font,double points,const char *str,size_t len,i_img_dim *cords, int utf8,char const *flags);
2527
2628 extern undef_int
27 i_t1_text(i_img *im,i_img_dim xb,i_img_dim yb,const i_color *cl,int fontnum,double points,const char* str,size_t len,int align, int utf8, char const *flags);
29 i_t1_text(i_t1_font_t font, i_img *im,i_img_dim xb,i_img_dim yb,const i_color *cl,double points,const char* str,size_t len,int align, int utf8, char const *flags, int aa);
2830
2931 extern int
30 i_t1_has_chars(int font_num, const char *text, size_t len, int utf8,
32 i_t1_has_chars(i_t1_font_t font, const char *text, size_t len, int utf8,
3133 char *out);
3234
3335 extern int
34 i_t1_face_name(int font_num, char *name_buf, size_t name_buf_size);
36 i_t1_face_name(i_t1_font_t font, char *name_buf, size_t name_buf_size);
3537
3638 extern int
37 i_t1_glyph_name(int font_num, unsigned long ch, char *name_buf,
39 i_t1_glyph_name(i_t1_font_t font, unsigned long ch, char *name_buf,
3840 size_t name_buf_size);
3941 #endif
11 use strict;
22 use Test::More;
33 use Imager ':all';
4 use Imager::Test qw(diff_text_with_nul is_color3);
4 use Imager::Test qw(diff_text_with_nul is_color3 is_image isnt_image);
55 use Imager::Font::T1;
66 use Cwd qw(getcwd abs_path);
77
88 #$Imager::DEBUG=1;
99
10 plan tests => 97;
10 plan tests => 110;
1111
1212 ok($Imager::formats{t1}, "must have t1");
1313
14 ok((-d "testout" or mkdir "testout"), "make output directory");
14 -d "testout" or mkdir "testout";
15 ok(-d "testout", "make output directory");
1516
1617 init_log("testout/t10type1.log",1);
1718
3940 init(t1log=>0);
4041 unlink "t1lib.log";
4142
42 my $fnum=Imager::Font::T1::i_t1_new($fontname_pfb,$fontname_afm); # this will load the pfb font
43 my $fnum=Imager::Font::T1xs->new($fontname_pfb,$fontname_afm); # this will load the pfb font
4344 unless (ok($fnum >= 0, "load font $fontname_pfb")) {
4445 skip("without the font I can't do a thing", 90);
4546 }
4647
47 my $bgcolor=Imager::Color->new(255,0,0,0);
48 my $bgcolor=Imager::Color->new(255,0,0,255);
4849 my $overlay=Imager::ImgRaw::new(200,70,3);
4950
50 ok(Imager::Font::T1::i_t1_cp($overlay,5,50,1,$fnum,50.0,'XMCLH',5,1), "i_t1_cp");
51 ok($fnum->cp($overlay,5,50,1,50.0,'XMCLH',1), "i_t1_cp");
5152
5253 i_line($overlay,0,50,100,50,$bgcolor,1);
5354
54 my @bbox=Imager::Font::T1::i_t1_bbox(0,50.0,'XMCLH',5);
55 my @bbox=$fnum->bbox(50.0,'XMCLH');
5556 is(@bbox, 8, "i_t1_bbox");
5657 print "# bbox: ($bbox[0], $bbox[1]) - ($bbox[2], $bbox[3])\n";
5758
6162 i_writeppm_wiol($overlay,$IO);
6263 close(FH);
6364
64 $bgcolor=Imager::Color::set($bgcolor,200,200,200,0);
65 $bgcolor=Imager::Color::set($bgcolor,200,200,200,255);
6566 my $backgr=Imager::ImgRaw::new(280,300,3);
6667
67 Imager::Font::T1::i_t1_set_aa(2);
68 ok(Imager::Font::T1::i_t1_text($backgr,10,100,$bgcolor,$fnum,150.0,'test',4,1), "i_t1_text");
68 ok($fnum->text($backgr,10,100,$bgcolor,150.0,'test',1,2), "i_t1_text");
6969
7070 # "UTF8" tests
7171 # for perl < 5.6 we can hand-encode text
7676 my $text = pack("C*", 0x41, 0xC2, 0xA1, 0xE2, 0x80, 0x90, 0x41);
7777 my $alttext = "A\xA1A";
7878
79 my @utf8box = Imager::Font::T1::i_t1_bbox($fnum, 50.0, $text, length($text), 1);
79 my @utf8box = $fnum->bbox(50.0, $text, 1);
8080 is(@utf8box, 8, "utf8 bbox element count");
81 my @base = Imager::Font::T1::i_t1_bbox($fnum, 50.0, $alttext, length($alttext), 0);
81 my @base = $fnum->bbox(50.0, $alttext, 0);
8282 is(@base, 8, "alt bbox element count");
8383 my $maxdiff = $fontname_pfb eq $deffont ? 0 : $base[2] / 3;
8484 print "# (@utf8box vs @base)\n";
8686 "compare box sizes $utf8box[2] vs $base[2] (maxerror $maxdiff)");
8787
8888 # hand-encoded UTF8 drawing
89 ok(Imager::Font::T1::i_t1_text($backgr, 10, 140, $bgcolor, $fnum, 32, $text, length($text), 1,1), "draw hand-encoded UTF8");
90
91 ok(Imager::Font::T1::i_t1_cp($backgr, 80, 140, 1, $fnum, 32, $text, length($text), 1, 1),
89 ok($fnum->text($backgr, 10, 140, $bgcolor, 32, $text, 1,1), "draw hand-encoded UTF8");
90
91 ok($fnum->cp($backgr, 80, 140, 1, 32, $text, 1, 1),
9292 "cp hand-encoded UTF8");
93
94 { # invalid utf8
95 my $text = pack("C", 0xC0);
96 ok(!$fnum->text($backgr, 10, 140, $bgcolor, 32, $text, 1, 1),
97 "attempt to draw invalid utf8");
98 is(Imager->_error_as_msg, "invalid UTF8 character",
99 "check message");
100 }
93101
94102 # ok, try native perl UTF8 if available
95103 SKIP:
100108 # versions
101109 eval q{$text = "A\xA1\x{2010}A"}; # A, a with ogonek, HYPHEN, A in our test font
102110 #$text = "A".chr(0xA1).chr(0x2010)."A"; # this one works too
103 ok(Imager::Font::T1::i_t1_text($backgr, 10, 180, $bgcolor, $fnum, 32, $text, length($text), 1),
111 Imager->log("draw UTF8\n");
112 ok($fnum->text($backgr, 10, 180, $bgcolor, 32, $text, 1),
104113 "draw UTF8");
105 ok(Imager::Font::T1::i_t1_cp($backgr, 80, 180, 1, $fnum, 32, $text, length($text), 1),
114 ok($fnum->cp($backgr, 80, 180, 1, 32, $text, 1),
106115 "cp UTF8");
107 @utf8box = Imager::Font::T1::i_t1_bbox($fnum, 50.0, $text, length($text), 0);
116 @utf8box = $fnum->bbox(50.0, $text, 0);
108117 is(@utf8box, 8, "native utf8 bbox element count");
109118 ok(abs($utf8box[2] - $base[2]) <= $maxdiff,
110119 "compare box sizes native $utf8box[2] vs $base[2] (maxerror $maxdiff)");
111120 eval q{$text = "A\xA1\xA2\x01\x1F\x{0100}A"};
112 ok(Imager::Font::T1::i_t1_text($backgr, 10, 220, $bgcolor, $fnum, 32, $text, 0, 1, 0, "uso"),
121 ok($fnum->text($backgr, 10, 220, $bgcolor, 32, $text, 0, 1, "uso"),
113122 "more complex output");
114123 }
115124
119128 i_writeppm_wiol($backgr, $IO);
120129 close(FH);
121130
122 my $rc=Imager::Font::T1::i_t1_destroy($fnum);
123 unless (ok($rc >= 0, "i_t1_destroy")) {
124 print "# i_t1_destroy failed: rc=$rc\n";
125 }
126
127 print "# debug: ",join(" x ",Imager::Font::T1::i_t1_bbox(0,50,"eses",4) ),"\n";
128 print "# debug: ",join(" x ",Imager::Font::T1::i_t1_bbox(0,50,"llll",4) ),"\n";
131 undef $fnum;
129132
130133 # character existance tests - uses the special ExistenceTest font
131134 my $exists_font = 'fontfiles/ExistenceTest.pfb';
133136
134137 -e $exists_font or die "$exists_font not found";
135138
136 my $font_num = Imager::Font::T1::i_t1_new($exists_font, $exists_afm);
139 my $font_num = Imager::Font::T1xs->new($exists_font, $exists_afm);
137140 SKIP: {
138141 ok($font_num >= 0, 'loading test font')
139142 or skip('Could not load test font', 6);
140143 # first the list interface
141 my @exists = Imager::Font::T1::i_t1_has_chars($font_num, "!A");
144 my @exists = $font_num->has_chars("!A");
142145 is(@exists, 2, "return count from has_chars");
143146 ok($exists[0], "we have an exclamation mark");
144147 ok(!$exists[1], "we have no uppercase A");
145148
146149 # then the scalar interface
147 my $exists = Imager::Font::T1::i_t1_has_chars($font_num, "!A");
150 my $exists = $font_num->has_chars("!A");
148151 is(length($exists), 2, "return scalar length");
149152 ok(ord(substr($exists, 0, 1)), "we have an exclamation mark");
150153 ok(!ord(substr($exists, 1, 1)), "we have no upper-case A");
151 Imager::Font::T1::i_t1_destroy($font_num);
154 undef $font_num;
152155 }
153156
154157 my $font = Imager::Font->new(file=>$exists_font, type=>'t1');
173176 isnt($bbox[2], $bbox[5], "different advance to pos_width");
174177
175178 # names
176 my $face_name = Imager::Font::T1::i_t1_face_name($font->{id});
179 my $face_name = $font->{t1font}->face_name();
177180 print "# face $face_name\n";
178181 is($face_name, 'ExistenceTest', "face name");
179182 $face_name = $font->face_name;
366369 ok($font, "found font by drive relative path")
367370 or print "# path $drive_path\n";
368371 }
372
373 {
374 Imager->log("Testing aa levels", 1);
375 my $f1 = Imager::Font->new(file => $deffont, type => "t1");
376 is($f1->{t1aa}, 2, "should have default aa level");
377 my $imbase = Imager->new(xsize => 100, ysize => 20);
378 ok($imbase->string(text => "test", size => 18, x => 5, y => 18,
379 color => "#FFF", font => $f1, aa => 1),
380 "draw text with def aa level");
381 ok(Imager::Font::T1->set_aa_level(1), "set aa level to 1");
382 my $f2 = Imager::Font->new(file => $deffont, type => "t1");
383 is($f2->{t1aa}, 1, "new font has new aa level");
384 my $imaa1 = Imager->new(xsize => 100, ysize => 20);
385 ok($imaa1->string(text => "test", size => 18, x => 5, y => 18,
386 color => "#FFF", font => $f2, aa => 1),
387 "draw text with non-def aa level");
388 isnt_image($imbase, $imaa1, "images should differ");
389 ok($f2->set_aa_level(2), "set aa level of font");
390 is($f2->{t1aa}, 2, "check new aa level");
391 my $imaa2 = Imager->new(xsize => 100, ysize => 20);
392 ok($imaa2->string(text => "test", size => 18, x => 5, y => 18,
393 color => "#FFF", font => $f2, aa => 1),
394 "draw text with non-def but 2 aa level");
395 is_image($imbase, $imaa2, "check images match");
396 }
397
398 { # error handling check
399 my $im = Imager->new(xsize => 100, ysize => 20);
400 my $fnum = Imager::Font->new(file => $deffont, type => "t1");
401 ok(!$im->string(font => $fnum, string => "text", size => -10),
402 "set invalid size");
403 is($im->errstr, "i_t1_text(): T1_AASetString failed: Invalid Argument in Function Call",
404 "check error message");
405 }
369406 }
370407
408
371409 #malloc_state();
410
1212 my $red=Imager::Color->new(205, 92, 92, 255);
1313 die $Imager::ERRSTR unless $red;
1414
15 ok((-d "testout" or mkdir "testout"), "make output directory");
15 -d "testout" or mkdir "testout";
16 ok(-d "testout", "make output directory");
1617
1718 Imager::init_log("testout/t20oo.log", 1);
1819
0 #!perl -w
1 use strict;
2 use Imager;
3
4 use Config;
5 my $loaded_threads;
6 BEGIN {
7 if ($Config{useithreads} && $] > 5.008007) {
8 $loaded_threads =
9 eval {
10 require threads;
11 threads->import;
12 1;
13 };
14 }
15 }
16
17 use Test::More;
18
19 $Config{useithreads}
20 or plan skip_all => "can't test Imager's threads support with no threads";
21 $] > 5.008007
22 or plan skip_all => "require a perl with CLONE_SKIP to test Imager's threads support";
23 $loaded_threads
24 or plan skip_all => "couldn't load threads";
25
26 $INC{"Devel/Cover.pm"}
27 and plan skip_all => "threads and Devel::Cover don't get along";
28
29 # https://rt.cpan.org/Ticket/Display.html?id=65812
30 # https://github.com/schwern/test-more/issues/labels/Test-Builder2#issue/100
31 $Test::More::VERSION =~ /^2\.00_/
32 and plan skip_all => "threads are hosed in 2.00_06 and presumably all 2.00_*";
33
34 plan tests => 8;
35
36 Imager->open_log(log => "testout/t30thread.log");
37
38 my $ft1 = Imager::Font->new(file => "fontfiles/dcr10.pfb", type => "t1");
39 ok($ft1, "make a font");
40 ok($ft1->_valid, "and it's valid");
41 my $ft2;
42
43 my $thr = threads->create
44 (
45 sub {
46 ok(!$ft1->_valid, "first font no longer valid");
47 $ft2 = Imager::Font->new(file => "fontfiles/dcr10.pfb", type => "t1");
48 ok($ft2, "make a new font in thread");
49 ok($ft2->_valid, "and it's valid");
50 1;
51 },
52 );
53
54 ok($thr->join, "join the thread");
55 ok($ft1->_valid, "original font still valid in main thread");
56 is($ft2, undef, "font created in thread shouldn't be set in main thread");
57
58 Imager->close_log();
0 #!perl -w
1 use strict;
2 use Imager::Test qw(std_font_tests std_font_test_count);
3 use Imager::Font;
4 use Test::More tests => std_font_test_count();
5
6 Imager->open_log(log => "testout/t90std.log");
7
8 my $font = Imager::Font->new(file => "fontfiles/dcr10.pfb",
9 type => "t1");
10
11 SKIP:
12 {
13 $font
14 or skip "Cannot load font", std_font_test_count();
15 std_font_tests({ font => $font,
16 has_chars => [ 1, '', 1 ]});
17 }
18
19 Imager->close_log;
0 Imager::Font::T1xs T_PTROBJ
3737 $opts{TYPEMAPS} = [ Imager::ExtUtils->typemap ];
3838
3939 # Imager required configure through use
40 my @Imager_req = ( Imager => "0.86" );
40 my @Imager_req = ( Imager => "0.94" );
4141 if ($MM_ver >= 6.46) {
4242 $opts{META_MERGE} =
4343 {
00 Imager::File::TIFF provides TIFF file format support for Imager.
11
2 It requires libtiff to be installed.
2 It requires libtiff to be installed, including development files.
3
4 For Linux distributions this typically requires installation of the
5 associated -dev or -devel package.
6
7 See Imager::Install for more information.
38
49 This is currently shipped as part of Imager, but Imager may install
510 with out installing Imager::File::TIFF, so if you need TIFF support,
33 use vars qw($VERSION @ISA);
44
55 BEGIN {
6 $VERSION = "0.84";
6 $VERSION = "0.87";
77
88 require XSLoader;
99 XSLoader::load('Imager::File::TIFF', $VERSION);
142142
143143 BOOT:
144144 PERL_INITIALIZE_IMAGER_CALLBACKS;
145 i_tiff_init();
264264 }
265265
266266 #endif
267
268 static i_mutex_t mutex;
269
270 void
271 i_tiff_init(void) {
272 mutex = i_mutex_new();
273 }
267274
268275 static int save_tiff_tags(TIFF *tif, i_img *im);
269276
620627 int current_page;
621628 tiffio_context_t ctx;
622629
630 i_mutex_lock(mutex);
631
623632 i_clear_error();
624633 old_handler = TIFFSetErrorHandler(error_handler);
625634 #ifdef USE_EXT_WARN_HANDLER
657666 TIFFSetWarningHandlerExt(old_ext_warn_handler);
658667 #endif
659668 tiffio_context_final(&ctx);
669 i_mutex_unlock(mutex);
660670 return NULL;
661671 }
662672
671681 #endif
672682 TIFFClose(tif);
673683 tiffio_context_final(&ctx);
684 i_mutex_unlock(mutex);
674685 return NULL;
675686 }
676687 }
685696 #endif
686697 TIFFClose(tif);
687698 tiffio_context_final(&ctx);
699 i_mutex_unlock(mutex);
688700
689701 return im;
690702 }
708720 int result_alloc = 0;
709721 tiffio_context_t ctx;
710722
723 i_mutex_lock(mutex);
724
711725 i_clear_error();
712726 old_handler = TIFFSetErrorHandler(error_handler);
713727 #ifdef USE_EXT_WARN_HANDLER
724738 /* Add code to get the filename info from the iolayer */
725739 /* Also add code to check for mmapped code */
726740
727 mm_log((1, "i_readtiff_wiol(ig %p, length %d)\n", ig));
741 mm_log((1, "i_readtiff_wiol(ig %p)\n", ig));
728742
729743 tif = TIFFClientOpen("(Iolayer)",
730744 "rm",
746760 TIFFSetWarningHandlerExt(old_ext_warn_handler);
747761 #endif
748762 tiffio_context_final(&ctx);
763 i_mutex_unlock(mutex);
749764 return NULL;
750765 }
751766
780795 #endif
781796 TIFFClose(tif);
782797 tiffio_context_final(&ctx);
798 i_mutex_unlock(mutex);
783799
784800 return results;
785801 }
14451461 int i;
14461462 tiffio_context_t ctx;
14471463
1464 i_mutex_lock(mutex);
1465
14481466 old_handler = TIFFSetErrorHandler(error_handler);
14491467
14501468 i_clear_error();
14711489 i_push_error(0, "Could not create TIFF object");
14721490 TIFFSetErrorHandler(old_handler);
14731491 tiffio_context_final(&ctx);
1492 i_mutex_unlock(mutex);
14741493 return 0;
14751494 }
14761495
14791498 TIFFClose(tif);
14801499 TIFFSetErrorHandler(old_handler);
14811500 tiffio_context_final(&ctx);
1501 i_mutex_unlock(mutex);
14821502 return 0;
14831503 }
14841504
14871507 TIFFClose(tif);
14881508 TIFFSetErrorHandler(old_handler);
14891509 tiffio_context_final(&ctx);
1510 i_mutex_unlock(mutex);
14901511 return 0;
14911512 }
14921513 }
14941515 TIFFSetErrorHandler(old_handler);
14951516 (void) TIFFClose(tif);
14961517 tiffio_context_final(&ctx);
1518
1519 i_mutex_unlock(mutex);
14971520
14981521 if (i_io_close(ig))
14991522 return 0;
15201543 int i;
15211544 TIFFErrorHandler old_handler;
15221545 tiffio_context_t ctx;
1546
1547 i_mutex_lock(mutex);
15231548
15241549 old_handler = TIFFSetErrorHandler(error_handler);
15251550
15471572 i_push_error(0, "Could not create TIFF object");
15481573 TIFFSetErrorHandler(old_handler);
15491574 tiffio_context_final(&ctx);
1575 i_mutex_unlock(mutex);
15501576 return 0;
15511577 }
15521578
15551581 TIFFClose(tif);
15561582 TIFFSetErrorHandler(old_handler);
15571583 tiffio_context_final(&ctx);
1584 i_mutex_unlock(mutex);
15581585 return 0;
15591586 }
15601587
15631590 TIFFClose(tif);
15641591 TIFFSetErrorHandler(old_handler);
15651592 tiffio_context_final(&ctx);
1593 i_mutex_unlock(mutex);
15661594 return 0;
15671595 }
15681596 }
15701598 (void) TIFFClose(tif);
15711599 TIFFSetErrorHandler(old_handler);
15721600 tiffio_context_final(&ctx);
1601
1602 i_mutex_unlock(mutex);
15731603
15741604 if (i_io_close(ig))
15751605 return 0;
15921622 TIFF* tif;
15931623 TIFFErrorHandler old_handler;
15941624 tiffio_context_t ctx;
1625
1626 i_mutex_lock(mutex);
15951627
15961628 old_handler = TIFFSetErrorHandler(error_handler);
15971629
16181650 i_push_error(0, "Could not create TIFF object");
16191651 tiffio_context_final(&ctx);
16201652 TIFFSetErrorHandler(old_handler);
1653 i_mutex_unlock(mutex);
16211654 return 0;
16221655 }
16231656
16251658 TIFFClose(tif);
16261659 tiffio_context_final(&ctx);
16271660 TIFFSetErrorHandler(old_handler);
1661 i_mutex_unlock(mutex);
16281662 return 0;
16291663 }
16301664
16311665 (void) TIFFClose(tif);
16321666 TIFFSetErrorHandler(old_handler);
1633 tiffio_context_final(&ctx);
1667 tiffio_context_final(&ctx);
1668 i_mutex_unlock(mutex);
16341669
16351670 if (i_io_close(ig))
16361671 return 0;
16601695 TIFF* tif;
16611696 TIFFErrorHandler old_handler;
16621697 tiffio_context_t ctx;
1698
1699 i_mutex_lock(mutex);
16631700
16641701 old_handler = TIFFSetErrorHandler(error_handler);
16651702
16861723 i_push_error(0, "Could not create TIFF object");
16871724 TIFFSetErrorHandler(old_handler);
16881725 tiffio_context_final(&ctx);
1726 i_mutex_unlock(mutex);
16891727 return 0;
16901728 }
16911729
16931731 TIFFClose(tif);
16941732 TIFFSetErrorHandler(old_handler);
16951733 tiffio_context_final(&ctx);
1734 i_mutex_unlock(mutex);
16961735 return 0;
16971736 }
16981737
16991738 (void) TIFFClose(tif);
17001739 TIFFSetErrorHandler(old_handler);
17011740 tiffio_context_final(&ctx);
1741 i_mutex_unlock(mutex);
17021742
17031743 if (i_io_close(ig))
17041744 return 0;
26842724 uint16 *p = state->raster;
26852725 int out_chan = state->img->channels;
26862726
2687 mm_log((4, "putter_cmyk16(%p, %d, %d, %d, %d, %d)\n", x, y, width, height, row_extras));
2727 mm_log((4, "putter_cmyk16(%p, %" i_DF ", %" i_DF ", %" i_DF
2728 ", %" i_DF ", %d)\n", state, i_DFcp(x, y), i_DFcp(width, height),
2729 row_extras));
26882730
26892731 state->pixels_read += width * height;
26902732 while (height > 0) {
22
33 #include "imdatatypes.h"
44
5 void i_tiff_init(void);
56 i_img * i_readtiff_wiol(io_glue *ig, int allow_incomplete, int page);
67 i_img ** i_readtiff_multi_wiol(io_glue *ig, int *count);
78 undef_int i_writetiff_wiol(i_img *im, io_glue *ig);
3737 $opts{TYPEMAPS} = [ Imager::ExtUtils->typemap ];
3838
3939 # Imager required configure through use
40 my @Imager_req = ( Imager => "0.86" );
40 my @Imager_req = ( Imager => "0.95" );
4141 if ($MM_ver >= 6.46) {
4242 $opts{META_MERGE} =
4343 {
44 @ISA = qw(Imager::Font);
55
66 BEGIN {
7 $VERSION = "0.85";
7 $VERSION = "0.87";
88
99 require XSLoader;
1010 XSLoader::load('Imager::Font::W32', $VERSION);
2929 my ($self, %opts) = @_;
3030
3131 my @bbox = i_wf_bbox($self->{face}, $opts{size}, $opts{string}, $opts{utf8});
32 unless (@bbox) {
33 Imager->_set_error(Imager->_error_as_msg);
34 return;
35 }
36
37 return @bbox;
3238 }
3339
3440 sub _draw {
3642
3743 my %input = @_;
3844 if (exists $input{channel}) {
39 i_wf_cp($self->{face}, $input{image}{IMG}, $input{x}, $input{'y'},
45 return i_wf_cp($self->{face}, $input{image}{IMG}, $input{x}, $input{'y'},
4046 $input{channel}, $input{size},
4147 $input{string}, $input{align}, $input{aa}, $input{utf8});
4248 }
4349 else {
44 i_wf_text($self->{face}, $input{image}{IMG}, $input{x},
50 return i_wf_text($self->{face}, $input{image}{IMG}, $input{x},
4551 $input{'y'}, $input{color}, $input{size},
4652 $input{string}, $input{align}, $input{aa}, $input{utf8});
4753 }
48
49 return 1;
5054 }
5155
5256
5357 sub utf8 {
5458 return 1;
59 }
60
61 sub can_glyph_names {
62 return;
5563 }
5664
5765 1;
0 #!perl -w
1 use strict;
2 use Imager::Test qw(std_font_tests std_font_test_count);
3 use Imager::Font;
4 use Test::More tests => std_font_test_count();
5
6 Imager->open_log(log => "testout/t90std.log");
7
8 my $font = Imager::Font->new(face => "Times New Roman Bold",
9 type => "w32");
10
11 SKIP:
12 {
13 $font
14 or skip "Cannot load font", std_font_test_count();
15 std_font_tests
16 ({
17 font => $font,
18 #has_chars => [ 1, 1, 1 ],
19 #files => 1,
20 #glyph_name_font => $name_font,
21 #glyph_names => [ "A", "uni2010", "A" ],
22 });
23 }
24 Imager->close_log;
542542 static
543543 LPWSTR
544544 utf8_to_wide_string(char const *text, int text_len, int *wide_chars) {
545 int wide_count = MultiByteToWideChar(CP_UTF8, 0, text, text_len, NULL, 0);
545 int wide_count = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, text, text_len, NULL, 0);
546546 LPWSTR result;
547547
548548 if (wide_count < 0) {
551551 }
552552 ++wide_count;
553553 result = mymalloc(sizeof(WCHAR) * wide_count);
554 if (MultiByteToWideChar(CP_UTF8, 0, text, text_len, result, wide_count) < 0) {
554 if (MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, text, text_len, result, wide_count) < 0) {
555555 i_push_errorf(0, "Could not convert utf8: %ld", GetLastError());
556556 return NULL;
557557 }
177177
178178 =head1 SEE ALSO
179179
180 Imager, Imager::ExtUtils, Imager::Inline
180 Imager, Imager::API, Imager::ExtUtils, Imager::Inline
181181
182182 =cut
183183 EOS
186186
187187
188188 sub make_func_list {
189 my @funcs = qw(i_img i_color i_fcolor i_fill_t mm_log i_img_color_channels i_img_has_alpha i_img_dim i_DF i_DFc i_DFp i_DFcp i_psamp_bits i_gsamp_bits i_psamp i_psampf);
189 my @funcs = qw(i_img i_color i_fcolor i_fill_t mm_log mm_log i_img_color_channels i_img_has_alpha i_img_dim i_DF i_DFc i_DFp i_DFcp i_psamp_bits i_gsamp_bits i_psamp i_psampf);
190190 open FUNCS, "< imexttypes.h"
191191 or die "Cannot open imexttypes.h: $!\n";
192192 my $in_struct;
193193 while (<FUNCS>) {
194194 /^typedef struct/ && ++$in_struct;
195 if ($in_struct && /\(\*f_(io?_\w+)/) {
195 if ($in_struct && !/SKIP/ && /\(\*f_(i[om]?_\w+)/) {
196196 my $name = $1;
197197 $name =~ s/_imp$//;
198198 push @funcs, $name;
+44
-25
bmp.c less more
0 #define IMAGER_NO_CONTEXT
01 #include <stdarg.h>
12 #include "imageri.h"
23
7576 */
7677 int
7778 i_writebmp_wiol(i_img *im, io_glue *ig) {
79 dIMCTXim(im);
7880 i_clear_error();
7981
8082 /* pick a format */
115117 i_packed_t xsize, ysize, planes, bit_count, compression, size_image, xres, yres;
116118 i_packed_t clr_used, clr_important, offbits;
117119 i_img *im;
118
119 mm_log((1, "i_readbmp_wiol(ig %p)\n", ig));
120 dIMCTXio(ig);
121
122 im_log((aIMCTX, 1, "i_readbmp_wiol(ig %p)\n", ig));
120123
121124 i_clear_error();
122125
134137 return 0;
135138 }
136139
137 mm_log((1, " bmp header: filesize %d offbits %d xsize %d ysize %d planes %d "
140 im_log((aIMCTX, 1, " bmp header: filesize %d offbits %d xsize %d ysize %d planes %d "
138141 "bit_count %d compression %d size %d xres %d yres %d clr_used %d "
139142 "clr_important %d\n", (int)filesize, (int)offbits, (int)xsize,
140143 (int)ysize, (int)planes, (int)bit_count, (int)compression,
142145 (int)clr_important));
143146
144147 if (!i_int_check_image_file_limits(xsize, abs(ysize), 3, sizeof(i_sample_t))) {
145 mm_log((1, "i_readbmp_wiol: image size exceeds limits\n"));
148 im_log((aIMCTX, 1, "i_readbmp_wiol: image size exceeds limits\n"));
146149 return NULL;
147150 }
148151
170173 break;
171174
172175 default:
173 i_push_errorf(0, "unknown bit count for BMP file (%d)", (int)bit_count);
176 im_push_errorf(aIMCTX, 0, "unknown bit count for BMP file (%d)", (int)bit_count);
174177 return NULL;
175178 }
176179
272275 break;
273276
274277 default:
275 i_fatal(1, "Unknown read_packed format code 0x%02x", code);
278 {
279 dIMCTXio(ig);
280 im_fatal(aIMCTX, 1, "Unknown read_packed format code 0x%02x", code);
281 }
276282 }
277283 }
278284 return 1;
324330 break;
325331
326332 default:
327 i_fatal(1, "Unknown write_packed format code 0x%02x", *format);
333 {
334 dIMCTXio(ig);
335 im_fatal(aIMCTX, 1, "Unknown write_packed format code 0x%02x", *format);
336 }
328337 }
329338 ++format;
330339 }
349358 int got_xres, got_yres, aspect_only;
350359 int colors_used = 0;
351360 int offset = FILEHEAD_SIZE + INFOHEAD_SIZE;
361 dIMCTXim(im);
352362
353363 if (im->xsize > SIGNMAX32 || im->ysize > SIGNMAX32) {
354364 i_push_error(0, "image too large to write to BMP");
450460 int line_size = (im->xsize+7) / 8;
451461 int x, y;
452462 int unpacked_size;
463 dIMCTXim(im);
453464
454465 /* round up to nearest multiple of four */
455466 line_size = (line_size + 3) / 4 * 4;
521532 int line_size = (im->xsize+1) / 2;
522533 int x, y;
523534 int unpacked_size;
535 dIMCTXim(im);
524536
525537 /* round up to nearest multiple of four */
526538 line_size = (line_size + 3) / 4 * 4;
579591 int line_size = im->xsize;
580592 int y;
581593 int unpacked_size;
594 dIMCTXim(im);
582595
583596 /* round up to nearest multiple of four */
584597 line_size = (line_size + 3) / 4 * 4;
626639 int y;
627640 int line_size = 3 * im->xsize;
628641 i_color bg;
642 dIMCTXim(im);
629643
630644 i_get_file_background(im, &bg);
631645
680694 int i;
681695 i_packed_t r, g, b, x;
682696 i_color c;
697 dIMCTXio(ig);
683698
684699 for (i = 0; i < count; ++i) {
685700 if (!read_packed(ig, "CCCC", &b, &g, &r, &x)) {
718733 int bit;
719734 unsigned char *in;
720735 long base_offset;
736 dIMCTXio(ig);
721737
722738 if (compression != BI_RGB) {
723 i_push_errorf(0, "unknown 1-bit BMP compression (%d)", compression);
724 return NULL;
725 }
726
727 if (xsize + 8 < xsize) { /* if there was overflow */
739 im_push_errorf(aIMCTX, 0, "unknown 1-bit BMP compression (%d)", compression);
740 return NULL;
741 }
742
743 if ((i_img_dim)((i_img_dim_u)xsize + 8) < xsize) { /* if there was overflow */
728744 /* we check with 8 because we allocate that much for the decoded
729745 line buffer */
730746 i_push_error(0, "integer overflow during memory allocation");
751767 if (!clr_used)
752768 clr_used = 2;
753769 if (clr_used < 0 || clr_used > 2) {
754 i_push_errorf(0, "out of range colors used (%d)", clr_used);
770 im_push_errorf(aIMCTX, 0, "out of range colors used (%d)", clr_used);
755771 return NULL;
756772 }
757773
758774 base_offset = FILEHEAD_SIZE + INFOHEAD_SIZE + clr_used * 4;
759775 if (offbits < base_offset) {
760 i_push_errorf(0, "image data offset too small (%ld)", offbits);
776 im_push_errorf(aIMCTX, 0, "image data offset too small (%ld)", offbits);
761777 return NULL;
762778 }
763779
846862 int size, i;
847863 long base_offset;
848864 int starty;
865 dIMCTXio(ig);
849866
850867 /* line_size is going to be smaller than xsize in most cases (and
851868 when it's not, xsize is itself small), and hence not overflow */
868885 clr_used = 16;
869886
870887 if (clr_used > 16 || clr_used < 0) {
871 i_push_errorf(0, "out of range colors used (%d)", clr_used);
888 im_push_errorf(aIMCTX, 0, "out of range colors used (%d)", clr_used);
872889 return NULL;
873890 }
874891
875892 base_offset = FILEHEAD_SIZE + INFOHEAD_SIZE + clr_used * 4;
876893 if (offbits < base_offset) {
877 i_push_errorf(0, "image data offset too small (%ld)", offbits);
894 im_push_errorf(aIMCTX, 0, "image data offset too small (%ld)", offbits);
878895 return NULL;
879896 }
880897
966983 myfree(packed);
967984 myfree(line);
968985 i_push_error(0, "invalid data during decompression");
969 mm_log((1, "read 4-bit: scanline overflow x %d + count %d vs xlimit %d (y %d)\n",
986 im_log((aIMCTX, 1, "read 4-bit: scanline overflow x %d + count %d vs xlimit %d (y %d)\n",
970987 (int)x, count, (int)xlimit, (int)y));
971988 i_img_destroy(im);
972989 return NULL;
10161033 myfree(packed);
10171034 myfree(line);
10181035 i_push_error(0, "invalid data during decompression");
1019 mm_log((1, "read 4-bit: scanline overflow (unpacked) x %d + count %d vs xlimit %d (y %d)\n",
1036 im_log((aIMCTX, 1, "read 4-bit: scanline overflow (unpacked) x %d + count %d vs xlimit %d (y %d)\n",
10201037 (int)x, count, (int)xlimit, (int)y));
10211038 i_img_destroy(im);
10221039 return NULL;
10511068 else { /*if (compression == BI_RLE4) {*/
10521069 myfree(packed);
10531070 myfree(line);
1054 i_push_errorf(0, "unknown 4-bit BMP compression (%d)", compression);
1071 im_push_errorf(aIMCTX, 0, "unknown 4-bit BMP compression (%d)", compression);
10551072 i_img_destroy(im);
10561073 return NULL;
10571074 }
10761093 i_palidx *line;
10771094 int line_size = xsize;
10781095 long base_offset;
1096 dIMCTXio(ig);
10791097
10801098 line_size = (line_size+3) / 4 * 4;
10811099 if (line_size < xsize) { /* if it overflowed (unlikely, but check) */
10991117 if (!clr_used)
11001118 clr_used = 256;
11011119 if (clr_used > 256 || clr_used < 0) {
1102 i_push_errorf(0, "out of range colors used (%d)", clr_used);
1120 im_push_errorf(aIMCTX, 0, "out of range colors used (%d)", clr_used);
11031121 return NULL;
11041122 }
11051123
11061124 base_offset = FILEHEAD_SIZE + INFOHEAD_SIZE + clr_used * 4;
11071125 if (offbits < base_offset) {
1108 i_push_errorf(0, "image data offset too small (%ld)", offbits);
1126 im_push_errorf(aIMCTX, 0, "image data offset too small (%ld)", offbits);
11091127 return NULL;
11101128 }
11111129
12481266 }
12491267 else {
12501268 myfree(line);
1251 i_push_errorf(0, "unknown 8-bit BMP compression (%d)", compression);
1269 im_push_errorf(aIMCTX, 0, "unknown 8-bit BMP compression (%d)", compression);
12521270 i_img_destroy(im);
12531271 return NULL;
12541272 }
13211339 const char *compression_name;
13221340 int bytes;
13231341 long base_offset = FILEHEAD_SIZE + INFOHEAD_SIZE;
1342 dIMCTXio(ig);
13241343
13251344 unpack_code[0] = *("v3V"+pix_size-2);
13261345 unpack_code[1] = '\0';
13671386 return 0;
13681387 }
13691388 if (rmask == 0) {
1370 i_push_errorf(0, "Zero mask for channel %d", i);
1389 im_push_errorf(aIMCTX, 0, "Zero mask for channel %d", i);
13711390 return NULL;
13721391 }
13731392 masks.masks[i] = rmask;
13911410 base_offset += 3 * 4;
13921411 }
13931412 else {
1394 i_push_errorf(0, "unknown 24-bit BMP compression (%d)", compression);
1413 im_push_errorf(aIMCTX, 0, "unknown 24-bit BMP compression (%d)", compression);
13951414 return NULL;
13961415 }
13971416
13981417 if (offbits < base_offset) {
1399 i_push_errorf(0, "image data offset too small (%ld)", offbits);
1418 im_push_errorf(aIMCTX, 0, "image data offset too small (%ld)", offbits);
14001419 return NULL;
14011420 }
14021421
0 #include "imageri.h"
1 #include <stdio.h>
2
3 static volatile im_slot_t slot_count = 1;
4 static im_slot_destroy_t *volatile slot_destructors;
5 static volatile i_mutex_t slot_mutex;
6
7 /*
8 =item im_context_new()
9
10 Create a new Imager context object.
11
12 =cut
13 */
14
15 im_context_t
16 im_context_new(void) {
17 im_context_t ctx = malloc(sizeof(im_context_struct));
18 int i;
19
20 if (!slot_mutex)
21 slot_mutex = i_mutex_new();
22
23 if (!ctx)
24 return NULL;
25
26 ctx->error_sp = IM_ERROR_COUNT-1;
27 for (i = 0; i < IM_ERROR_COUNT; ++i) {
28 ctx->error_alloc[i] = 0;
29 ctx->error_stack[i].msg = NULL;
30 ctx->error_stack[i].code = 0;
31 }
32 #ifdef IMAGER_LOG
33 ctx->log_level = 0;
34 ctx->lg_file = NULL;
35 #endif
36 ctx->max_width = 0;
37 ctx->max_height = 0;
38 ctx->max_bytes = DEF_BYTES_LIMIT;
39
40 ctx->slot_alloc = slot_count;
41 ctx->slots = calloc(sizeof(void *), ctx->slot_alloc);
42 if (!ctx->slots) {
43 free(ctx);
44 return NULL;
45 }
46
47 ctx->refcount = 1;
48
49 #ifdef IMAGER_TRACE_CONTEXT
50 fprintf(stderr, "im_context: created %p\n", ctx);
51 #endif
52
53
54 return ctx;
55 }
56
57 /*
58 =item im_context_refinc(ctx, where)
59 X<im_context_refinc API>
60 =section Context objects
61 =synopsis im_context_refinc(aIMCTX, "a description");
62
63 Add a new reference to the context.
64
65 =cut
66 */
67
68 void
69 im_context_refinc(im_context_t ctx, const char *where) {
70 ++ctx->refcount;
71
72 #ifdef IMAGER_TRACE_CONTEXT
73 fprintf(stderr, "im_context:%s: refinc %p (count now %lu)\n", where,
74 ctx, (unsigned long)ctx->refcount);
75 #endif
76 }
77
78 /*
79 =item im_context_refdec(ctx, where)
80 X<im_context_refdec API>
81 =section Context objects
82 =synopsis im_context_refdec(aIMCTX, "a description");
83
84 Remove a reference to the context, releasing it if all references have
85 been removed.
86
87 =cut
88 */
89
90 void
91 im_context_refdec(im_context_t ctx, const char *where) {
92 int i;
93 im_slot_t slot;
94
95 im_assert(ctx->refcount > 0);
96
97 --ctx->refcount;
98
99 #ifdef IMAGER_TRACE_CONTEXT
100 fprintf(stderr, "im_context:%s: delete %p (count now %lu)\n", where,
101 ctx, (unsigned long)ctx->refcount);
102 #endif
103
104 if (ctx->refcount != 0)
105 return;
106
107 /* lock here to avoid slot_destructors from being moved under us */
108 i_mutex_lock(slot_mutex);
109 for (slot = 0; slot < ctx->slot_alloc; ++slot) {
110 if (ctx->slots[slot] && slot_destructors[slot])
111 slot_destructors[slot](ctx->slots[slot]);
112 }
113 i_mutex_unlock(slot_mutex);
114
115 free(ctx->slots);
116
117 for (i = 0; i < IM_ERROR_COUNT; ++i) {
118 if (ctx->error_stack[i].msg)
119 myfree(ctx->error_stack[i].msg);
120 }
121 #ifdef IMAGER_LOG
122 if (ctx->lg_file && ctx->own_log)
123 fclose(ctx->lg_file);
124 #endif
125
126 free(ctx);
127 }
128
129 /*
130 =item im_context_clone(ctx)
131
132 Clone an Imager context object, returning the result.
133
134 The error stack is not copied from the original context.
135
136 =cut
137 */
138
139 im_context_t
140 im_context_clone(im_context_t ctx, const char *where) {
141 im_context_t nctx = malloc(sizeof(im_context_struct));
142 int i;
143
144 if (!nctx)
145 return NULL;
146
147 nctx->slot_alloc = slot_count;
148 nctx->slots = calloc(sizeof(void *), nctx->slot_alloc);
149 if (!nctx->slots) {
150 free(nctx);
151 return NULL;
152 }
153
154 nctx->error_sp = IM_ERROR_COUNT-1;
155 for (i = 0; i < IM_ERROR_COUNT; ++i) {
156 nctx->error_alloc[i] = 0;
157 nctx->error_stack[i].msg = NULL;
158 }
159 #ifdef IMAGER_LOG
160 nctx->log_level = ctx->log_level;
161 if (ctx->lg_file) {
162 if (ctx->own_log) {
163 int newfd = dup(fileno(ctx->lg_file));
164 nctx->own_log = 1;
165 nctx->lg_file = fdopen(newfd, "w");
166 if (nctx->lg_file)
167 setvbuf(nctx->lg_file, NULL, _IONBF, BUFSIZ);
168 }
169 else {
170 /* stderr */
171 nctx->lg_file = ctx->lg_file;
172 nctx->own_log = 0;
173 }
174 }
175 else {
176 nctx->lg_file = NULL;
177 }
178 #endif
179 nctx->max_width = ctx->max_width;
180 nctx->max_height = ctx->max_height;
181 nctx->max_bytes = ctx->max_bytes;
182
183 nctx->refcount = 1;
184
185 #ifdef IMAGER_TRACE_CONTEXT
186 fprintf(stderr, "im_context:%s: cloned %p to %p\n", where, ctx, nctx);
187 #endif
188
189 return nctx;
190 }
191
192 /*
193 =item im_context_slot_new(destructor)
194
195 Allocate a new context-local-storage slot.
196
197 C<desctructor> will be called when the context is destroyed if the
198 corresponding slot is non-NULL.
199
200 =cut
201 */
202
203 im_slot_t
204 im_context_slot_new(im_slot_destroy_t destructor) {
205 im_slot_t new_slot;
206 im_slot_destroy_t *new_destructors;
207 if (!slot_mutex)
208 slot_mutex = i_mutex_new();
209
210 i_mutex_lock(slot_mutex);
211
212 new_slot = slot_count++;
213 new_destructors = realloc(slot_destructors, sizeof(void *) * slot_count);
214 if (!new_destructors)
215 i_fatal(1, "Cannot allocate memory for slot destructors");
216 slot_destructors = new_destructors;
217
218 slot_destructors[new_slot] = destructor;
219
220 i_mutex_unlock(slot_mutex);
221
222 return new_slot;
223 }
224
225 /*
226 =item im_context_slot_set(slot, value)
227
228 Set the value of a slot.
229
230 Returns true on success.
231
232 Aborts if the slot supplied is invalid.
233
234 If reallocation of slot storage fails, returns false.
235
236 =cut
237 */
238
239 int
240 im_context_slot_set(im_context_t ctx, im_slot_t slot, void *value) {
241 if (slot < 0 || slot >= slot_count) {
242 fprintf(stderr, "Invalid slot %d (valid 0 - %d)\n",
243 (int)slot, (int)slot_count-1);
244 abort();
245 }
246
247 if (slot >= ctx->slot_alloc) {
248 ssize_t i;
249 size_t new_alloc = slot_count;
250 void **new_slots = realloc(ctx->slots, sizeof(void *) * new_alloc);
251
252 if (!new_slots)
253 return 0;
254
255 for (i = ctx->slot_alloc; i < new_alloc; ++i)
256 new_slots[i] = NULL;
257
258 ctx->slots = new_slots;
259 ctx->slot_alloc = new_alloc;
260 }
261
262 ctx->slots[slot] = value;
263
264 return 1;
265 }
266
267 /*
268 =item im_context_slot_get(ctx, slot)
269
270 Retrieve the value previously stored in the given slot of the context
271 object.
272
273 =cut
274 */
275
276 void *
277 im_context_slot_get(im_context_t ctx, im_slot_t slot) {
278 if (slot < 0 || slot >= slot_count) {
279 fprintf(stderr, "Invalid slot %d (valid 0 - %d)\n",
280 (int)slot, (int)slot_count-1);
281 abort();
282 }
283
284 if (slot >= ctx->slot_alloc)
285 return NULL;
286
287 return ctx->slots[slot];
288 }
0 #define IMAGER_NO_CONTEXT
01 #include "imager.h"
12 #include "imageri.h"
23
1819 double pc;
1920 double res[MAXCHANNELS];
2021 i_img *timg;
22 dIMCTXim(im);
2123
22 mm_log((1,"i_conv(im %p, coeff %p, len %d)\n",im,coeff,len));
23 i_clear_error();
24 im_log((aIMCTX,1,"i_conv(im %p, coeff %p, len %d)\n",im,coeff,len));
25 im_clear_error(aIMCTX);
2426
2527 if (len < 1) {
26 i_push_error(0, "there must be at least one coefficient");
28 im_push_error(aIMCTX, 0, "there must be at least one coefficient");
2729 return 0;
2830 }
2931
1616 =cut
1717 */
1818
19 #define IMAGER_NO_CONTEXT
1920 #include "imager.h"
2021
2122 struct chan_copy {
6869 int i, j;
6970 int ilimit;
7071 i_img *im = NULL;
71
72 mm_log((1,"i_convert(im %p, src %p, coeff %p,outchan %d, inchan %d)\n",
72 dIMCTXim(src);
73
74 im_log((aIMCTX,1,"i_convert(im %p, src %p, coeff %p,outchan %d, inchan %d)\n",
7375 im, src, coeff, outchan, inchan));
7476
75 i_clear_error();
77 im_clear_error(aIMCTX);
7678
7779 ilimit = inchan;
7880 if (ilimit > src->channels)
7981 ilimit = src->channels;
8082 if (outchan > MAXCHANNELS) {
81 i_push_error(0, "cannot have outchan > MAXCHANNELS");
83 im_push_error(aIMCTX, 0, "cannot have outchan > MAXCHANNELS");
8284 return 0;
8385 }
8486
129131 i_color *colors;
130132 i_palidx *vals;
131133
132 im = i_img_pal_new(src->xsize, src->ysize, outchan,
133 i_maxcolors(src));
134 im = im_img_pal_new(aIMCTX, src->xsize, src->ysize, outchan,
135 i_maxcolors(src));
134136
135137 /* just translate the color table */
136138 count = i_colorcount(src);
00 #include <stdlib.h>
11 #include <stdio.h>
22 #include <string.h>
3 #define IMAGER_NO_CONTEXT
34 #include "imager.h"
45
56 /*
128129 }
129130 }
130131 /* fprintf(stderr,"0x%08X\n",l->t); */
131 if (llist_llink_push(l,l->t,data)) {
132 i_fatal(3, "out of memory\n");
132 if (llist_llink_push(l,l->t,data)) {
133 dIMCTX;
134 im_fatal(aIMCTX, 3, "out of memory\n");
133135 }
134136 }
135137
0 #define IMAGER_NO_CONTEXT
01 #include "imager.h"
12 #include "draw.h"
23 #include "log.h"
235236 void
236237 i_arc(i_img *im, i_img_dim x, i_img_dim y,double rad,double d1,double d2,const i_color *val) {
237238 i_int_hlines hlines;
239 dIMCTXim(im);
240
241 im_log((aIMCTX,1,"i_arc(im %p,(x,y)=(" i_DFp "), rad %f, d1 %f, d2 %f, col %p)",
242 im, i_DFcp(x, y), rad, d1, d2, val));
238243
239244 i_int_init_hlines_img(&hlines, im);
240245
263268 void
264269 i_arc_cfill(i_img *im, i_img_dim x, i_img_dim y,double rad,double d1,double d2,i_fill_t *fill) {
265270 i_int_hlines hlines;
271 dIMCTXim(im);
272
273 im_log((aIMCTX,1,"i_arc_cfill(im %p,(x,y)=(" i_DFp "), rad %f, d1 %f, d2 %f, fill %p)",
274 im, i_DFcp(x, y), rad, d1, d2, fill));
266275
267276 i_int_init_hlines_img(&hlines, im);
268277
362371 const i_color *val) {
363372 double *xvals, *yvals;
364373 int count;
374 dIMCTXim(im);
375
376 im_log((aIMCTX,1,"i_arc_aa(im %p,(x,y)=(%f,%f), rad %f, d1 %f, d2 %f, col %p)",
377 im, x, y, rad, d1, d2, val));
365378
366379 arc_poly(&count, &xvals, &yvals, x, y, rad, d1, d2);
367380
388401 i_fill_t *fill) {
389402 double *xvals, *yvals;
390403 int count;
404 dIMCTXim(im);
405
406 im_log((aIMCTX,1,"i_arc_aa_cfill(im %p,(x,y)=(%f,%f), rad %f, d1 %f, d2 %f, fill %p)",
407 im, x, y, rad, d1, d2, fill));
391408
392409 arc_poly(&count, &xvals, &yvals, x, y, rad, d1, d2);
393410
412429
413430 static
414431 void
415 make_minmax_list(i_mmarray *dot, double x, double y, double radius) {
432 make_minmax_list(pIMCTX, i_mmarray *dot, double x, double y, double radius) {
416433 float angle = 0.0;
417434 float astep = radius>0.1 ? .5/radius : 10;
418435 frac cx, cy, lx, ly, sx, sy;
419436
420 mm_log((1, "make_minmax_list(dot %p, x %.2f, y %.2f, radius %.2f)\n", dot, x, y, radius));
437 im_log((aIMCTX, 1, "make_minmax_list(dot %p, x %.2f, y %.2f, radius %.2f)\n", dot, x, y, radius));
421438
422439 polar_to_plane(x, y, angle, radius, &sx, &sy);
423440
493510 i_mmarray dot;
494511 i_color temp;
495512 i_img_dim ly;
496
497 mm_log((1, "i_circle_aa(im %p, centre(" i_DFp "), rad %.2f, val %p)\n",
513 dIMCTXim(im);
514
515 im_log((aIMCTX, 1, "i_circle_aa(im %p, centre(" i_DFp "), rad %.2f, val %p)\n",
498516 im, i_DFcp(x, y), rad, val));
499517
500518 i_mmarray_cr(&dot,16*im->ysize);
501 make_minmax_list(&dot, x, y, rad);
519 make_minmax_list(aIMCTX, &dot, x, y, rad);
502520
503521 for(ly = 0; ly<im->ysize; ly++) {
504522 int ix, cy, minx = INT_MAX, maxx = INT_MIN;
568586 i_img_dim x, y;
569587 i_img_dim dx, dy;
570588 int error;
571
572 i_clear_error();
589 dIMCTXim(im);
590
591 im_log((aIMCTX, 1, "i_circle_out(im %p, centre(" i_DFp "), rad %" i_DF ", col %p)\n",
592 im, i_DFcp(xc, yc), i_DFc(r), col));
593
594 im_clear_error(aIMCTX);
573595
574596 if (r < 0) {
575 i_push_error(0, "circle: radius must be non-negative");
597 im_push_error(aIMCTX, 0, "circle: radius must be non-negative");
576598 return 0;
577599 }
578600
683705 i_img_dim seg2 = scale * 4;
684706 i_img_dim seg3 = scale * 6;
685707 i_img_dim seg4 = scale * 8;
686
687 i_clear_error();
708 dIMCTXim(im);
709
710 im_log((aIMCTX,1,"i_arc_out(im %p,centre(" i_DFp "), rad %" i_DF ", d1 %f, d2 %f, col %p)",
711 im, i_DFcp(xc, yc), i_DFc(r), d1, d2, col));
712
713 im_clear_error(aIMCTX);
688714
689715 if (r <= 0) {
690 i_push_error(0, "arc: radius must be non-negative");
716 im_push_error(aIMCTX, 0, "arc: radius must be non-negative");
691717 return 0;
692718 }
693719 if (d1 + 360 <= d2)
819845 double t;
820846 i_color workc = *col;
821847 int orig_alpha = col->channel[3];
822
823 i_clear_error();
848 dIMCTXim(im);
849
850 im_log((aIMCTX,1,"i_circle_out_aa(im %p,centre(" i_DFp "), rad %" i_DF ", col %p)",
851 im, i_DFcp(xc, yc), i_DFc(r), col));
852
853 im_clear_error(aIMCTX);
824854 if (r <= 0) {
825 i_push_error(0, "arc: radius must be non-negative");
855 im_push_error(aIMCTX, 0, "arc: radius must be non-negative");
826856 return 0;
827857 }
828858 i = r;
929959 i_img_dim seg2 = scale * 4;
930960 i_img_dim seg3 = scale * 6;
931961 i_img_dim seg4 = scale * 8;
932
933 i_clear_error();
962 dIMCTXim(im);
963
964 im_log((aIMCTX,1,"i_arc_out_aa(im %p,centre(" i_DFp "), rad %" i_DF ", d1 %f, d2 %f, col %p)",
965 im, i_DFcp(xc, yc), i_DFc(r), d1, d2, col));
966
967 im_clear_error(aIMCTX);
934968 if (r <= 0) {
935 i_push_error(0, "arc: radius must be non-negative");
969 im_push_error(aIMCTX, 0, "arc: radius must be non-negative");
936970 return 0;
937971 }
938972 if (d1 + 360 <= d2)
10521086 void
10531087 i_box(i_img *im,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img_dim y2,const i_color *val) {
10541088 i_img_dim x,y;
1055 mm_log((1,"i_box(im* %p, p1(" i_DFp "), p2(" i_DFp "),val %p)\n",
1089 dIMCTXim(im);
1090
1091 im_log((aIMCTX, 1,"i_box(im* %p, p1(" i_DFp "), p2(" i_DFp "),val %p)\n",
10561092 im, i_DFcp(x1,y1), i_DFcp(x2,y2), val));
10571093 for(x=x1;x<x2+1;x++) {
10581094 i_ppix(im,x,y1,val);
10791115 i_box_filled(i_img *im,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img_dim y2, const i_color *val) {
10801116 i_img_dim x, y, width;
10811117 i_palidx index;
1082
1083 mm_log((1,"i_box_filled(im* %p, p1(" i_DFp "), p2(" i_DFp "),val %p)\n",
1118 dIMCTXim(im);
1119
1120 im_log((aIMCTX,1,"i_box_filled(im* %p, p1(" i_DFp "), p2(" i_DFp "),val %p)\n",
10841121 im, i_DFcp(x1, y1), i_DFcp(x2,y2) ,val));
10851122
10861123 if (x1 > x2 || y1 > y2
11391176 int
11401177 i_box_filledf(i_img *im,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img_dim y2, const i_fcolor *val) {
11411178 i_img_dim x, y, width;
1142
1143 mm_log((1,"i_box_filledf(im* %p, p1(" i_DFp "), p2(" i_DFp "),val %p)\n",
1179 dIMCTXim(im);
1180
1181 im_log((aIMCTX, 1,"i_box_filledf(im* %p, p1(" i_DFp "), p2(" i_DFp "),val %p)\n",
11441182 im, i_DFcp(x1, y1), i_DFcp(x2, y2), val));
11451183
11461184 if (x1 > x2 || y1 > y2
11971235 void
11981236 i_box_cfill(i_img *im,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img_dim y2,i_fill_t *fill) {
11991237 i_render r;
1200
1201 mm_log((1,"i_box_cfill(im* %p, p1(" i_DFp "), p2(" i_DFp "), fill %p)\n",
1238 dIMCTXim(im);
1239
1240 im_log((aIMCTX,1,"i_box_cfill(im* %p, p1(" i_DFp "), p2(" i_DFp "), fill %p)\n",
12021241 im, i_DFcp(x1, y1), i_DFcp(x2,y2), fill));
12031242
12041243 ++x2;
18151854 struct i_bitmap *btm;
18161855 i_img_dim x, y;
18171856 i_color val;
1818
1819 i_clear_error();
1857 dIMCTXim(im);
1858
1859 im_log((aIMCTX, 1, "i_flood_fill(im %p, seed(" i_DFp "), col %p)",
1860 im, i_DFcp(seedx, seedy), dcol));
1861
1862 im_clear_error(aIMCTX);
18201863 if (seedx < 0 || seedx >= im->xsize ||
18211864 seedy < 0 || seedy >= im->ysize) {
1822 i_push_error(0, "i_flood_cfill: Seed pixel outside of image");
1865 im_push_error(aIMCTX, 0, "i_flood_cfill: Seed pixel outside of image");
18231866 return 0;
18241867 }
18251868
18561899 i_img_dim bxmin, bxmax, bymin, bymax;
18571900 struct i_bitmap *btm;
18581901 i_color val;
1859
1860 i_clear_error();
1902 dIMCTXim(im);
1903
1904 im_log((aIMCTX, 1, "i_flood_cfill(im %p, seed(" i_DFp "), fill %p)",
1905 im, i_DFcp(seedx, seedy), fill));
1906
1907 im_clear_error(aIMCTX);
18611908
18621909 if (seedx < 0 || seedx >= im->xsize ||
18631910 seedy < 0 || seedy >= im->ysize) {
1864 i_push_error(0, "i_flood_cfill: Seed pixel outside of image");
1911 im_push_error(aIMCTX, 0, "i_flood_cfill: Seed pixel outside of image");
18651912 return 0;
18661913 }
18671914
18981945 i_img_dim bxmin, bxmax, bymin, bymax;
18991946 struct i_bitmap *btm;
19001947 i_img_dim x, y;
1901
1902 i_clear_error();
1948 dIMCTXim(im);
1949
1950 im_log((aIMCTX, 1, "i_flood_cfill(im %p, seed(" i_DFp "), dcol %p, border %p)",
1951 im, i_DFcp(seedx, seedy), dcol, border));
1952
1953 im_clear_error(aIMCTX);
19031954 if (seedx < 0 || seedx >= im->xsize ||
19041955 seedy < 0 || seedy >= im->ysize) {
1905 i_push_error(0, "i_flood_cfill: Seed pixel outside of image");
1956 im_push_error(aIMCTX, 0, "i_flood_cfill: Seed pixel outside of image");
19061957 return 0;
19071958 }
19081959
19371988 const i_color *border) {
19381989 i_img_dim bxmin, bxmax, bymin, bymax;
19391990 struct i_bitmap *btm;
1940
1941 i_clear_error();
1991 dIMCTXim(im);
1992
1993 im_log((aIMCTX, 1, "i_flood_cfill_border(im %p, seed(" i_DFp "), fill %p, border %p)",
1994 im, i_DFcp(seedx, seedy), fill, border));
1995
1996 im_clear_error(aIMCTX);
19421997
19431998 if (seedx < 0 || seedx >= im->xsize ||
19441999 seedy < 0 || seedy >= im->ysize) {
1945 i_push_error(0, "i_flood_cfill_border: Seed pixel outside of image");
2000 im_push_error(aIMCTX, 0, "i_flood_cfill_border: Seed pixel outside of image");
19462001 return 0;
19472002 }
19482003
1010 typedef void *minthandle_t;
1111 #endif
1212
13 #include "plug.h"
13 #include "ext.h"
1414
1515 struct DSO_handle_tag {
1616 minthandle_t handle;
2222 #include "dynaload.h"
2323 /* #include "XSUB.h" so we can compile on threaded perls */
2424 #include "imageri.h"
25
26 static im_context_t
27 do_get_context(void) {
28 return im_get_context();
29 }
2530
2631 static symbol_table_t symbol_table=
2732 {
2833 i_has_format,
2934 ICL_set_internal,
3035 ICL_info,
31 i_img_new,
32 i_img_empty,
33 i_img_empty_ch,
36 do_get_context,
37 im_img_empty_ch,
3438 i_img_exorcise,
3539 i_img_info,
3640 i_img_setmask,
4040 rcomm('rm testout/*');
4141 rcomm(@precommands);
4242 my $make = $Config{make};
43 rcomm("$^X Makefile.PL") || rcomm("$make") || rcomm("$make test TEST_VERBOSE=1");
43 rcomm("$^X Makefile.PL --verbose") || rcomm("$make") || rcomm("$make test TEST_VERBOSE=1");
4444 head("Logfiles from run");
4545 dumplogs();
4646
6060 =cut
6161 */
6262
63 #include "imager.h"
63 #include "imageri.h"
6464 #include <stdio.h>
6565 #include <stdlib.h>
6666
67 /* we never actually use the last item - it's the NULL terminator */
68 #define ERRSTK 20
69 static i_errmsg error_stack[ERRSTK];
70 static int error_sp = ERRSTK - 1;
71 /* we track the amount of space used each string, so we don't reallocate
72 space unless we need to.
73 This also means that a memory tracking library may see the memory
74 allocated for this as a leak. */
75 static int error_space[ERRSTK];
76
77 static i_error_cb error_cb;
78 static i_failed_cb failed_cb;
79 static int failures_fatal;
80 static char *argv0;
81
82 /*
83 =item i_set_argv0(char const *program)
84
85 Sets the name of the program to be displayed in fatal error messages.
86
87 The simplest way to use this is just:
88
89 i_set_argv0(argv[0]);
90
91 when your program starts.
92 */
93 void i_set_argv0(char const *name) {
94 char *dupl;
95 if (!name)
96 return;
97 /* if the user has an existing string of MAXINT length then
98 the system is broken anyway */
99 dupl = mymalloc(strlen(name)+1); /* check 17jul05 tonyc */
100 strcpy(dupl, name);
101 if (argv0)
102 myfree(argv0);
103 argv0 = dupl;
104 }
105
106 /*
107 =item i_set_failure_fatal(int failure_fatal)
108
109 If failure_fatal is non-zero then any future failures will result in
110 Imager exiting your program with a message describing the failure.
111
112 Returns the previous setting.
113
114 =cut
115 */
116 int i_set_failures_fatal(int fatal) {
117 int old = failures_fatal;
118 failures_fatal = fatal;
119
120 return old;
121 }
122
123 /*
124 =item i_set_error_cb(i_error_cb)
125
126 Sets a callback function that is called each time an error is pushed
127 onto the error stack.
128
129 Returns the previous callback.
130
131 i_set_failed_cb() is probably more useful.
132
133 =cut
134 */
135 i_error_cb i_set_error_cb(i_error_cb cb) {
136 i_error_cb old = error_cb;
137 error_cb = cb;
138
139 return old;
140 }
141
142 /*
143 =item i_set_failed_cb(i_failed_cb cb)
144
145 Sets a callback function that is called each time an Imager function
146 fails.
147
148 Returns the previous callback.
149
150 =cut
151 */
152 i_failed_cb i_set_failed_cb(i_failed_cb cb) {
153 i_failed_cb old = failed_cb;
154 failed_cb = cb;
155
156 return old;
157 }
158
159 /*
160 =item i_errors()
67 /*
68 =item im_errors(ctx)
69 =synopsis i_errmsg *errors = im_errors(aIMCTX);
70 =synopsis i_errmsg *errors = i_errors();
16171
16272 Returns a pointer to the first element of an array of error messages,
16373 terminated by a NULL pointer. The highest level message is first.
16474
165 =cut
166 */
167 i_errmsg *i_errors() {
168 return error_stack + error_sp;
75 Also callable as C<i_errors()>.
76
77 =cut
78 */
79 i_errmsg *im_errors(im_context_t ctx) {
80 return ctx->error_stack + ctx->error_sp;
16981 }
17082
17183 /*
18193
18294 =over
18395
184 =item i_clear_error()
96 =item im_clear_error(ctx)
97 X<im_clear_error API>X<i_clear_error API>
98 =synopsis im_clear_error(aIMCTX);
18599 =synopsis i_clear_error();
186100 =category Error handling
187101
189103
190104 Called by any Imager function before doing any other processing.
191105
192 =cut
193 */
194 void i_clear_error() {
106 Also callable as C<i_clear_error()>.
107
108 =cut
109 */
110
111 void
112 im_clear_error(im_context_t ctx) {
195113 #ifdef IMAGER_DEBUG_MALLOC
196114 int i;
197115
198 for (i = 0; i < ERRSTK; ++i) {
199 if (error_space[i]) {
200 myfree(error_stack[i].msg);
201 error_stack[i].msg = NULL;
202 error_space[i] = 0;
116 for (i = 0; i < IM_ERROR_COUNT; ++i) {
117 if (ctx->error_space[i]) {
118 myfree(ctx->error_stack[i].msg);
119 ctx->error_stack[i].msg = NULL;
120 ctx->error_space[i] = 0;
203121 }
204122 }
205123 #endif
206 error_sp = ERRSTK-1;
207 }
208
209 /*
210 =item i_push_error(int code, char const *msg)
124 ctx->error_sp = IM_ERROR_COUNT-1;
125 }
126
127 /*
128 =item im_push_error(ctx, code, message)
129 X<im_push_error API>X<i_push_error API>
211130 =synopsis i_push_error(0, "Yep, it's broken");
212131 =synopsis i_push_error(errno, "Error writing");
132 =synopsis im_push_error(aIMCTX, 0, "Something is wrong");
213133 =category Error handling
214134
215135 Called by an Imager function to push an error message onto the stack.
220140
221141 =cut
222142 */
223 void i_push_error(int code, char const *msg) {
143 void
144 im_push_error(im_context_t ctx, int code, char const *msg) {
224145 size_t size = strlen(msg)+1;
225146
226 if (error_sp <= 0)
147 if (ctx->error_sp <= 0)
227148 /* bad, bad programmer */
228149 return;
229150
230 --error_sp;
231 if (error_space[error_sp] < size) {
232 if (error_stack[error_sp].msg)
233 myfree(error_stack[error_sp].msg);
151 --ctx->error_sp;
152 if (ctx->error_alloc[ctx->error_sp] < size) {
153 if (ctx->error_stack[ctx->error_sp].msg)
154 myfree(ctx->error_stack[ctx->error_sp].msg);
234155 /* memory allocated on the following line is only ever released when
235156 we need a bigger string */
236157 /* size is size (len+1) of an existing string, overflow would mean
237158 the system is broken anyway */
238 error_stack[error_sp].msg = mymalloc(size); /* checked 17jul05 tonyc */
239 error_space[error_sp] = size;
240 }
241 strcpy(error_stack[error_sp].msg, msg);
242 error_stack[error_sp].code = code;
243
244 if (error_cb)
245 error_cb(code, msg);
246 }
247
248 /*
249 =item i_push_errorvf(int C<code>, char const *C<fmt>, va_list C<ap>)
250
159 ctx->error_stack[ctx->error_sp].msg = mymalloc(size); /* checked 17jul05 tonyc */
160 ctx->error_alloc[ctx->error_sp] = size;
161 }
162 strcpy(ctx->error_stack[ctx->error_sp].msg, msg);
163 ctx->error_stack[ctx->error_sp].code = code;
164 }
165
166 /*
167 =item im_push_errorvf(ctx, code, format, args)
168 X<im_push_error_vf API>X<i_push_errorvf API>
169 =synopsis va_args args;
170 =synopsis va_start(args, lastarg);
171 =synopsis im_push_errorvf(ctx, code, format, args);
251172 =category Error handling
252173
253174 Intended for use by higher level functions, takes a varargs pointer
255176
256177 Does not support perl specific format codes.
257178
258 =cut
259 */
260 void i_push_errorvf(int code, char const *fmt, va_list ap) {
179 Also callable as C<i_push_errorvf(code, format, args)>
180
181 =cut
182 */
183 void
184 im_push_errorvf(im_context_t ctx, int code, char const *fmt, va_list ap) {
261185 char buf[1024];
262186 #if defined(IMAGER_VSNPRINTF)
263187 vsnprintf(buf, sizeof(buf), fmt, ap);
270194 */
271195 vsprintf(buf, fmt, ap);
272196 #endif
273 i_push_error(code, buf);
197 im_push_error(ctx, code, buf);
274198 }
275199
276200 /*
284208
285209 =cut
286210 */
287 void i_push_errorf(int code, char const *fmt, ...) {
211 void
212 i_push_errorf(int code, char const *fmt, ...) {
288213 va_list ap;
289214 va_start(ap, fmt);
290215 i_push_errorvf(code, fmt, ap);
216 va_end(ap);
217 }
218
219 /*
220 =item im_push_errorf(ctx, code, char const *fmt, ...)
221 =synopsis im_push_errorf(aIMCTX, errno, "Cannot open file %s: %d", filename, errno);
222 =category Error handling
223
224 A version of im_push_error() that does printf() like formatting.
225
226 Does not support perl specific format codes.
227
228 =cut
229 */
230 void
231 im_push_errorf(im_context_t ctx, int code, char const *fmt, ...) {
232 va_list ap;
233 va_start(ap, fmt);
234 im_push_errorvf(ctx, code, fmt, ap);
291235 va_end(ap);
292236 }
293237
356300
357301 #endif
358302
303 #ifdef IM_ASSERT
304
359305 /*
360306 =item im_assert_fail(file, line, message)
361307
362308 Called when an im_assert() assertion fails.
309
310 Only available when Imager is built with assertions.
363311
364312 =cut
365313 */
368316 im_assert_fail(char const *file, int line, char const *message) {
369317 fprintf(stderr, "Assertion failed line %d file %s: %s\n",
370318 line, file, message);
371 exit(EXIT_FAILURE);
372 }
319 abort();
320 }
321
322 #endif
373323
374324 /*
375325 =back
0 #include "imager.h"
0 #include "imdatatypes.h"
11
22 #ifndef IMAGER_EXT_H
33 #define IMAGER_EXT_H
1919 int (*getobj)(void *hv_t,char* key,char* type,void **store);
2020 } UTIL_table_t;
2121
22 typedef struct {
23 undef_int (*i_has_format)(char *frmt);
24 i_color*(*ICL_set)(i_color *cl,unsigned char r,unsigned char g,unsigned char b,unsigned char a);
25 void (*ICL_info)(const i_color *cl);
26
27 im_context_t (*im_get_context_f)(void);
28 i_img*(*im_img_empty_ch_f)(im_context_t, i_img *im,i_img_dim x,i_img_dim y,int ch);
29 void(*i_img_exorcise_f)(i_img *im);
30
31 void(*i_img_info_f)(i_img *im,i_img_dim *info);
32
33 void(*i_img_setmask_f)(i_img *im,int ch_mask);
34 int (*i_img_getmask_f)(i_img *im);
35
36 /*
37 int (*i_ppix)(i_img *im,i_img_dim x,i_img_dim y,i_color *val);
38 int (*i_gpix)(i_img *im,i_img_dim x,i_img_dim y,i_color *val);
39 */
40 void(*i_box)(i_img *im,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img_dim y2,const i_color *val);
41 void(*i_line)(i_img *im,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img_dim y2,const i_color *val,int endp);
42 void(*i_arc)(i_img *im,i_img_dim x,i_img_dim y,double rad,double d1,double d2,const i_color *val);
43 void(*i_copyto)(i_img *im,i_img *src,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img_dim y2,i_img_dim tx,i_img_dim ty);
44 void(*i_copyto_trans)(i_img *im,i_img *src,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img_dim y2,i_img_dim tx,i_img_dim ty,const i_color *trans);
45 int(*i_rubthru)(i_img *im,i_img *src,i_img_dim tx,i_img_dim ty, i_img_dim src_minx, i_img_dim src_miny, i_img_dim src_maxx, i_img_dim src_maxy);
46
47 } symbol_table_t;
48
2249 #endif
0 #define IMAGER_NO_CONTEXT
01 #include "imager.h"
12 #include "imageri.h"
23
855856 }
856857 else if (f->yoff) {
857858 ry += ix * f->yoff;
858 iy = ry / f->src->xsize;
859 iy = ry / f->src->ysize;
859860 }
860861 rx -= ix * f->src->xsize;
861862 ry -= iy * f->src->ysize;
0 #define IMAGER_NO_CONTEXT
01 #include "imager.h"
12 #include "imageri.h"
23 #include <stdlib.h>
7273 unsigned char ch;
7374 unsigned int new_color;
7475 i_color rcolor;
75
76 mm_log((1,"i_contrast(im %p, intensity %f)\n", im, intensity));
76 dIMCTXim(im);
77
78 im_log((aIMCTX, 1,"i_contrast(im %p, intensity %f)\n", im, intensity));
7779
7880 if(intensity < 0) return;
7981
99101 i_img_dim x, y;
100102 int ch;
101103 int invert_channels = all ? im->channels : i_img_color_channels(im);
102
103 mm_log((1,"i_hardinvert(im %p)\n", im));
104 dIMCTXim(im);
105
106 im_log((aIMCTX,1,"i_hardinvert)low(im %p, all %d)\n", im, all));
104107
105108 #code im->bits <= 8
106109 IM_COLOR *row, *entry;
183186 float damount = amount * 2;
184187 i_color rcolor;
185188 int color_inc = 0;
186
187 mm_log((1,"i_noise(im %p, intensity %.2f\n", im, amount));
189 dIMCTXim(im);
190
191 im_log((aIMCTX, 1,"i_noise(im %p, intensity %.2f\n", im, amount));
188192
189193 if(amount < 0) return;
190194
244248 double aX, aY, aL;
245249 double fZ;
246250 unsigned char px1, px2, py1, py2;
247
251 dIMCTXim(im);
248252 i_img new_im;
249253
250 mm_log((1, "i_bumpmap(im %p, add_im %p, channel %d, light(" i_DFp "), st %" i_DF ")\n",
254 im_log((aIMCTX, 1, "i_bumpmap(im %p, add_im %p, channel %d, light(" i_DFp "), st %" i_DF ")\n",
251255 im, bump, channel, i_DFcp(light_x, light_y), i_DFc(st)));
252256
253257
254258 if(channel >= bump->channels) {
255 mm_log((1, "i_bumpmap: channel = %d while bump image only has %d channels\n", channel, bump->channels));
259 im_log((aIMCTX, 1, "i_bumpmap: channel = %d while bump image only has %d channels\n", channel, bump->channels));
256260 return;
257261 }
258262
426430 fvec R; /* Reflection vector */
427431 fvec V; /* Vision vector */
428432
429 mm_log((1, "i_bumpmap_complex(im %p, bump %p, channel %d, t(" i_DFp
433 dIMCTXim(im);
434
435 im_log((aIMCTX, 1, "i_bumpmap_complex(im %p, bump %p, channel %d, t(" i_DFp
430436 "), Lx %.2f, Ly %.2f, Lz %.2f, cd %.2f, cs %.2f, n %.2f, Ia %p, Il %p, Is %p)\n",
431437 im, bump, channel, i_DFcp(tx, ty), Lx, Ly, Lz, cd, cs, n, Ia, Il, Is));
432438
433439 if (channel >= bump->channels) {
434 mm_log((1, "i_bumpmap_complex: channel = %d while bump image only has %d channels\n", channel, bump->channels));
440 im_log((aIMCTX, 1, "i_bumpmap_complex: channel = %d while bump image only has %d channels\n", channel, bump->channels));
435441 return;
436442 }
437443
667673 i_img_dim gsum, gmin, gmax;
668674 i_img_dim bsum, bmin, bmax;
669675 i_img_dim rcl, rcu, gcl, gcu, bcl, bcu;
670
671 mm_log((1,"i_autolevels(im %p, lsat %f,usat %f,skew %f)\n", im, lsat,usat,skew));
676 dIMCTXim(im);
677
678 im_log((aIMCTX, 1,"i_autolevels(im %p, lsat %f,usat %f,skew %f)\n", im, lsat,usat,skew));
672679
673680 rsum=gsum=bsum=0;
674681 for(i=0;i<256;i++) rhist[i]=ghist[i]=bhist[i] = 0;
923930 size_t bytes;
924931
925932 double *fdist;
926
927 mm_log((1,"i_gradgen(im %p, num %d, xo %p, yo %p, ival %p, dmeasure %d)\n", im, num, xo, yo, ival, dmeasure));
933 dIMCTXim(im);
934
935 im_log((aIMCTX, 1,"i_gradgen(im %p, num %d, xo %p, yo %p, ival %p, dmeasure %d)\n", im, num, xo, yo, ival, dmeasure));
928936
929937 for(p = 0; p<num; p++) {
930 mm_log((1,"i_gradgen: p%d(" i_DFp ")\n", p, i_DFcp(xo[p], yo[p])));
938 im_log((aIMCTX,1,"i_gradgen: p%d(" i_DFp ")\n", p, i_DFcp(xo[p], yo[p])));
931939 ICL_info(&ival[p]);
932940 }
933941
963971 fdist[p] = i_max(xd*xd, yd*yd); /* manhattan distance */
964972 break;
965973 default:
966 i_fatal(3,"i_gradgen: Unknown distance measure\n");
974 im_fatal(aIMCTX, 3,"i_gradgen: Unknown distance measure\n");
967975 }
968976 cs += fdist[p];
969977 }
990998 i_img_dim x, y;
991999 i_img_dim xsize = im->xsize;
9921000 i_img_dim ysize = im->ysize;
993
994 mm_log((1,"i_gradgen(im %p, num %d, xo %p, yo %p, ival %p, dmeasure %d)\n", im, num, xo, yo, ival, dmeasure));
1001 dIMCTXim(im);
1002
1003 im_log((aIMCTX,1,"i_gradgen(im %p, num %d, xo %p, yo %p, ival %p, dmeasure %d)\n", im, num, xo, yo, ival, dmeasure));
9951004
9961005 for(p = 0; p<num; p++) {
997 mm_log((1,"i_gradgen: p%d(" i_DFp ")\n", p, i_DFcp(xo[p], yo[p])));
1006 im_log((aIMCTX, 1,"i_gradgen: p%d(" i_DFp ")\n", p, i_DFcp(xo[p], yo[p])));
9981007 ICL_info(&ival[p]);
9991008 }
10001009
10171026 mindist = i_max(xd*xd, yd*yd); /* manhattan distance */
10181027 break;
10191028 default:
1020 i_fatal(3,"i_nearest_color: Unknown distance measure\n");
1029 im_fatal(aIMCTX, 3,"i_nearest_color: Unknown distance measure\n");
10211030 }
10221031
10231032 for(p = 1; p<num; p++) {
10341043 curdist = i_max(xd*xd, yd*yd); /* manhattan distance */
10351044 break;
10361045 default:
1037 i_fatal(3,"i_nearest_color: Unknown distance measure\n");
1046 im_fatal(aIMCTX, 3,"i_nearest_color: Unknown distance measure\n");
10381047 }
10391048 if (curdist < mindist) {
10401049 mindist = curdist;
11241133 i_img_dim ysize = im->ysize;
11251134 int *cmatch;
11261135 size_t ival_bytes, tval_bytes;
1127
1128 mm_log((1,"i_nearest_color(im %p, num %d, xo %p, yo %p, oval %p, dmeasure %d)\n", im, num, xo, yo, oval, dmeasure));
1136 dIMCTXim(im);
1137
1138 im_log((aIMCTX, 1,"i_nearest_color(im %p, num %d, xo %p, yo %p, oval %p, dmeasure %d)\n", im, num, xo, yo, oval, dmeasure));
11291139
11301140 i_clear_error();
11311141
11781188 mindist = i_max(xd*xd, yd*yd); /* manhattan distance */
11791189 break;
11801190 default:
1181 i_fatal(3,"i_nearest_color: Unknown distance measure\n");
1191 im_fatal(aIMCTX, 3,"i_nearest_color: Unknown distance measure\n");
11821192 }
11831193
11841194 for(p = 1; p<num; p++) {
11951205 curdist = i_max(xd*xd, yd*yd); /* manhattan distance */
11961206 break;
11971207 default:
1198 i_fatal(3,"i_nearest_color: Unknown distance measure\n");
1208 im_fatal(aIMCTX, 3,"i_nearest_color: Unknown distance measure\n");
11991209 }
12001210 if (curdist < mindist) {
12011211 mindist = curdist;
13191329 i_img *out;
13201330 int outchans, diffchans;
13211331 i_img_dim xsize, ysize;
1332 dIMCTXim(im1);
13221333
13231334 i_clear_error();
13241335 if (im1->channels != im2->channels) {
16411652 i_fountain_seg *my_segs;
16421653 i_fill_combine_f combine_func = NULL;
16431654 i_fill_combinef_f combinef_func = NULL;
1655 dIMCTXim(im);
16441656
16451657 i_clear_error();
16461658
0 #define IMAGER_NO_CONTEXT
01 #include "imager.h"
12
23 static void flip_h(i_img *im);
2122
2223 undef_int
2324 i_flipxy(i_img *im, int direction) {
25 dIMCTXim(im);
2426 i_clear_error();
2527
26 mm_log((1, "i_flipxy(im %p, direction %d)\n", im, direction ));
28 im_log((aIMCTX, 1, "i_flipxy(im %p, direction %d)\n", im, direction ));
2729
2830 if (!im)
2931 return 0;
4244 break;
4345
4446 default:
45 mm_log((1, "i_flipxy: direction is invalid\n" ));
46 i_push_errorf(0, "direction %d invalid", direction);
47 im_log((aIMCTX, 1, "i_flipxy: direction is invalid\n" ));
48 im_push_errorf(aIMCTX, 0, "direction %d invalid", direction);
4749 return 0;
48
4950 }
5051 return 1;
5152 }
+0
-1378
font.c less more
0 #include "imager.h"
1 #include "imrender.h"
2
3 #include <sys/types.h>
4 #include <sys/stat.h>
5 #include <fcntl.h>
6
7 #include <stdio.h>
8 #include <stdlib.h>
9
10 #ifdef HAVE_LIBT1
11 #endif
12
13
14 /*
15 =head1 NAME
16
17 font.c - implements font handling functions for t1 and truetype fonts
18
19 =head1 SYNOPSIS
20
21 i_init_fonts();
22
23 #ifdef HAVE_LIBT1
24 fontnum = i_t1_new(path_to_pfb, path_to_afm);
25 i_t1_bbox(fontnum, points, "foo", 3, i_img_dim cords[BOUNDING_BOX_COUNT]);
26 rc = i_t1_destroy(fontnum);
27 #endif
28
29 #ifdef HAVE_LIBTT
30 handle = i_tt_new(path_to_ttf);
31 rc = i_tt_bbox(handle, points, "foo", 3, int cords[6], utf8);
32 i_tt_destroy(handle);
33
34 // and much more
35
36 =head1 DESCRIPTION
37
38 font.c implements font creation, rendering, bounding box functions and
39 more for Imager.
40
41 =head1 FUNCTION REFERENCE
42
43 Some of these functions are internal.
44
45 =over
46
47 =cut
48
49 */
50
51
52 /* Truetype font support */
53 #ifdef HAVE_LIBTT
54
55 /* These are enabled by default when configuring Freetype 1.x
56 I haven't a clue how to reliably detect it at compile time.
57
58 We need a compilation probe in Makefile.PL
59 */
60 #define FTXPOST 1
61 #define FTXERR18 1
62
63 #include <freetype.h>
64 #define TT_CHC 5
65
66 #ifdef FTXPOST
67 #include <ftxpost.h>
68 #endif
69
70 #ifdef FTXERR18
71 #include <ftxerr18.h>
72 #endif
73
74 /* some versions of FT1.x don't seem to define this - it's font defined
75 so it won't change */
76 #ifndef TT_MS_LANGID_ENGLISH_GENERAL
77 #define TT_MS_LANGID_ENGLISH_GENERAL 0x0409
78 #endif
79
80 /* convert a code point into an index in the glyph cache */
81 #define TT_HASH(x) ((x) & 0xFF)
82
83 typedef struct i_glyph_entry_ {
84 TT_Glyph glyph;
85 unsigned long ch;
86 } i_tt_glyph_entry;
87
88 #define TT_NOCHAR (~0UL)
89
90 struct TT_Instancehandle_ {
91 TT_Instance instance;
92 TT_Instance_Metrics imetrics;
93 TT_Glyph_Metrics gmetrics[256];
94 i_tt_glyph_entry glyphs[256];
95 int smooth;
96 int order;
97 i_img_dim ptsize;
98 };
99
100 typedef struct TT_Instancehandle_ TT_Instancehandle;
101
102 struct TT_Fonthandle_ {
103 TT_Face face;
104 TT_Face_Properties properties;
105 TT_Instancehandle instanceh[TT_CHC];
106 TT_CharMap char_map;
107 #ifdef FTXPOST
108 int loaded_names;
109 TT_Error load_cond;
110 #endif
111 };
112
113 /* Defines */
114
115 #define USTRCT(x) ((x).z)
116 #define TT_VALID( handle ) ( ( handle ).z != NULL )
117
118 static void i_tt_push_error(TT_Error rc);
119
120 /* Prototypes */
121
122 static int i_tt_get_instance( TT_Fonthandle *handle, i_img_dim points, int smooth );
123 static void i_tt_init_raster_map( TT_Raster_Map* bit, i_img_dim width, i_img_dim height, int smooth );
124 static void i_tt_done_raster_map( TT_Raster_Map *bit );
125 static void i_tt_clear_raster_map( TT_Raster_Map* bit );
126 static void i_tt_blit_or( TT_Raster_Map *dst, TT_Raster_Map *src,i_img_dim x_off, i_img_dim y_off );
127 static int i_tt_get_glyph( TT_Fonthandle *handle, int inst, unsigned long j );
128 static void
129 i_tt_render_glyph( TT_Glyph glyph, TT_Glyph_Metrics* gmetrics,
130 TT_Raster_Map *bit, TT_Raster_Map *small_bit,
131 i_img_dim x_off, i_img_dim y_off, int smooth );
132 static int
133 i_tt_render_all_glyphs( TT_Fonthandle *handle, int inst, TT_Raster_Map *bit,
134 TT_Raster_Map *small_bit, i_img_dim cords[6],
135 char const* txt, size_t len, int smooth, int utf8 );
136 static void i_tt_dump_raster_map2( i_img* im, TT_Raster_Map* bit, i_img_dim xb, i_img_dim yb, const i_color *cl, int smooth );
137 static void i_tt_dump_raster_map_channel( i_img* im, TT_Raster_Map* bit, i_img_dim xb, i_img_dim yb, int channel, int smooth );
138 static int
139 i_tt_rasterize( TT_Fonthandle *handle, TT_Raster_Map *bit, i_img_dim cords[6],
140 double points, char const* txt, size_t len, int smooth, int utf8 );
141 static undef_int i_tt_bbox_inst( TT_Fonthandle *handle, int inst ,const char *txt, size_t len, i_img_dim cords[6], int utf8 );
142
143
144 /* static globals needed */
145
146 static int TT_initialized = 0;
147 static TT_Engine engine;
148 static int LTT_dpi = 72; /* FIXME: this ought to be a part of the call interface */
149 static int LTT_hinted = 1; /* FIXME: this too */
150
151
152 /*
153 * FreeType interface
154 */
155
156
157 /*
158 =item init_tt()
159
160 Initializes the freetype font rendering engine
161
162 =cut
163 */
164
165 static undef_int
166 i_init_tt(void) {
167 TT_Error error;
168 TT_Byte palette[] = { 0, 64, 127, 191, 255 };
169
170 i_clear_error();
171
172 mm_log((1,"init_tt()\n"));
173 error = TT_Init_FreeType( &engine );
174 if ( error ){
175 mm_log((1,"Initialization of freetype failed, code = 0x%x\n",
176 (unsigned)error));
177 i_tt_push_error(error);
178 i_push_error(0, "Could not initialize freetype 1.x");
179 return(1);
180 }
181
182 #ifdef FTXPOST
183 error = TT_Init_Post_Extension( engine );
184 if (error) {
185 mm_log((1, "Initialization of Post extension failed = 0x%x\n",
186 (unsigned)error));
187
188 i_tt_push_error(error);
189 i_push_error(0, "Could not initialize FT 1.x POST extension");
190 return 1;
191 }
192 #endif
193
194 error = TT_Set_Raster_Gray_Palette(engine, palette);
195 if (error) {
196 mm_log((1, "Initialization of gray levels failed = 0x%x\n",
197 (unsigned)error));
198 i_tt_push_error(error);
199 i_push_error(0, "Could not initialize FT 1.x POST extension");
200 return 1;
201 }
202
203 TT_initialized = 1;
204
205 return(0);
206 }
207
208
209 /*
210 =item i_tt_get_instance(handle, points, smooth)
211
212 Finds a points+smooth instance or if one doesn't exist in the cache
213 allocates room and returns its cache entry
214
215 fontname - path to the font to load
216 handle - handle to the font.
217 points - points of the requested font
218 smooth - boolean (True: antialias on, False: antialias is off)
219
220 =cut
221 */
222
223 static
224 int
225 i_tt_get_instance( TT_Fonthandle *handle, i_img_dim points, int smooth ) {
226 int i,idx;
227 TT_Error error;
228
229 mm_log((1,"i_tt_get_instance(handle %p, points %" i_DF ", smooth %d)\n",
230 handle, i_DFc(points), smooth));
231
232 if (smooth == -1) { /* Smooth doesn't matter for this search */
233 for(i=0;i<TT_CHC;i++) {
234 if (handle->instanceh[i].ptsize==points) {
235 mm_log((1,"i_tt_get_instance: in cache - (non selective smoothing search) returning %d\n",i));
236 return i;
237 }
238 }
239 smooth=1; /* We will be adding a font - add it as smooth then */
240 } else { /* Smooth doesn't matter for this search */
241 for(i=0;i<TT_CHC;i++) {
242 if (handle->instanceh[i].ptsize == points
243 && handle->instanceh[i].smooth == smooth) {
244 mm_log((1,"i_tt_get_instance: in cache returning %d\n",i));
245 return i;
246 }
247 }
248 }
249
250 /* Found the instance in the cache - return the cache index */
251
252 for(idx=0;idx<TT_CHC;idx++) {
253 if (!(handle->instanceh[idx].order)) break; /* find the lru item */
254 }
255
256 mm_log((1,"i_tt_get_instance: lru item is %d\n",idx));
257 mm_log((1,"i_tt_get_instance: lru pointer %p\n",
258 USTRCT(handle->instanceh[idx].instance) ));
259
260 if ( USTRCT(handle->instanceh[idx].instance) ) {
261 mm_log((1,"i_tt_get_instance: freeing lru item from cache %d\n",idx));
262
263 /* Free cached glyphs */
264 for(i=0;i<256;i++)
265 if ( USTRCT(handle->instanceh[idx].glyphs[i].glyph) )
266 TT_Done_Glyph( handle->instanceh[idx].glyphs[i].glyph );
267
268 for(i=0;i<256;i++) {
269 handle->instanceh[idx].glyphs[i].ch = TT_NOCHAR;
270 USTRCT(handle->instanceh[idx].glyphs[i].glyph)=NULL;
271 }
272
273 /* Free instance if needed */
274 TT_Done_Instance( handle->instanceh[idx].instance );
275 }
276
277 /* create and initialize instance */
278 /* FIXME: probably a memory leak on fail */
279
280 (void) (( error = TT_New_Instance( handle->face, &handle->instanceh[idx].instance ) ) ||
281 ( error = TT_Set_Instance_Resolutions( handle->instanceh[idx].instance, LTT_dpi, LTT_dpi ) ) ||
282 ( error = TT_Set_Instance_CharSize( handle->instanceh[idx].instance, points*64 ) ) );
283
284 if ( error ) {
285 mm_log((1, "Could not create and initialize instance: error %x.\n",
286 (unsigned)error ));
287 return -1;
288 }
289
290 /* Now that the instance should the inplace we need to lower all of the
291 ru counts and put `this' one with the highest entry */
292
293 for(i=0;i<TT_CHC;i++) handle->instanceh[i].order--;
294
295 handle->instanceh[idx].order=TT_CHC-1;
296 handle->instanceh[idx].ptsize=points;
297 handle->instanceh[idx].smooth=smooth;
298 TT_Get_Instance_Metrics( handle->instanceh[idx].instance, &(handle->instanceh[idx].imetrics) );
299
300 /* Zero the memory for the glyph storage so they are not thought as
301 cached if they haven't been cached since this new font was loaded */
302
303 for(i=0;i<256;i++) {
304 handle->instanceh[idx].glyphs[i].ch = TT_NOCHAR;
305 USTRCT(handle->instanceh[idx].glyphs[i].glyph)=NULL;
306 }
307
308 return idx;
309 }
310
311
312 /*
313 =item i_tt_new(fontname)
314
315 Creates a new font handle object, finds a character map and initialise the
316 the font handle's cache
317
318 fontname - path to the font to load
319
320 =cut
321 */
322
323 TT_Fonthandle*
324 i_tt_new(const char *fontname) {
325 TT_Error error;
326 TT_Fonthandle *handle;
327 unsigned short i,n;
328 unsigned short platform,encoding;
329
330 if (!TT_initialized && i_init_tt()) {
331 i_push_error(0, "Could not initialize FT1 engine");
332 return NULL;
333 }
334
335 i_clear_error();
336
337 mm_log((1,"i_tt_new(fontname '%s')\n",fontname));
338
339 /* allocate memory for the structure */
340
341 handle = mymalloc( sizeof(TT_Fonthandle) ); /* checked 5Nov05 tonyc */
342
343 /* load the typeface */
344 error = TT_Open_Face( engine, fontname, &handle->face );
345 if ( error ) {
346 if ( error == TT_Err_Could_Not_Open_File ) {
347 mm_log((1, "Could not find/open %s.\n", fontname ));
348 }
349 else {
350 mm_log((1, "Error while opening %s, error code = 0x%x.\n",fontname,
351 (unsigned)error ));
352 }
353 i_tt_push_error(error);
354 return NULL;
355 }
356
357 TT_Get_Face_Properties( handle->face, &(handle->properties) );
358
359 /* First, look for a Unicode charmap */
360 n = handle->properties.num_CharMaps;
361 USTRCT( handle->char_map )=NULL; /* Invalidate character map */
362
363 for ( i = 0; i < n; i++ ) {
364 TT_Get_CharMap_ID( handle->face, i, &platform, &encoding );
365 if ( (platform == 3 && encoding == 1 )
366 || (platform == 0 && encoding == 0 ) ) {
367 mm_log((2,"i_tt_new - found char map platform %u encoding %u\n",
368 platform, encoding));
369 TT_Get_CharMap( handle->face, i, &(handle->char_map) );
370 break;
371 }
372 }
373 if (!USTRCT(handle->char_map) && n != 0) {
374 /* just use the first one */
375 TT_Get_CharMap( handle->face, 0, &(handle->char_map));
376 }
377
378 /* Zero the pointsizes - and ordering */
379
380 for(i=0;i<TT_CHC;i++) {
381 USTRCT(handle->instanceh[i].instance)=NULL;
382 handle->instanceh[i].order=i;
383 handle->instanceh[i].ptsize=0;
384 handle->instanceh[i].smooth=-1;
385 }
386
387 #ifdef FTXPOST
388 handle->loaded_names = 0;
389 #endif
390
391 mm_log((1,"i_tt_new <- %p\n",handle));
392 return handle;
393 }
394
395
396
397 /*
398 * raster map management
399 */
400
401 /*
402 =item i_tt_init_raster_map(bit, width, height, smooth)
403
404 Allocates internal memory for the bitmap as needed by the parameters (internal)
405
406 bit - bitmap to allocate into
407 width - width of the bitmap
408 height - height of the bitmap
409 smooth - boolean (True: antialias on, False: antialias is off)
410
411 =cut
412 */
413
414 static
415 void
416 i_tt_init_raster_map( TT_Raster_Map* bit, i_img_dim width, i_img_dim height, int smooth ) {
417
418 mm_log((1,"i_tt_init_raster_map( bit %p, width %" i_DF ", height %" i_DF
419 ", smooth %d)\n", bit, i_DFc(width), i_DFc(height), smooth));
420
421 bit->rows = height;
422 bit->width = ( width + 3 ) & -4;
423 bit->flow = TT_Flow_Down;
424
425 if ( smooth ) {
426 bit->cols = bit->width;
427 bit->size = bit->rows * bit->width;
428 } else {
429 bit->cols = ( bit->width + 7 ) / 8; /* convert to # of bytes */
430 bit->size = bit->rows * bit->cols; /* number of bytes in buffer */
431 }
432
433 /* rows can be 0 for some glyphs, for example ' ' */
434 if (bit->rows && bit->size / bit->rows != bit->cols) {
435 i_fatal(0, "Integer overflow calculating bitmap size (%d, %d)\n",
436 bit->width, bit->rows);
437 }
438
439 mm_log((1,"i_tt_init_raster_map: bit->width %d, bit->cols %d, bit->rows %d, bit->size %ld)\n", bit->width, bit->cols, bit->rows, bit->size ));
440
441 bit->bitmap = (void *) mymalloc( bit->size ); /* checked 6Nov05 tonyc */
442 if ( !bit->bitmap ) i_fatal(0,"Not enough memory to allocate bitmap (%d)!\n",bit->size );
443 }
444
445
446 /*
447 =item i_tt_clear_raster_map(bit)
448
449 Frees the bitmap data and sets pointer to NULL (internal)
450
451 bit - bitmap to free
452
453 =cut
454 */
455
456 static
457 void
458 i_tt_done_raster_map( TT_Raster_Map *bit ) {
459 myfree( bit->bitmap );
460 bit->bitmap = NULL;
461 }
462
463
464 /*
465 =item i_tt_clear_raster_map(bit)
466
467 Clears the specified bitmap (internal)
468
469 bit - bitmap to zero
470
471 =cut
472 */
473
474
475 static
476 void
477 i_tt_clear_raster_map( TT_Raster_Map* bit ) {
478 memset( bit->bitmap, 0, bit->size );
479 }
480
481
482 /*
483 =item i_tt_blit_or(dst, src, x_off, y_off)
484
485 function that blits one raster map into another (internal)
486
487 dst - destination bitmap
488 src - source bitmap
489 x_off - x offset into the destination bitmap
490 y_off - y offset into the destination bitmap
491
492 =cut
493 */
494
495 static
496 void
497 i_tt_blit_or( TT_Raster_Map *dst, TT_Raster_Map *src,i_img_dim x_off, i_img_dim y_off ) {
498 i_img_dim x, y;
499 i_img_dim x1, x2, y1, y2;
500 unsigned char *s, *d;
501
502 x1 = x_off < 0 ? -x_off : 0;
503 y1 = y_off < 0 ? -y_off : 0;
504
505 x2 = (int)dst->cols - x_off;
506 if ( x2 > src->cols ) x2 = src->cols;
507
508 y2 = (int)dst->rows - y_off;
509 if ( y2 > src->rows ) y2 = src->rows;
510
511 if ( x1 >= x2 ) return;
512
513 /* do the real work now */
514
515 for ( y = y1; y < y2; ++y ) {
516 s = ( (unsigned char*)src->bitmap ) + y * src->cols + x1;
517 d = ( (unsigned char*)dst->bitmap ) + ( y + y_off ) * dst->cols + x1 + x_off;
518
519 for ( x = x1; x < x2; ++x ) {
520 if (*s > *d)
521 *d = *s;
522 d++;
523 s++;
524 }
525 }
526 }
527
528 /* useful for debugging */
529 #if 0
530
531 static void dump_raster_map(FILE *out, TT_Raster_Map *bit ) {
532 int x, y;
533 fprintf(out, "cols %d rows %d flow %d\n", bit->cols, bit->rows, bit->flow);
534 for (y = 0; y < bit->rows; ++y) {
535 fprintf(out, "%2d:", y);
536 for (x = 0; x < bit->cols; ++x) {
537 if ((x & 7) == 0 && x) putc(' ', out);
538 fprintf(out, "%02x", ((unsigned char *)bit->bitmap)[y*bit->cols+x]);
539 }
540 putc('\n', out);
541 }
542 }
543
544 #endif
545
546 /*
547 =item i_tt_get_glyph(handle, inst, j)
548
549 Function to see if a glyph exists and if so cache it (internal)
550
551 handle - pointer to font handle
552 inst - font instance
553 j - charcode of glyph
554
555 =cut
556 */
557
558 static
559 int
560 i_tt_get_glyph( TT_Fonthandle *handle, int inst, unsigned long j) {
561 unsigned short load_flags, code;
562 TT_Error error;
563
564 mm_log((1, "i_tt_get_glyph(handle %p, inst %d, j %lu (%c))\n",
565 handle,inst,j, (int)((j >= ' ' && j <= '~') ? j : '.')));
566
567 /*mm_log((1, "handle->instanceh[inst].glyphs[j]=0x%08X\n",handle->instanceh[inst].glyphs[j] ));*/
568
569 if ( TT_VALID(handle->instanceh[inst].glyphs[TT_HASH(j)].glyph)
570 && handle->instanceh[inst].glyphs[TT_HASH(j)].ch == j) {
571 mm_log((1,"i_tt_get_glyph: %lu in cache\n",j));
572 return 1;
573 }
574
575 if ( TT_VALID(handle->instanceh[inst].glyphs[TT_HASH(j)].glyph) ) {
576 /* clean up the entry */
577 TT_Done_Glyph( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph );
578 USTRCT( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph ) = NULL;
579 handle->instanceh[inst].glyphs[TT_HASH(j)].ch = TT_NOCHAR;
580 }
581
582 /* Ok - it wasn't cached - try to get it in */
583 load_flags = TTLOAD_SCALE_GLYPH;
584 if ( LTT_hinted ) load_flags |= TTLOAD_HINT_GLYPH;
585
586 if ( !TT_VALID(handle->char_map) ) {
587 code = (j - ' ' + 1) < 0 ? 0 : (j - ' ' + 1);
588 if ( code >= handle->properties.num_Glyphs ) code = 0;
589 } else code = TT_Char_Index( handle->char_map, j );
590
591 if ( (error = TT_New_Glyph( handle->face, &handle->instanceh[inst].glyphs[TT_HASH(j)].glyph)) ) {
592 mm_log((1, "Cannot allocate and load glyph: error %#x.\n", (unsigned)error ));
593 i_push_error(error, "TT_New_Glyph()");
594 return 0;
595 }
596 if ( (error = TT_Load_Glyph( handle->instanceh[inst].instance, handle->instanceh[inst].glyphs[TT_HASH(j)].glyph, code, load_flags)) ) {
597 mm_log((1, "Cannot allocate and load glyph: error %#x.\n", (unsigned)error ));
598 /* Don't leak */
599 TT_Done_Glyph( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph );
600 USTRCT( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph ) = NULL;
601 i_push_error(error, "TT_Load_Glyph()");
602 return 0;
603 }
604
605 /* At this point the glyph should be allocated and loaded */
606 handle->instanceh[inst].glyphs[TT_HASH(j)].ch = j;
607
608 /* Next get the glyph metrics */
609 error = TT_Get_Glyph_Metrics( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph,
610 &handle->instanceh[inst].gmetrics[TT_HASH(j)] );
611 if (error) {
612 mm_log((1, "TT_Get_Glyph_Metrics: error %#x.\n", (unsigned)error ));
613 TT_Done_Glyph( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph );
614 USTRCT( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph ) = NULL;
615 handle->instanceh[inst].glyphs[TT_HASH(j)].ch = TT_NOCHAR;
616 i_push_error(error, "TT_Get_Glyph_Metrics()");
617 return 0;
618 }
619
620 return 1;
621 }
622
623 /*
624 =item i_tt_has_chars(handle, text, len, utf8, out)
625
626 Check if the given characters are defined by the font. Note that len
627 is the number of bytes, not the number of characters (when utf8 is
628 non-zero).
629
630 Returns the number of characters that were checked.
631
632 =cut
633 */
634
635 size_t
636 i_tt_has_chars(TT_Fonthandle *handle, char const *text, size_t len, int utf8,
637 char *out) {
638 size_t count = 0;
639 mm_log((1, "i_tt_has_chars(handle %p, text %p, len %ld, utf8 %d)\n",
640 handle, text, (long)len, utf8));
641
642 while (len) {
643 unsigned long c;
644 int index;
645 if (utf8) {
646 c = i_utf8_advance(&text, &len);
647 if (c == ~0UL) {
648 i_push_error(0, "invalid UTF8 character");
649 return 0;
650 }
651 }
652 else {
653 c = (unsigned char)*text++;
654 --len;
655 }
656
657 if (TT_VALID(handle->char_map)) {
658 index = TT_Char_Index(handle->char_map, c);
659 }
660 else {
661 index = (c - ' ' + 1) < 0 ? 0 : (c - ' ' + 1);
662 if (index >= handle->properties.num_Glyphs)
663 index = 0;
664 }
665 *out++ = index != 0;
666 ++count;
667 }
668
669 return count;
670 }
671
672 /*
673 =item i_tt_destroy(handle)
674
675 Clears the data taken by a font including all cached data such as
676 pixmaps and glyphs
677
678 handle - pointer to font handle
679
680 =cut
681 */
682
683 void
684 i_tt_destroy( TT_Fonthandle *handle) {
685 TT_Close_Face( handle->face );
686 myfree( handle );
687
688 /* FIXME: Should these be freed automatically by the library?
689
690 TT_Done_Instance( instance );
691 void
692 i_tt_done_glyphs( void ) {
693 int i;
694
695 if ( !glyphs ) return;
696
697 for ( i = 0; i < 256; ++i ) TT_Done_Glyph( glyphs[i] );
698 free( glyphs );
699
700 glyphs = NULL;
701 }
702 */
703 }
704
705
706 /*
707 * FreeType Rendering functions
708 */
709
710
711 /*
712 =item i_tt_render_glyph(handle, gmetrics, bit, smallbit, x_off, y_off, smooth)
713
714 Renders a single glyph into the bit rastermap (internal)
715
716 handle - pointer to font handle
717 gmetrics - the metrics for the glyph to be rendered
718 bit - large bitmap that is the destination for the text
719 smallbit - small bitmap that is used only if smooth is true
720 x_off - x offset of glyph
721 y_off - y offset of glyph
722 smooth - boolean (True: antialias on, False: antialias is off)
723
724 =cut
725 */
726
727 static
728 void
729 i_tt_render_glyph( TT_Glyph glyph, TT_Glyph_Metrics* gmetrics, TT_Raster_Map *bit, TT_Raster_Map *small_bit, i_img_dim x_off, i_img_dim y_off, int smooth ) {
730
731 mm_log((1,"i_tt_render_glyph(glyph %p, gmetrics %p, bit %p, small_bit %p, x_off %" i_DF ", y_off %" i_DF ", smooth %d)\n",
732 USTRCT(glyph), gmetrics, bit, small_bit, i_DFc(x_off),
733 i_DFc(y_off), smooth));
734
735 if ( !smooth ) TT_Get_Glyph_Bitmap( glyph, bit, x_off * 64, y_off * 64);
736 else {
737 TT_F26Dot6 xmin, ymin, xmax, ymax;
738
739 xmin = gmetrics->bbox.xMin & -64;
740 ymin = gmetrics->bbox.yMin & -64;
741 xmax = (gmetrics->bbox.xMax + 63) & -64;
742 ymax = (gmetrics->bbox.yMax + 63) & -64;
743
744 i_tt_clear_raster_map( small_bit );
745 TT_Get_Glyph_Pixmap( glyph, small_bit, -xmin, -ymin );
746 i_tt_blit_or( bit, small_bit, xmin/64 + x_off, -ymin/64 - y_off );
747 }
748 }
749
750
751 /*
752 =item i_tt_render_all_glyphs(handle, inst, bit, small_bit, cords, txt, len, smooth)
753
754 calls i_tt_render_glyph to render each glyph into the bit rastermap (internal)
755
756 handle - pointer to font handle
757 inst - font instance
758 bit - large bitmap that is the destination for the text
759 smallbit - small bitmap that is used only if smooth is true
760 txt - string to render
761 len - length of the string to render
762 smooth - boolean (True: antialias on, False: antialias is off)
763
764 =cut
765 */
766
767 static
768 int
769 i_tt_render_all_glyphs( TT_Fonthandle *handle, int inst, TT_Raster_Map *bit,
770 TT_Raster_Map *small_bit, i_img_dim cords[6],
771 char const* txt, size_t len, int smooth, int utf8 ) {
772 unsigned long j;
773 TT_F26Dot6 x,y;
774
775 mm_log((1,"i_tt_render_all_glyphs( handle %p, inst %d, bit %p, small_bit %p, txt '%.*s', len %ld, smooth %d, utf8 %d)\n",
776 handle, inst, bit, small_bit, (int)len, txt, (long)len, smooth, utf8));
777
778 /*
779 y=-( handle->properties.horizontal->Descender * handle->instanceh[inst].imetrics.y_ppem )/(handle->properties.header->Units_Per_EM);
780 */
781
782 x=-cords[0]; /* FIXME: If you font is antialiased this should be expanded by one to allow for aa expansion and the allocation too - do before passing here */
783 y=-cords[4];
784
785 while (len) {
786 if (utf8) {
787 j = i_utf8_advance(&txt, &len);
788 if (j == ~0UL) {
789 i_push_error(0, "invalid UTF8 character");
790 return 0;
791 }
792 }
793 else {
794 j = (unsigned char)*txt++;
795 --len;
796 }
797 if ( !i_tt_get_glyph(handle,inst,j) )
798 continue;
799 i_tt_render_glyph( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph,
800 &handle->instanceh[inst].gmetrics[TT_HASH(j)], bit,
801 small_bit, x, y, smooth );
802 x += handle->instanceh[inst].gmetrics[TT_HASH(j)].advance / 64;
803 }
804
805 return 1;
806 }
807
808
809 /*
810 * Functions to render rasters (single channel images) onto images
811 */
812
813 /*
814 =item i_tt_dump_raster_map2(im, bit, xb, yb, cl, smooth)
815
816 Function to dump a raster onto an image in color used by i_tt_text() (internal).
817
818 im - image to dump raster on
819 bit - bitmap that contains the text to be dumped to im
820 xb, yb - coordinates, left edge and baseline
821 cl - color to use for text
822 smooth - boolean (True: antialias on, False: antialias is off)
823
824 =cut
825 */
826
827 static
828 void
829 i_tt_dump_raster_map2( i_img* im, TT_Raster_Map* bit, i_img_dim xb, i_img_dim yb, const i_color *cl, int smooth ) {
830 unsigned char *bmap;
831 i_img_dim x, y;
832 mm_log((1,"i_tt_dump_raster_map2(im %p, bit %p, xb %" i_DF ", yb %" i_DF ", cl %p)\n",
833 im, bit, i_DFc(xb), i_DFc(yb), cl));
834
835 bmap = bit->bitmap;
836
837 if ( smooth ) {
838
839 i_render r;
840 i_render_init(&r, im, bit->cols);
841 for(y=0;y<bit->rows;y++) {
842 i_render_color(&r, xb, yb+y, bit->cols, bmap + y*bit->cols, cl);
843 }
844 i_render_done(&r);
845 } else {
846 for(y=0;y<bit->rows;y++) {
847 unsigned mask = 0x80;
848 unsigned char *p = bmap + y * bit->cols;
849
850 for(x = 0; x < bit->width; x++) {
851 if (*p & mask) {
852 i_ppix(im, x+xb, y+yb, cl);
853 }
854 mask >>= 1;
855 if (!mask) {
856 mask = 0x80;
857 ++p;
858 }
859 }
860 }
861
862 }
863 }
864
865
866 /*
867 =item i_tt_dump_raster_map_channel(im, bit, xb, yb, channel, smooth)
868
869 Function to dump a raster onto a single channel image in color (internal)
870
871 im - image to dump raster on
872 bit - bitmap that contains the text to be dumped to im
873 xb, yb - coordinates, left edge and baseline
874 channel - channel to copy to
875 smooth - boolean (True: antialias on, False: antialias is off)
876
877 =cut
878 */
879
880 static
881 void
882 i_tt_dump_raster_map_channel( i_img* im, TT_Raster_Map* bit, i_img_dim xb, i_img_dim yb, int channel, int smooth ) {
883 unsigned char *bmap;
884 i_color val;
885 int c;
886 i_img_dim x,y;
887 int old_mask = im->ch_mask;
888 im->ch_mask = 1 << channel;
889
890 mm_log((1,"i_tt_dump_raster_channel(im %p, bit %p, xb %" i_DF ", yb %" i_DF ", channel %d)\n",
891 im, bit, i_DFc(xb), i_DFc(yb), channel));
892
893 bmap = bit->bitmap;
894
895 if ( smooth ) {
896 for(y=0;y<bit->rows;y++) for(x=0;x<bit->width;x++) {
897 c = bmap[y*(bit->cols)+x];
898 val.channel[channel] = c;
899 i_ppix(im,x+xb,y+yb,&val);
900 }
901 } else {
902 for(y=0;y<bit->rows;y++) {
903 unsigned mask = 0x80;
904 unsigned char *p = bmap + y * bit->cols;
905
906 for(x=0;x<bit->width;x++) {
907 val.channel[channel] = (*p & mask) ? 255 : 0;
908 i_ppix(im,x+xb,y+yb,&val);
909
910 mask >>= 1;
911 if (!mask) {
912 ++p;
913 mask = 0x80;
914 }
915 }
916 }
917 }
918 im->ch_mask = old_mask;
919 }
920
921
922 /*
923 =item i_tt_rasterize(handle, bit, cords, points, txt, len, smooth)
924
925 interface for generating single channel raster of text (internal)
926
927 handle - pointer to font handle
928 bit - the bitmap that is allocated, rendered into and NOT freed
929 cords - the bounding box (modified in place)
930 points - font size to use
931 txt - string to render
932 len - length of the string to render
933 smooth - boolean (True: antialias on, False: antialias is off)
934
935 =cut
936 */
937
938 static
939 int
940 i_tt_rasterize( TT_Fonthandle *handle, TT_Raster_Map *bit, i_img_dim cords[6], double points, char const* txt, size_t len, int smooth, int utf8 ) {
941 int inst;
942 i_img_dim width, height;
943 TT_Raster_Map small_bit;
944
945 /* find or install an instance */
946 if ( (inst=i_tt_get_instance(handle,points,smooth)) < 0) {
947 mm_log((1,"i_tt_rasterize: get instance failed\n"));
948 return 0;
949 }
950
951 /* calculate bounding box */
952 if (!i_tt_bbox_inst( handle, inst, txt, len, cords, utf8 ))
953 return 0;
954
955
956 width = cords[2]-cords[0];
957 height = cords[5]-cords[4];
958
959 mm_log((1,"i_tt_rasterize: width=%" i_DF ", height=%" i_DF "\n",
960 i_DFc(width), i_DFc(height) ));
961
962 i_tt_init_raster_map ( bit, width, height, smooth );
963 i_tt_clear_raster_map( bit );
964 if ( smooth ) i_tt_init_raster_map( &small_bit, handle->instanceh[inst].imetrics.x_ppem + 32, height, smooth );
965
966 if (!i_tt_render_all_glyphs( handle, inst, bit, &small_bit, cords, txt, len,
967 smooth, utf8 )) {
968 if ( smooth )
969 i_tt_done_raster_map( &small_bit );
970 return 0;
971 }
972
973 if ( smooth ) i_tt_done_raster_map( &small_bit );
974 return 1;
975 }
976
977
978
979 /*
980 * Exported text rendering interfaces
981 */
982
983
984 /*
985 =item i_tt_cp(handle, im, xb, yb, channel, points, txt, len, smooth, utf8)
986
987 Interface to text rendering into a single channel in an image
988
989 handle - pointer to font handle
990 im - image to render text on to
991 xb, yb - coordinates, left edge and baseline
992 channel - channel to render into
993 points - font size to use
994 txt - string to render
995 len - length of the string to render
996 smooth - boolean (True: antialias on, False: antialias is off)
997
998 =cut
999 */
1000
1001 undef_int
1002 i_tt_cp( TT_Fonthandle *handle, i_img *im, i_img_dim xb, i_img_dim yb, int channel, double points, char const* txt, size_t len, int smooth, int utf8, int align ) {
1003
1004 i_img_dim cords[BOUNDING_BOX_COUNT];
1005 i_img_dim ascent, st_offset, y;
1006 TT_Raster_Map bit;
1007
1008 i_clear_error();
1009 if (! i_tt_rasterize( handle, &bit, cords, points, txt, len, smooth, utf8 ) ) return 0;
1010
1011 ascent=cords[BBOX_ASCENT];
1012 st_offset=cords[BBOX_NEG_WIDTH];
1013 y = align ? yb-ascent : yb;
1014
1015 i_tt_dump_raster_map_channel( im, &bit, xb-st_offset , y, channel, smooth );
1016 i_tt_done_raster_map( &bit );
1017
1018 return 1;
1019 }
1020
1021
1022 /*
1023 =item i_tt_text(handle, im, xb, yb, cl, points, txt, len, smooth, utf8)
1024
1025 Interface to text rendering in a single color onto an image
1026
1027 handle - pointer to font handle
1028 im - image to render text on to
1029 xb, yb - coordinates, left edge and baseline
1030 cl - color to use for text
1031 points - font size to use
1032 txt - string to render
1033 len - length of the string to render
1034 smooth - boolean (True: antialias on, False: antialias is off)
1035
1036 =cut
1037 */
1038
1039 undef_int
1040 i_tt_text( TT_Fonthandle *handle, i_img *im, i_img_dim xb, i_img_dim yb, const i_color *cl, double points, char const* txt, size_t len, int smooth, int utf8, int align) {
1041 i_img_dim cords[BOUNDING_BOX_COUNT];
1042 i_img_dim ascent, st_offset, y;
1043 TT_Raster_Map bit;
1044
1045 i_clear_error();
1046
1047 if (! i_tt_rasterize( handle, &bit, cords, points, txt, len, smooth, utf8 ) ) return 0;
1048
1049 ascent=cords[BBOX_ASCENT];
1050 st_offset=cords[BBOX_NEG_WIDTH];
1051 y = align ? yb-ascent : yb;
1052
1053 i_tt_dump_raster_map2( im, &bit, xb+st_offset, y, cl, smooth );
1054 i_tt_done_raster_map( &bit );
1055
1056 return 1;
1057 }
1058
1059
1060 /*
1061 =item i_tt_bbox_inst(handle, inst, txt, len, cords, utf8)
1062
1063 Function to get texts bounding boxes given the instance of the font (internal)
1064
1065 handle - pointer to font handle
1066 inst - font instance
1067 txt - string to measure
1068 len - length of the string to render
1069 cords - the bounding box (modified in place)
1070
1071 =cut
1072 */
1073
1074 static
1075 undef_int
1076 i_tt_bbox_inst( TT_Fonthandle *handle, int inst ,const char *txt, size_t len, i_img_dim cords[BOUNDING_BOX_COUNT], int utf8 ) {
1077 int upm, casc, cdesc, first;
1078
1079 int start = 0;
1080 i_img_dim width = 0;
1081 int gdescent = 0;
1082 int gascent = 0;
1083 int descent = 0;
1084 int ascent = 0;
1085 int rightb = 0;
1086
1087 unsigned long j;
1088 unsigned char *ustr;
1089 ustr=(unsigned char*)txt;
1090
1091 mm_log((1,"i_tt_box_inst(handle %p,inst %d,txt '%.*s', len %ld, utf8 %d)\n",
1092 handle, inst, (int)len, txt, (long)len, utf8));
1093
1094 upm = handle->properties.header->Units_Per_EM;
1095 gascent = ( handle->properties.horizontal->Ascender * handle->instanceh[inst].imetrics.y_ppem + upm - 1) / upm;
1096 gdescent = ( handle->properties.horizontal->Descender * handle->instanceh[inst].imetrics.y_ppem - upm + 1) / upm;
1097
1098 width = 0;
1099 start = 0;
1100
1101 mm_log((1, "i_tt_box_inst: gascent=%d gdescent=%d\n", gascent, gdescent));
1102
1103 first=1;
1104 while (len) {
1105 if (utf8) {
1106 j = i_utf8_advance(&txt, &len);
1107 if (j == ~0UL) {
1108 i_push_error(0, "invalid UTF8 character");
1109 return 0;
1110 }
1111 }
1112 else {
1113 j = (unsigned char)*txt++;
1114 --len;
1115 }
1116 if ( i_tt_get_glyph(handle,inst,j) ) {
1117 TT_Glyph_Metrics *gm = handle->instanceh[inst].gmetrics + TT_HASH(j);
1118 width += gm->advance / 64;
1119 casc = (gm->bbox.yMax+63) / 64;
1120 cdesc = (gm->bbox.yMin-63) / 64;
1121
1122 mm_log((1, "i_tt_box_inst: glyph='%c' casc=%d cdesc=%d\n",
1123 (int)((j >= ' ' && j <= '~') ? j : '.'), casc, cdesc));
1124
1125 if (first) {
1126 start = gm->bbox.xMin / 64;
1127 ascent = (gm->bbox.yMax+63) / 64;
1128 descent = (gm->bbox.yMin-63) / 64;
1129 first = 0;
1130 }
1131 if (!len) { /* if at end of string */
1132 /* the right-side bearing - in case the right-side of a
1133 character goes past the right of the advance width,
1134 as is common for italic fonts
1135 */
1136 rightb = gm->advance - gm->bearingX
1137 - (gm->bbox.xMax - gm->bbox.xMin);
1138 /* fprintf(stderr, "font info last: %d %d %d %d\n",
1139 gm->bbox.xMax, gm->bbox.xMin, gm->advance, rightb); */
1140 }
1141
1142 ascent = (ascent > casc ? ascent : casc );
1143 descent = (descent < cdesc ? descent : cdesc);
1144 }
1145 }
1146
1147 cords[BBOX_NEG_WIDTH]=start;
1148 cords[BBOX_GLOBAL_DESCENT]=gdescent;
1149 cords[BBOX_POS_WIDTH]=width;
1150 if (rightb < 0)
1151 cords[BBOX_POS_WIDTH] -= rightb / 64;
1152 cords[BBOX_GLOBAL_ASCENT]=gascent;
1153 cords[BBOX_DESCENT]=descent;
1154 cords[BBOX_ASCENT]=ascent;
1155 cords[BBOX_ADVANCE_WIDTH] = width;
1156 cords[BBOX_RIGHT_BEARING] = rightb / 64;
1157
1158 return BBOX_RIGHT_BEARING + 1;
1159 }
1160
1161
1162 /*
1163 =item i_tt_bbox(handle, points, txt, len, cords, utf8)
1164
1165 Interface to get a strings bounding box
1166
1167 handle - pointer to font handle
1168 points - font size to use
1169 txt - string to render
1170 len - length of the string to render
1171 cords - the bounding box (modified in place)
1172
1173 =cut
1174 */
1175
1176 undef_int
1177 i_tt_bbox( TT_Fonthandle *handle, double points,const char *txt,size_t len,i_img_dim cords[6], int utf8) {
1178 int inst;
1179
1180 i_clear_error();
1181 mm_log((1,"i_tt_box(handle %p,points %f,txt '%.*s', len %ld, utf8 %d)\n",
1182 handle, points, (int)len, txt, (long)len, utf8));
1183
1184 if ( (inst=i_tt_get_instance(handle,points,-1)) < 0) {
1185 i_push_errorf(0, "i_tt_get_instance(%g)", points);
1186 mm_log((1,"i_tt_text: get instance failed\n"));
1187 return 0;
1188 }
1189
1190 return i_tt_bbox_inst(handle, inst, txt, len, cords, utf8);
1191 }
1192
1193 /*
1194 =item i_tt_face_name(handle, name_buf, name_buf_size)
1195
1196 Retrieve's the font's postscript name.
1197
1198 This is complicated by the need to handle encodings and so on.
1199
1200 =cut
1201 */
1202 size_t
1203 i_tt_face_name(TT_Fonthandle *handle, char *name_buf, size_t name_buf_size) {
1204 TT_Face_Properties props;
1205 int name_count;
1206 int i;
1207 TT_UShort platform_id, encoding_id, lang_id, name_id;
1208 TT_UShort name_len;
1209 TT_String *name;
1210 int want_index = -1; /* an acceptable but not perfect name */
1211 int score = 0;
1212
1213 i_clear_error();
1214
1215 TT_Get_Face_Properties(handle->face, &props);
1216 name_count = props.num_Names;
1217 for (i = 0; i < name_count; ++i) {
1218 TT_Get_Name_ID(handle->face, i, &platform_id, &encoding_id, &lang_id,
1219 &name_id);
1220
1221 TT_Get_Name_String(handle->face, i, &name, &name_len);
1222
1223 if (platform_id != TT_PLATFORM_APPLE_UNICODE && name_len
1224 && name_id == TT_NAME_ID_PS_NAME) {
1225 int might_want_index = -1;
1226 int might_score = 0;
1227 if ((platform_id == TT_PLATFORM_MACINTOSH && encoding_id == TT_MAC_ID_ROMAN)
1228 ||
1229 (platform_id == TT_PLATFORM_MICROSOFT && encoding_id == TT_MS_LANGID_ENGLISH_UNITED_STATES)) {
1230 /* exactly what we want */
1231 want_index = i;
1232 break;
1233 }
1234
1235 if (platform_id == TT_PLATFORM_MICROSOFT
1236 && (encoding_id & 0xFF) == TT_MS_LANGID_ENGLISH_GENERAL) {
1237 /* any english is good */
1238 might_want_index = i;
1239 might_score = 9;
1240 }
1241 /* there might be something in between */
1242 else {
1243 /* anything non-unicode is better than nothing */
1244 might_want_index = i;
1245 might_score = 1;
1246 }
1247 if (might_score > score) {
1248 score = might_score;
1249 want_index = might_want_index;
1250 }
1251 }
1252 }
1253
1254 if (want_index != -1) {
1255 TT_Get_Name_String(handle->face, want_index, &name, &name_len);
1256
1257 strncpy(name_buf, name, name_buf_size);
1258 name_buf[name_buf_size-1] = '\0';
1259
1260 return strlen(name) + 1;
1261 }
1262 else {
1263 i_push_error(0, "no face name present");
1264 return 0;
1265 }
1266 }
1267
1268 void i_tt_dump_names(TT_Fonthandle *handle) {
1269 TT_Face_Properties props;
1270 int name_count;
1271 int i;
1272 TT_UShort platform_id, encoding_id, lang_id, name_id;
1273 TT_UShort name_len;
1274 TT_String *name;
1275
1276 TT_Get_Face_Properties(handle->face, &props);
1277 name_count = props.num_Names;
1278 for (i = 0; i < name_count; ++i) {
1279 TT_Get_Name_ID(handle->face, i, &platform_id, &encoding_id, &lang_id,
1280 &name_id);
1281 TT_Get_Name_String(handle->face, i, &name, &name_len);
1282
1283 printf("# %d: plat %d enc %d lang %d name %d value ", i, platform_id,
1284 encoding_id, lang_id, name_id);
1285 if (platform_id == TT_PLATFORM_APPLE_UNICODE) {
1286 printf("(unicode)\n");
1287 }
1288 else {
1289 printf("'%s'\n", name);
1290 }
1291 }
1292 fflush(stdout);
1293 }
1294
1295 size_t
1296 i_tt_glyph_name(TT_Fonthandle *handle, unsigned long ch, char *name_buf,
1297 size_t name_buf_size) {
1298 #ifdef FTXPOST
1299 TT_Error rc;
1300 TT_String *psname;
1301 TT_UShort index;
1302
1303 i_clear_error();
1304
1305 if (!handle->loaded_names) {
1306 TT_Post post;
1307 mm_log((1, "Loading PS Names"));
1308 handle->load_cond = TT_Load_PS_Names(handle->face, &post);
1309 ++handle->loaded_names;
1310 }
1311
1312 if (handle->load_cond) {
1313 i_push_errorf(handle->load_cond, "error loading names (%#x)",
1314 (unsigned)handle->load_cond);
1315 return 0;
1316 }
1317
1318 index = TT_Char_Index(handle->char_map, ch);
1319 if (!index) {
1320 i_push_error(0, "no such character");
1321 return 0;
1322 }
1323
1324 rc = TT_Get_PS_Name(handle->face, index, &psname);
1325
1326 if (rc) {
1327 i_push_error(rc, "error getting name");
1328 return 0;
1329 }
1330
1331 strncpy(name_buf, psname, name_buf_size);
1332 name_buf[name_buf_size-1] = '\0';
1333
1334 return strlen(psname) + 1;
1335 #else
1336 mm_log((1, "FTXPOST extension not enabled\n"));
1337 i_clear_error();
1338 i_push_error(0, "Use of FTXPOST extension disabled");
1339
1340 return 0;
1341 #endif
1342 }
1343
1344 /*
1345 =item i_tt_push_error(code)
1346
1347 Push an error message and code onto the Imager error stack.
1348
1349 =cut
1350 */
1351 static void
1352 i_tt_push_error(TT_Error rc) {
1353 #ifdef FTXERR18
1354 TT_String const *msg = TT_ErrToString18(rc);
1355
1356 i_push_error(rc, msg);
1357 #else
1358 i_push_errorf(rc, "Error code 0x%04x", (unsigned)rc);
1359 #endif
1360 }
1361
1362 #endif /* HAVE_LIBTT */
1363
1364
1365 /*
1366 =back
1367
1368 =head1 AUTHOR
1369
1370 Arnar M. Hrafnkelsson <addi@umich.edu>
1371
1372 =head1 SEE ALSO
1373
1374 Imager(3)
1375
1376 =cut
1377 */
0 #include "imager.h"
1 #include "imrender.h"
2
3 #include <sys/types.h>
4 #include <sys/stat.h>
5 #include <fcntl.h>
6
7 #include <stdio.h>
8 #include <stdlib.h>
9
10
11 /*
12 =head1 NAME
13
14 fontft1.c - Freetype 1.x font driver for Imager
15
16 =head1 SYNOPSIS
17
18 handle = i_tt_new(path_to_ttf);
19 rc = i_tt_bbox(handle, points, "foo", 3, int cords[6], utf8);
20 i_tt_destroy(handle);
21
22 // and much more
23
24 =head1 DESCRIPTION
25
26 fontft1.c implements font creation, rendering, bounding box functions and
27 more for Imager using Freetype 1.x.
28
29 In general this driver should be ignored in favour of the FT2 driver.
30
31 =head1 FUNCTION REFERENCE
32
33 Some of these functions are internal.
34
35 =over
36
37 =cut
38
39 */
40
41
42 /* Truetype font support */
43 /* These are enabled by default when configuring Freetype 1.x
44 I haven't a clue how to reliably detect it at compile time.
45
46 We need a compilation probe in Makefile.PL
47 */
48 #define FTXPOST 1
49 #define FTXERR18 1
50
51 #include <freetype.h>
52 #define TT_CHC 5
53
54 #ifdef FTXPOST
55 #include <ftxpost.h>
56 #endif
57
58 #ifdef FTXERR18
59 #include <ftxerr18.h>
60 #endif
61
62 /* some versions of FT1.x don't seem to define this - it's font defined
63 so it won't change */
64 #ifndef TT_MS_LANGID_ENGLISH_GENERAL
65 #define TT_MS_LANGID_ENGLISH_GENERAL 0x0409
66 #endif
67
68 static im_slot_t slot = -1;
69
70 /* convert a code point into an index in the glyph cache */
71 #define TT_HASH(x) ((x) & 0xFF)
72
73 typedef struct {
74 int initialized;
75 TT_Engine engine;
76 } i_tt_engine;
77
78 typedef struct i_glyph_entry_ {
79 TT_Glyph glyph;
80 unsigned long ch;
81 } i_tt_glyph_entry;
82
83 #define TT_NOCHAR (~0UL)
84
85 struct TT_Instancehandle_ {
86 TT_Instance instance;
87 TT_Instance_Metrics imetrics;
88 TT_Glyph_Metrics gmetrics[256];
89 i_tt_glyph_entry glyphs[256];
90 int smooth;
91 int order;
92 i_img_dim ptsize;
93 };
94
95 typedef struct TT_Instancehandle_ TT_Instancehandle;
96
97 struct TT_Fonthandle_ {
98 TT_Face face;
99 TT_Face_Properties properties;
100 TT_Instancehandle instanceh[TT_CHC];
101 TT_CharMap char_map;
102 #ifdef FTXPOST
103 int loaded_names;
104 TT_Error load_cond;
105 #endif
106 };
107
108 /* Defines */
109
110 #define USTRCT(x) ((x).z)
111 #define TT_VALID( handle ) ( ( handle ).z != NULL )
112
113 static void i_tt_push_error(TT_Error rc);
114 static void i_tt_uninit(void *);
115
116 /* Prototypes */
117
118 static int i_tt_get_instance( TT_Fonthandle *handle, i_img_dim points, int smooth );
119 static void i_tt_init_raster_map( TT_Raster_Map* bit, i_img_dim width, i_img_dim height, int smooth );
120 static void i_tt_done_raster_map( TT_Raster_Map *bit );
121 static void i_tt_clear_raster_map( TT_Raster_Map* bit );
122 static void i_tt_blit_or( TT_Raster_Map *dst, TT_Raster_Map *src,i_img_dim x_off, i_img_dim y_off );
123 static int i_tt_get_glyph( TT_Fonthandle *handle, int inst, unsigned long j );
124 static void
125 i_tt_render_glyph( TT_Glyph glyph, TT_Glyph_Metrics* gmetrics,
126 TT_Raster_Map *bit, TT_Raster_Map *small_bit,
127 i_img_dim x_off, i_img_dim y_off, int smooth );
128 static int
129 i_tt_render_all_glyphs( TT_Fonthandle *handle, int inst, TT_Raster_Map *bit,
130 TT_Raster_Map *small_bit, i_img_dim cords[6],
131 char const* txt, size_t len, int smooth, int utf8 );
132 static void i_tt_dump_raster_map2( i_img* im, TT_Raster_Map* bit, i_img_dim xb, i_img_dim yb, const i_color *cl, int smooth );
133 static void i_tt_dump_raster_map_channel( i_img* im, TT_Raster_Map* bit, i_img_dim xb, i_img_dim yb, int channel, int smooth );
134 static int
135 i_tt_rasterize( TT_Fonthandle *handle, TT_Raster_Map *bit, i_img_dim cords[6],
136 double points, char const* txt, size_t len, int smooth, int utf8 );
137 static undef_int i_tt_bbox_inst( TT_Fonthandle *handle, int inst ,const char *txt, size_t len, i_img_dim cords[6], int utf8 );
138
139
140 /* static globals needed */
141
142 static int LTT_dpi = 72; /* FIXME: this ought to be a part of the call interface */
143 static int LTT_hinted = 1; /* FIXME: this too */
144
145
146 /*
147 * FreeType interface
148 */
149
150 void
151 i_tt_start(void) {
152 if (slot == -1)
153 slot = im_context_slot_new(i_tt_uninit);
154 }
155
156
157 /*
158 =item init_tt()
159
160 Initializes the freetype font rendering engine (if needed)
161
162 =cut
163 */
164
165 static i_tt_engine *
166 i_init_tt(void) {
167 TT_Error error;
168 im_context_t ctx = im_get_context();
169 TT_Byte palette[] = { 0, 64, 127, 191, 255 };
170 i_tt_engine *result = im_context_slot_get(ctx, slot);
171
172 i_clear_error();
173
174 if (result == NULL) {
175 result = mymalloc(sizeof(i_tt_engine));
176 memset(result, 0, sizeof(*result));
177 im_context_slot_set(ctx, slot, result);
178 mm_log((1, "allocated FT1 state %p\n", result));
179 }
180
181 mm_log((1,"init_tt()\n"));
182
183 if (result->initialized)
184 return result;
185
186 error = TT_Init_FreeType( &result->engine );
187 if ( error ){
188 mm_log((1,"Initialization of freetype failed, code = 0x%x\n",
189 (unsigned)error));
190 i_tt_push_error(error);
191 i_push_error(0, "Could not initialize freetype 1.x");
192 return NULL;
193 }
194
195 #ifdef FTXPOST
196 error = TT_Init_Post_Extension( result->engine );
197 if (error) {
198 mm_log((1, "Initialization of Post extension failed = 0x%x\n",
199 (unsigned)error));
200
201 i_tt_push_error(error);
202 i_push_error(0, "Could not initialize FT 1.x POST extension");
203 return NULL;
204 }
205 #endif
206
207 error = TT_Set_Raster_Gray_Palette(result->engine, palette);
208 if (error) {
209 mm_log((1, "Initialization of gray levels failed = 0x%x\n",
210 (unsigned)error));
211 i_tt_push_error(error);
212 i_push_error(0, "Could not initialize FT 1.x POST extension");
213 return NULL;
214 }
215
216 mm_log((1, "initialized FT1 state %p\n", result));
217
218 result->initialized = 1;
219
220 return result;
221 }
222
223 static void
224 i_tt_uninit(void *p) {
225 i_tt_engine *tteng = p;
226
227 if (tteng->initialized) {
228 mm_log((1, "finalizing FT1 state %p\n", tteng));
229 TT_Done_FreeType(tteng->engine);
230 }
231 mm_log((1, "freeing FT1 state %p\n", tteng));
232 myfree(tteng);
233 }
234
235 /*
236 =item i_tt_get_instance(handle, points, smooth)
237
238 Finds a points+smooth instance or if one doesn't exist in the cache
239 allocates room and returns its cache entry
240
241 fontname - path to the font to load
242 handle - handle to the font.
243 points - points of the requested font
244 smooth - boolean (True: antialias on, False: antialias is off)
245
246 =cut
247 */
248
249 static
250 int
251 i_tt_get_instance( TT_Fonthandle *handle, i_img_dim points, int smooth ) {
252 int i,idx;
253 TT_Error error;
254
255 mm_log((1,"i_tt_get_instance(handle %p, points %" i_DF ", smooth %d)\n",
256 handle, i_DFc(points), smooth));
257
258 if (smooth == -1) { /* Smooth doesn't matter for this search */
259 for(i=0;i<TT_CHC;i++) {
260 if (handle->instanceh[i].ptsize==points) {
261 mm_log((1,"i_tt_get_instance: in cache - (non selective smoothing search) returning %d\n",i));
262 return i;
263 }
264 }
265 smooth=1; /* We will be adding a font - add it as smooth then */
266 } else { /* Smooth doesn't matter for this search */
267 for(i=0;i<TT_CHC;i++) {
268 if (handle->instanceh[i].ptsize == points
269 && handle->instanceh[i].smooth == smooth) {
270 mm_log((1,"i_tt_get_instance: in cache returning %d\n",i));
271 return i;
272 }
273 }
274 }
275
276 /* Found the instance in the cache - return the cache index */
277
278 for(idx=0;idx<TT_CHC;idx++) {
279 if (!(handle->instanceh[idx].order)) break; /* find the lru item */
280 }
281
282 mm_log((1,"i_tt_get_instance: lru item is %d\n",idx));
283 mm_log((1,"i_tt_get_instance: lru pointer %p\n",
284 USTRCT(handle->instanceh[idx].instance) ));
285
286 if ( USTRCT(handle->instanceh[idx].instance) ) {
287 mm_log((1,"i_tt_get_instance: freeing lru item from cache %d\n",idx));
288
289 /* Free cached glyphs */
290 for(i=0;i<256;i++)
291 if ( USTRCT(handle->instanceh[idx].glyphs[i].glyph) )
292 TT_Done_Glyph( handle->instanceh[idx].glyphs[i].glyph );
293
294 for(i=0;i<256;i++) {
295 handle->instanceh[idx].glyphs[i].ch = TT_NOCHAR;
296 USTRCT(handle->instanceh[idx].glyphs[i].glyph)=NULL;
297 }
298
299 /* Free instance if needed */
300 TT_Done_Instance( handle->instanceh[idx].instance );
301 }
302
303 /* create and initialize instance */
304 /* FIXME: probably a memory leak on fail */
305
306 (void) (( error = TT_New_Instance( handle->face, &handle->instanceh[idx].instance ) ) ||
307 ( error = TT_Set_Instance_Resolutions( handle->instanceh[idx].instance, LTT_dpi, LTT_dpi ) ) ||
308 ( error = TT_Set_Instance_CharSize( handle->instanceh[idx].instance, points*64 ) ) );
309
310 if ( error ) {
311 mm_log((1, "Could not create and initialize instance: error %x.\n",
312 (unsigned)error ));
313 return -1;
314 }
315
316 /* Now that the instance should the inplace we need to lower all of the
317 ru counts and put `this' one with the highest entry */
318
319 for(i=0;i<TT_CHC;i++) handle->instanceh[i].order--;
320
321 handle->instanceh[idx].order=TT_CHC-1;
322 handle->instanceh[idx].ptsize=points;
323 handle->instanceh[idx].smooth=smooth;
324 TT_Get_Instance_Metrics( handle->instanceh[idx].instance, &(handle->instanceh[idx].imetrics) );
325
326 /* Zero the memory for the glyph storage so they are not thought as
327 cached if they haven't been cached since this new font was loaded */
328
329 for(i=0;i<256;i++) {
330 handle->instanceh[idx].glyphs[i].ch = TT_NOCHAR;
331 USTRCT(handle->instanceh[idx].glyphs[i].glyph)=NULL;
332 }
333
334 return idx;
335 }
336
337
338 /*
339 =item i_tt_new(fontname)
340
341 Creates a new font handle object, finds a character map and initialise the
342 the font handle's cache
343
344 fontname - path to the font to load
345
346 =cut
347 */
348
349 TT_Fonthandle*
350 i_tt_new(const char *fontname) {
351 TT_Error error;
352 TT_Fonthandle *handle;
353 unsigned short i,n;
354 unsigned short platform,encoding;
355 i_tt_engine *tteng;
356
357 if ((tteng = i_init_tt()) == NULL) {
358 i_push_error(0, "Could not initialize FT1 engine");
359 return NULL;
360 }
361
362 i_clear_error();
363
364 mm_log((1,"i_tt_new(fontname '%s')\n",fontname));
365
366 /* allocate memory for the structure */
367
368 handle = mymalloc( sizeof(TT_Fonthandle) ); /* checked 5Nov05 tonyc */
369
370 /* load the typeface */
371 error = TT_Open_Face( tteng->engine, fontname, &handle->face );
372 if ( error ) {
373 if ( error == TT_Err_Could_Not_Open_File ) {
374 mm_log((1, "Could not find/open %s.\n", fontname ));
375 }
376 else {
377 mm_log((1, "Error while opening %s, error code = 0x%x.\n",fontname,
378 (unsigned)error ));
379 }
380 i_tt_push_error(error);
381 return NULL;
382 }
383
384 TT_Get_Face_Properties( handle->face, &(handle->properties) );
385
386 /* First, look for a Unicode charmap */
387 n = handle->properties.num_CharMaps;
388 USTRCT( handle->char_map )=NULL; /* Invalidate character map */
389
390 for ( i = 0; i < n; i++ ) {
391 TT_Get_CharMap_ID( handle->face, i, &platform, &encoding );
392 if ( (platform == 3 && encoding == 1 )
393 || (platform == 0 && encoding == 0 ) ) {
394 mm_log((2,"i_tt_new - found char map platform %u encoding %u\n",
395 platform, encoding));
396 TT_Get_CharMap( handle->face, i, &(handle->char_map) );
397 break;
398 }
399 }
400 if (!USTRCT(handle->char_map) && n != 0) {
401 /* just use the first one */
402 TT_Get_CharMap( handle->face, 0, &(handle->char_map));
403 }
404
405 /* Zero the pointsizes - and ordering */
406
407 for(i=0;i<TT_CHC;i++) {
408 USTRCT(handle->instanceh[i].instance)=NULL;
409 handle->instanceh[i].order=i;
410 handle->instanceh[i].ptsize=0;
411 handle->instanceh[i].smooth=-1;
412 }
413
414 #ifdef FTXPOST
415 handle->loaded_names = 0;
416 #endif
417
418 mm_log((1,"i_tt_new <- %p\n",handle));
419 return handle;
420 }
421
422
423
424 /*
425 * raster map management
426 */
427
428 /*
429 =item i_tt_init_raster_map(bit, width, height, smooth)
430
431 Allocates internal memory for the bitmap as needed by the parameters (internal)
432
433 bit - bitmap to allocate into
434 width - width of the bitmap
435 height - height of the bitmap
436 smooth - boolean (True: antialias on, False: antialias is off)
437
438 =cut
439 */
440
441 static
442 void
443 i_tt_init_raster_map( TT_Raster_Map* bit, i_img_dim width, i_img_dim height, int smooth ) {
444
445 mm_log((1,"i_tt_init_raster_map( bit %p, width %" i_DF ", height %" i_DF
446 ", smooth %d)\n", bit, i_DFc(width), i_DFc(height), smooth));
447
448 bit->rows = height;
449 bit->width = ( width + 3 ) & -4;
450 bit->flow = TT_Flow_Down;
451
452 if ( smooth ) {
453 bit->cols = bit->width;
454 bit->size = bit->rows * bit->width;
455 } else {
456 bit->cols = ( bit->width + 7 ) / 8; /* convert to # of bytes */
457 bit->size = bit->rows * bit->cols; /* number of bytes in buffer */
458 }
459
460 /* rows can be 0 for some glyphs, for example ' ' */
461 if (bit->rows && bit->size / bit->rows != bit->cols) {
462 i_fatal(0, "Integer overflow calculating bitmap size (%d, %d)\n",
463 bit->width, bit->rows);
464 }
465
466 mm_log((1,"i_tt_init_raster_map: bit->width %d, bit->cols %d, bit->rows %d, bit->size %ld)\n", bit->width, bit->cols, bit->rows, bit->size ));
467
468 bit->bitmap = (void *) mymalloc( bit->size ); /* checked 6Nov05 tonyc */
469 if ( !bit->bitmap ) i_fatal(0,"Not enough memory to allocate bitmap (%d)!\n",bit->size );
470 }
471
472
473 /*
474 =item i_tt_clear_raster_map(bit)
475
476 Frees the bitmap data and sets pointer to NULL (internal)
477
478 bit - bitmap to free
479
480 =cut
481 */
482
483 static
484 void
485 i_tt_done_raster_map( TT_Raster_Map *bit ) {
486 myfree( bit->bitmap );
487 bit->bitmap = NULL;
488 }
489
490
491 /*
492 =item i_tt_clear_raster_map(bit)
493
494 Clears the specified bitmap (internal)
495
496 bit - bitmap to zero
497
498 =cut
499 */
500
501
502 static
503 void
504 i_tt_clear_raster_map( TT_Raster_Map* bit ) {
505 memset( bit->bitmap, 0, bit->size );
506 }
507
508
509 /*
510 =item i_tt_blit_or(dst, src, x_off, y_off)
511
512 function that blits one raster map into another (internal)
513
514 dst - destination bitmap
515 src - source bitmap
516 x_off - x offset into the destination bitmap
517 y_off - y offset into the destination bitmap
518
519 =cut
520 */
521
522 static
523 void
524 i_tt_blit_or( TT_Raster_Map *dst, TT_Raster_Map *src,i_img_dim x_off, i_img_dim y_off ) {
525 i_img_dim x, y;
526 i_img_dim x1, x2, y1, y2;
527 unsigned char *s, *d;
528
529 x1 = x_off < 0 ? -x_off : 0;
530 y1 = y_off < 0 ? -y_off : 0;
531
532 x2 = (int)dst->cols - x_off;
533 if ( x2 > src->cols ) x2 = src->cols;
534
535 y2 = (int)dst->rows - y_off;
536 if ( y2 > src->rows ) y2 = src->rows;
537
538 if ( x1 >= x2 ) return;
539
540 /* do the real work now */
541
542 for ( y = y1; y < y2; ++y ) {
543 s = ( (unsigned char*)src->bitmap ) + y * src->cols + x1;
544 d = ( (unsigned char*)dst->bitmap ) + ( y + y_off ) * dst->cols + x1 + x_off;
545
546 for ( x = x1; x < x2; ++x ) {
547 if (*s > *d)
548 *d = *s;
549 d++;
550 s++;
551 }
552 }
553 }
554
555 /* useful for debugging */
556 #if 0
557
558 static void dump_raster_map(FILE *out, TT_Raster_Map *bit ) {
559 int x, y;
560 fprintf(out, "cols %d rows %d flow %d\n", bit->cols, bit->rows, bit->flow);
561 for (y = 0; y < bit->rows; ++y) {
562 fprintf(out, "%2d:", y);
563 for (x = 0; x < bit->cols; ++x) {
564 if ((x & 7) == 0 && x) putc(' ', out);
565 fprintf(out, "%02x", ((unsigned char *)bit->bitmap)[y*bit->cols+x]);
566 }
567 putc('\n', out);
568 }
569 }
570
571 #endif
572
573 /*
574 =item i_tt_get_glyph(handle, inst, j)
575
576 Function to see if a glyph exists and if so cache it (internal)
577
578 handle - pointer to font handle
579 inst - font instance
580 j - charcode of glyph
581
582 =cut
583 */
584
585 static
586 int
587 i_tt_get_glyph( TT_Fonthandle *handle, int inst, unsigned long j) {
588 unsigned short load_flags, code;
589 TT_Error error;
590
591 mm_log((1, "i_tt_get_glyph(handle %p, inst %d, j %lu (%c))\n",
592 handle,inst,j, (int)((j >= ' ' && j <= '~') ? j : '.')));
593
594 /*mm_log((1, "handle->instanceh[inst].glyphs[j]=0x%08X\n",handle->instanceh[inst].glyphs[j] ));*/
595
596 if ( TT_VALID(handle->instanceh[inst].glyphs[TT_HASH(j)].glyph)
597 && handle->instanceh[inst].glyphs[TT_HASH(j)].ch == j) {
598 mm_log((1,"i_tt_get_glyph: %lu in cache\n",j));
599 return 1;
600 }
601
602 if ( TT_VALID(handle->instanceh[inst].glyphs[TT_HASH(j)].glyph) ) {
603 /* clean up the entry */
604 TT_Done_Glyph( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph );
605 USTRCT( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph ) = NULL;
606 handle->instanceh[inst].glyphs[TT_HASH(j)].ch = TT_NOCHAR;
607 }
608
609 /* Ok - it wasn't cached - try to get it in */
610 load_flags = TTLOAD_SCALE_GLYPH;
611 if ( LTT_hinted ) load_flags |= TTLOAD_HINT_GLYPH;
612
613 if ( !TT_VALID(handle->char_map) ) {
614 code = (j - ' ' + 1) < 0 ? 0 : (j - ' ' + 1);
615 if ( code >= handle->properties.num_Glyphs ) code = 0;
616 } else code = TT_Char_Index( handle->char_map, j );
617
618 if ( (error = TT_New_Glyph( handle->face, &handle->instanceh[inst].glyphs[TT_HASH(j)].glyph)) ) {
619 mm_log((1, "Cannot allocate and load glyph: error %#x.\n", (unsigned)error ));
620 i_push_error(error, "TT_New_Glyph()");
621 return 0;
622 }
623 if ( (error = TT_Load_Glyph( handle->instanceh[inst].instance, handle->instanceh[inst].glyphs[TT_HASH(j)].glyph, code, load_flags)) ) {
624 mm_log((1, "Cannot allocate and load glyph: error %#x.\n", (unsigned)error ));
625 /* Don't leak */
626 TT_Done_Glyph( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph );
627 USTRCT( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph ) = NULL;
628 i_push_error(error, "TT_Load_Glyph()");
629 return 0;
630 }
631
632 /* At this point the glyph should be allocated and loaded */
633 handle->instanceh[inst].glyphs[TT_HASH(j)].ch = j;
634
635 /* Next get the glyph metrics */
636 error = TT_Get_Glyph_Metrics( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph,
637 &handle->instanceh[inst].gmetrics[TT_HASH(j)] );
638 if (error) {
639 mm_log((1, "TT_Get_Glyph_Metrics: error %#x.\n", (unsigned)error ));
640 TT_Done_Glyph( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph );
641 USTRCT( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph ) = NULL;
642 handle->instanceh[inst].glyphs[TT_HASH(j)].ch = TT_NOCHAR;
643 i_push_error(error, "TT_Get_Glyph_Metrics()");
644 return 0;
645 }
646
647 return 1;
648 }
649
650 /*
651 =item i_tt_has_chars(handle, text, len, utf8, out)
652
653 Check if the given characters are defined by the font. Note that len
654 is the number of bytes, not the number of characters (when utf8 is
655 non-zero).
656
657 Returns the number of characters that were checked.
658
659 =cut
660 */
661
662 size_t
663 i_tt_has_chars(TT_Fonthandle *handle, char const *text, size_t len, int utf8,
664 char *out) {
665 size_t count = 0;
666 mm_log((1, "i_tt_has_chars(handle %p, text %p, len %ld, utf8 %d)\n",
667 handle, text, (long)len, utf8));
668
669 while (len) {
670 unsigned long c;
671 int index;
672 if (utf8) {
673 c = i_utf8_advance(&text, &len);
674 if (c == ~0UL) {
675 i_push_error(0, "invalid UTF8 character");
676 return 0;
677 }
678 }
679 else {
680 c = (unsigned char)*text++;
681 --len;
682 }
683
684 if (TT_VALID(handle->char_map)) {
685 index = TT_Char_Index(handle->char_map, c);
686 }
687 else {
688 index = (c - ' ' + 1) < 0 ? 0 : (c - ' ' + 1);
689 if (index >= handle->properties.num_Glyphs)
690 index = 0;
691 }
692 *out++ = index != 0;
693 ++count;
694 }
695
696 return count;
697 }
698
699 /*
700 =item i_tt_destroy(handle)
701
702 Clears the data taken by a font including all cached data such as
703 pixmaps and glyphs
704
705 handle - pointer to font handle
706
707 =cut
708 */
709
710 void
711 i_tt_destroy( TT_Fonthandle *handle) {
712 TT_Close_Face( handle->face );
713 myfree( handle );
714
715 /* FIXME: Should these be freed automatically by the library?
716
717 TT_Done_Instance( instance );
718 void
719 i_tt_done_glyphs( void ) {
720 int i;
721
722 if ( !glyphs ) return;
723
724 for ( i = 0; i < 256; ++i ) TT_Done_Glyph( glyphs[i] );
725 free( glyphs );
726
727 glyphs = NULL;
728 }
729 */
730 }
731
732
733 /*
734 * FreeType Rendering functions
735 */
736
737
738 /*
739 =item i_tt_render_glyph(handle, gmetrics, bit, smallbit, x_off, y_off, smooth)
740
741 Renders a single glyph into the bit rastermap (internal)
742
743 handle - pointer to font handle
744 gmetrics - the metrics for the glyph to be rendered
745 bit - large bitmap that is the destination for the text
746 smallbit - small bitmap that is used only if smooth is true
747 x_off - x offset of glyph
748 y_off - y offset of glyph
749 smooth - boolean (True: antialias on, False: antialias is off)
750
751 =cut
752 */
753
754 static
755 void
756 i_tt_render_glyph( TT_Glyph glyph, TT_Glyph_Metrics* gmetrics, TT_Raster_Map *bit, TT_Raster_Map *small_bit, i_img_dim x_off, i_img_dim y_off, int smooth ) {
757
758 mm_log((1,"i_tt_render_glyph(glyph %p, gmetrics %p, bit %p, small_bit %p, x_off %" i_DF ", y_off %" i_DF ", smooth %d)\n",
759 USTRCT(glyph), gmetrics, bit, small_bit, i_DFc(x_off),
760 i_DFc(y_off), smooth));
761
762 if ( !smooth ) TT_Get_Glyph_Bitmap( glyph, bit, x_off * 64, y_off * 64);
763 else {
764 TT_F26Dot6 xmin, ymin, xmax, ymax;
765
766 xmin = gmetrics->bbox.xMin & -64;
767 ymin = gmetrics->bbox.yMin & -64;
768 xmax = (gmetrics->bbox.xMax + 63) & -64;
769 ymax = (gmetrics->bbox.yMax + 63) & -64;
770
771 i_tt_clear_raster_map( small_bit );
772 TT_Get_Glyph_Pixmap( glyph, small_bit, -xmin, -ymin );
773 i_tt_blit_or( bit, small_bit, xmin/64 + x_off, -ymin/64 - y_off );
774 }
775 }
776
777
778 /*
779 =item i_tt_render_all_glyphs(handle, inst, bit, small_bit, cords, txt, len, smooth)
780
781 calls i_tt_render_glyph to render each glyph into the bit rastermap (internal)
782
783 handle - pointer to font handle
784 inst - font instance
785 bit - large bitmap that is the destination for the text
786 smallbit - small bitmap that is used only if smooth is true
787 txt - string to render
788 len - length of the string to render
789 smooth - boolean (True: antialias on, False: antialias is off)
790
791 =cut
792 */
793
794 static
795 int
796 i_tt_render_all_glyphs( TT_Fonthandle *handle, int inst, TT_Raster_Map *bit,
797 TT_Raster_Map *small_bit, i_img_dim cords[6],
798 char const* txt, size_t len, int smooth, int utf8 ) {
799 unsigned long j;
800 TT_F26Dot6 x,y;
801
802 mm_log((1,"i_tt_render_all_glyphs( handle %p, inst %d, bit %p, small_bit %p, txt '%.*s', len %ld, smooth %d, utf8 %d)\n",
803 handle, inst, bit, small_bit, (int)len, txt, (long)len, smooth, utf8));
804
805 /*
806 y=-( handle->properties.horizontal->Descender * handle->instanceh[inst].imetrics.y_ppem )/(handle->properties.header->Units_Per_EM);
807 */
808
809 x=-cords[0]; /* FIXME: If you font is antialiased this should be expanded by one to allow for aa expansion and the allocation too - do before passing here */
810 y=-cords[4];
811
812 while (len) {
813 if (utf8) {
814 j = i_utf8_advance(&txt, &len);
815 if (j == ~0UL) {
816 i_push_error(0, "invalid UTF8 character");
817 return 0;
818 }
819 }
820 else {
821 j = (unsigned char)*txt++;
822 --len;
823 }
824 if ( !i_tt_get_glyph(handle,inst,j) )
825 continue;
826 i_tt_render_glyph( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph,
827 &handle->instanceh[inst].gmetrics[TT_HASH(j)], bit,
828 small_bit, x, y, smooth );
829 x += handle->instanceh[inst].gmetrics[TT_HASH(j)].advance / 64;
830 }
831
832 return 1;
833 }
834
835
836 /*
837 * Functions to render rasters (single channel images) onto images
838 */
839
840 /*
841 =item i_tt_dump_raster_map2(im, bit, xb, yb, cl, smooth)
842
843 Function to dump a raster onto an image in color used by i_tt_text() (internal).
844
845 im - image to dump raster on
846 bit - bitmap that contains the text to be dumped to im
847 xb, yb - coordinates, left edge and baseline
848 cl - color to use for text
849 smooth - boolean (True: antialias on, False: antialias is off)
850
851 =cut
852 */
853
854 static
855 void
856 i_tt_dump_raster_map2( i_img* im, TT_Raster_Map* bit, i_img_dim xb, i_img_dim yb, const i_color *cl, int smooth ) {
857 unsigned char *bmap;
858 i_img_dim x, y;
859 mm_log((1,"i_tt_dump_raster_map2(im %p, bit %p, xb %" i_DF ", yb %" i_DF ", cl %p)\n",
860 im, bit, i_DFc(xb), i_DFc(yb), cl));
861
862 bmap = bit->bitmap;
863
864 if ( smooth ) {
865
866 i_render r;
867 i_render_init(&r, im, bit->cols);
868 for(y=0;y<bit->rows;y++) {
869 i_render_color(&r, xb, yb+y, bit->cols, bmap + y*bit->cols, cl);
870 }
871 i_render_done(&r);
872 } else {
873 for(y=0;y<bit->rows;y++) {
874 unsigned mask = 0x80;
875 unsigned char *p = bmap + y * bit->cols;
876
877 for(x = 0; x < bit->width; x++) {
878 if (*p & mask) {
879 i_ppix(im, x+xb, y+yb, cl);
880 }
881 mask >>= 1;
882 if (!mask) {
883 mask = 0x80;
884 ++p;
885 }
886 }
887 }
888
889 }
890 }
891
892
893 /*
894 =item i_tt_dump_raster_map_channel(im, bit, xb, yb, channel, smooth)
895
896 Function to dump a raster onto a single channel image in color (internal)
897
898 im - image to dump raster on
899 bit - bitmap that contains the text to be dumped to im
900 xb, yb - coordinates, left edge and baseline
901 channel - channel to copy to
902 smooth - boolean (True: antialias on, False: antialias is off)
903
904 =cut
905 */
906
907 static
908 void
909 i_tt_dump_raster_map_channel( i_img* im, TT_Raster_Map* bit, i_img_dim xb, i_img_dim yb, int channel, int smooth ) {
910 unsigned char *bmap;
911 i_color val;
912 int c;
913 i_img_dim x,y;
914 int old_mask = im->ch_mask;
915 im->ch_mask = 1 << channel;
916
917 mm_log((1,"i_tt_dump_raster_channel(im %p, bit %p, xb %" i_DF ", yb %" i_DF ", channel %d)\n",
918 im, bit, i_DFc(xb), i_DFc(yb), channel));
919
920 bmap = bit->bitmap;
921
922 if ( smooth ) {
923 for(y=0;y<bit->rows;y++) for(x=0;x<bit->width;x++) {
924 c = bmap[y*(bit->cols)+x];
925 val.channel[channel] = c;
926 i_ppix(im,x+xb,y+yb,&val);
927 }
928 } else {
929 for(y=0;y<bit->rows;y++) {
930 unsigned mask = 0x80;
931 unsigned char *p = bmap + y * bit->cols;
932
933 for(x=0;x<bit->width;x++) {
934 val.channel[channel] = (*p & mask) ? 255 : 0;
935 i_ppix(im,x+xb,y+yb,&val);
936
937 mask >>= 1;
938 if (!mask) {
939 ++p;
940 mask = 0x80;
941 }
942 }
943 }
944 }
945 im->ch_mask = old_mask;
946 }
947
948
949 /*
950 =item i_tt_rasterize(handle, bit, cords, points, txt, len, smooth)
951
952 interface for generating single channel raster of text (internal)
953
954 handle - pointer to font handle
955 bit - the bitmap that is allocated, rendered into and NOT freed
956 cords - the bounding box (modified in place)
957 points - font size to use
958 txt - string to render
959 len - length of the string to render
960 smooth - boolean (True: antialias on, False: antialias is off)
961
962 =cut
963 */
964
965 static
966 int
967 i_tt_rasterize( TT_Fonthandle *handle, TT_Raster_Map *bit, i_img_dim cords[6], double points, char const* txt, size_t len, int smooth, int utf8 ) {
968 int inst;
969 i_img_dim width, height;
970 TT_Raster_Map small_bit;
971
972 /* find or install an instance */
973 if ( (inst=i_tt_get_instance(handle,points,smooth)) < 0) {
974 mm_log((1,"i_tt_rasterize: get instance failed\n"));
975 return 0;
976 }
977
978 /* calculate bounding box */
979 if (!i_tt_bbox_inst( handle, inst, txt, len, cords, utf8 ))
980 return 0;
981
982
983 width = cords[2]-cords[0];
984 height = cords[5]-cords[4];
985
986 mm_log((1,"i_tt_rasterize: width=%" i_DF ", height=%" i_DF "\n",
987 i_DFc(width), i_DFc(height) ));
988
989 i_tt_init_raster_map ( bit, width, height, smooth );
990 i_tt_clear_raster_map( bit );
991 if ( smooth ) i_tt_init_raster_map( &small_bit, handle->instanceh[inst].imetrics.x_ppem + 32, height, smooth );
992
993 if (!i_tt_render_all_glyphs( handle, inst, bit, &small_bit, cords, txt, len,
994 smooth, utf8 )) {
995 if ( smooth )
996 i_tt_done_raster_map( &small_bit );
997 return 0;
998 }
999
1000 if ( smooth ) i_tt_done_raster_map( &small_bit );
1001 return 1;
1002 }
1003
1004
1005
1006 /*
1007 * Exported text rendering interfaces
1008 */
1009
1010
1011 /*
1012 =item i_tt_cp(handle, im, xb, yb, channel, points, txt, len, smooth, utf8)
1013
1014 Interface to text rendering into a single channel in an image
1015
1016 handle - pointer to font handle
1017 im - image to render text on to
1018 xb, yb - coordinates, left edge and baseline
1019 channel - channel to render into
1020 points - font size to use
1021 txt - string to render
1022 len - length of the string to render
1023 smooth - boolean (True: antialias on, False: antialias is off)
1024
1025 =cut
1026 */
1027
1028 undef_int
1029 i_tt_cp( TT_Fonthandle *handle, i_img *im, i_img_dim xb, i_img_dim yb, int channel, double points, char const* txt, size_t len, int smooth, int utf8, int align ) {
1030
1031 i_img_dim cords[BOUNDING_BOX_COUNT];
1032 i_img_dim ascent, st_offset, y;
1033 TT_Raster_Map bit;
1034
1035 i_clear_error();
1036 if (! i_tt_rasterize( handle, &bit, cords, points, txt, len, smooth, utf8 ) ) return 0;
1037
1038 ascent=cords[BBOX_ASCENT];
1039 st_offset=cords[BBOX_NEG_WIDTH];
1040 y = align ? yb-ascent : yb;
1041
1042 i_tt_dump_raster_map_channel( im, &bit, xb-st_offset , y, channel, smooth );
1043 i_tt_done_raster_map( &bit );
1044
1045 return 1;
1046 }
1047
1048
1049 /*
1050 =item i_tt_text(handle, im, xb, yb, cl, points, txt, len, smooth, utf8)
1051
1052 Interface to text rendering in a single color onto an image
1053
1054 handle - pointer to font handle
1055 im - image to render text on to
1056 xb, yb - coordinates, left edge and baseline
1057 cl - color to use for text
1058 points - font size to use
1059 txt - string to render
1060 len - length of the string to render
1061 smooth - boolean (True: antialias on, False: antialias is off)
1062
1063 =cut
1064 */
1065
1066 undef_int
1067 i_tt_text( TT_Fonthandle *handle, i_img *im, i_img_dim xb, i_img_dim yb, const i_color *cl, double points, char const* txt, size_t len, int smooth, int utf8, int align) {
1068 i_img_dim cords[BOUNDING_BOX_COUNT];
1069 i_img_dim ascent, st_offset, y;
1070 TT_Raster_Map bit;
1071
1072 i_clear_error();
1073
1074 if (! i_tt_rasterize( handle, &bit, cords, points, txt, len, smooth, utf8 ) ) return 0;
1075
1076 ascent=cords[BBOX_ASCENT];
1077 st_offset=cords[BBOX_NEG_WIDTH];
1078 y = align ? yb-ascent : yb;
1079
1080 i_tt_dump_raster_map2( im, &bit, xb+st_offset, y, cl, smooth );
1081 i_tt_done_raster_map( &bit );
1082
1083 return 1;
1084 }
1085
1086
1087 /*
1088 =item i_tt_bbox_inst(handle, inst, txt, len, cords, utf8)
1089
1090 Function to get texts bounding boxes given the instance of the font (internal)
1091
1092 handle - pointer to font handle
1093 inst - font instance
1094 txt - string to measure
1095 len - length of the string to render
1096 cords - the bounding box (modified in place)
1097
1098 =cut
1099 */
1100
1101 static
1102 undef_int
1103 i_tt_bbox_inst( TT_Fonthandle *handle, int inst ,const char *txt, size_t len, i_img_dim cords[BOUNDING_BOX_COUNT], int utf8 ) {
1104 int upm, casc, cdesc, first;
1105
1106 int start = 0;
1107 i_img_dim width = 0;
1108 int gdescent = 0;
1109 int gascent = 0;
1110 int descent = 0;
1111 int ascent = 0;
1112 int rightb = 0;
1113
1114 unsigned long j;
1115 unsigned char *ustr;
1116 ustr=(unsigned char*)txt;
1117
1118 mm_log((1,"i_tt_box_inst(handle %p,inst %d,txt '%.*s', len %ld, utf8 %d)\n",
1119 handle, inst, (int)len, txt, (long)len, utf8));
1120
1121 upm = handle->properties.header->Units_Per_EM;
1122 gascent = ( handle->properties.horizontal->Ascender * handle->instanceh[inst].imetrics.y_ppem + upm - 1) / upm;
1123 gdescent = ( handle->properties.horizontal->Descender * handle->instanceh[inst].imetrics.y_ppem - upm + 1) / upm;
1124
1125 width = 0;
1126 start = 0;
1127
1128 mm_log((1, "i_tt_box_inst: gascent=%d gdescent=%d\n", gascent, gdescent));
1129
1130 first=1;
1131 while (len) {
1132 if (utf8) {
1133 j = i_utf8_advance(&txt, &len);
1134 if (j == ~0UL) {
1135 i_push_error(0, "invalid UTF8 character");
1136 return 0;
1137 }
1138 }
1139 else {
1140 j = (unsigned char)*txt++;
1141 --len;
1142 }
1143 if ( i_tt_get_glyph(handle,inst,j) ) {
1144 TT_Glyph_Metrics *gm = handle->instanceh[inst].gmetrics + TT_HASH(j);
1145 width += gm->advance / 64;
1146 casc = (gm->bbox.yMax+63) / 64;
1147 cdesc = (gm->bbox.yMin-63) / 64;
1148
1149 mm_log((1, "i_tt_box_inst: glyph='%c' casc=%d cdesc=%d\n",
1150 (int)((j >= ' ' && j <= '~') ? j : '.'), casc, cdesc));
1151
1152 if (first) {
1153 start = gm->bbox.xMin / 64;
1154 ascent = (gm->bbox.yMax+63) / 64;
1155 descent = (gm->bbox.yMin-63) / 64;
1156 first = 0;
1157 }
1158 if (!len) { /* if at end of string */
1159 /* the right-side bearing - in case the right-side of a
1160 character goes past the right of the advance width,
1161 as is common for italic fonts
1162 */
1163 rightb = gm->advance - gm->bearingX
1164 - (gm->bbox.xMax - gm->bbox.xMin);
1165 /* fprintf(stderr, "font info last: %d %d %d %d\n",
1166 gm->bbox.xMax, gm->bbox.xMin, gm->advance, rightb); */
1167 }
1168
1169 ascent = (ascent > casc ? ascent : casc );
1170 descent = (descent < cdesc ? descent : cdesc);
1171 }
1172 }
1173
1174 cords[BBOX_NEG_WIDTH]=start;
1175 cords[BBOX_GLOBAL_DESCENT]=gdescent;
1176 cords[BBOX_POS_WIDTH]=width;
1177 if (rightb < 0)
1178 cords[BBOX_POS_WIDTH] -= rightb / 64;
1179 cords[BBOX_GLOBAL_ASCENT]=gascent;
1180 cords[BBOX_DESCENT]=descent;
1181 cords[BBOX_ASCENT]=ascent;
1182 cords[BBOX_ADVANCE_WIDTH] = width;
1183 cords[BBOX_RIGHT_BEARING] = rightb / 64;
1184
1185 return BBOX_RIGHT_BEARING + 1;
1186 }
1187
1188
1189 /*
1190 =item i_tt_bbox(handle, points, txt, len, cords, utf8)
1191
1192 Interface to get a strings bounding box
1193
1194 handle - pointer to font handle
1195 points - font size to use
1196 txt - string to render
1197 len - length of the string to render
1198 cords - the bounding box (modified in place)
1199
1200 =cut
1201 */
1202
1203 undef_int
1204 i_tt_bbox( TT_Fonthandle *handle, double points,const char *txt,size_t len,i_img_dim cords[6], int utf8) {
1205 int inst;
1206
1207 i_clear_error();
1208 mm_log((1,"i_tt_box(handle %p,points %f,txt '%.*s', len %ld, utf8 %d)\n",
1209 handle, points, (int)len, txt, (long)len, utf8));
1210
1211 if ( (inst=i_tt_get_instance(handle,points,-1)) < 0) {
1212 i_push_errorf(0, "i_tt_get_instance(%g)", points);
1213 mm_log((1,"i_tt_text: get instance failed\n"));
1214 return 0;
1215 }
1216
1217 return i_tt_bbox_inst(handle, inst, txt, len, cords, utf8);
1218 }
1219
1220 /*
1221 =item i_tt_face_name(handle, name_buf, name_buf_size)
1222
1223 Retrieve's the font's postscript name.
1224
1225 This is complicated by the need to handle encodings and so on.
1226
1227 =cut
1228 */
1229 size_t
1230 i_tt_face_name(TT_Fonthandle *handle, char *name_buf, size_t name_buf_size) {
1231 TT_Face_Properties props;
1232 int name_count;
1233 int i;
1234 TT_UShort platform_id, encoding_id, lang_id, name_id;
1235 TT_UShort name_len;
1236 TT_String *name;
1237 int want_index = -1; /* an acceptable but not perfect name */
1238 int score = 0;
1239
1240 i_clear_error();
1241
1242 TT_Get_Face_Properties(handle->face, &props);
1243 name_count = props.num_Names;
1244 for (i = 0; i < name_count; ++i) {
1245 TT_Get_Name_ID(handle->face, i, &platform_id, &encoding_id, &lang_id,
1246 &name_id);
1247
1248 TT_Get_Name_String(handle->face, i, &name, &name_len);
1249
1250 if (platform_id != TT_PLATFORM_APPLE_UNICODE && name_len
1251 && name_id == TT_NAME_ID_PS_NAME) {
1252 int might_want_index = -1;
1253 int might_score = 0;
1254 if ((platform_id == TT_PLATFORM_MACINTOSH && encoding_id == TT_MAC_ID_ROMAN)
1255 ||
1256 (platform_id == TT_PLATFORM_MICROSOFT && encoding_id == TT_MS_LANGID_ENGLISH_UNITED_STATES)) {
1257 /* exactly what we want */
1258 want_index = i;
1259 break;
1260 }
1261
1262 if (platform_id == TT_PLATFORM_MICROSOFT
1263 && (encoding_id & 0xFF) == TT_MS_LANGID_ENGLISH_GENERAL) {
1264 /* any english is good */
1265 might_want_index = i;
1266 might_score = 9;
1267 }
1268 /* there might be something in between */
1269 else {
1270 /* anything non-unicode is better than nothing */
1271 might_want_index = i;
1272 might_score = 1;
1273 }
1274 if (might_score > score) {
1275 score = might_score;
1276 want_index = might_want_index;
1277 }
1278 }
1279 }
1280
1281 if (want_index != -1) {
1282 TT_Get_Name_String(handle->face, want_index, &name, &name_len);
1283
1284 strncpy(name_buf, name, name_buf_size);
1285 name_buf[name_buf_size-1] = '\0';
1286
1287 return strlen(name) + 1;
1288 }
1289 else {
1290 i_push_error(0, "no face name present");
1291 return 0;
1292 }
1293 }
1294
1295 void i_tt_dump_names(TT_Fonthandle *handle) {
1296 TT_Face_Properties props;
1297 int name_count;
1298 int i;
1299 TT_UShort platform_id, encoding_id, lang_id, name_id;
1300 TT_UShort name_len;
1301 TT_String *name;
1302
1303 TT_Get_Face_Properties(handle->face, &props);
1304 name_count = props.num_Names;
1305 for (i = 0; i < name_count; ++i) {
1306 TT_Get_Name_ID(handle->face, i, &platform_id, &encoding_id, &lang_id,
1307 &name_id);
1308 TT_Get_Name_String(handle->face, i, &name, &name_len);
1309
1310 printf("# %d: plat %d enc %d lang %d name %d value ", i, platform_id,
1311 encoding_id, lang_id, name_id);
1312 if (platform_id == TT_PLATFORM_APPLE_UNICODE) {
1313 printf("(unicode)\n");
1314 }
1315 else {
1316 printf("'%s'\n", name);
1317 }
1318 }
1319 fflush(stdout);
1320 }
1321
1322 size_t
1323 i_tt_glyph_name(TT_Fonthandle *handle, unsigned long ch, char *name_buf,
1324 size_t name_buf_size) {
1325 #ifdef FTXPOST
1326 TT_Error rc;
1327 TT_String *psname;
1328 TT_UShort index;
1329
1330 i_clear_error();
1331
1332 if (!handle->loaded_names) {
1333 TT_Post post;
1334 mm_log((1, "Loading PS Names"));
1335 handle->load_cond = TT_Load_PS_Names(handle->face, &post);
1336 ++handle->loaded_names;
1337 }
1338
1339 if (handle->load_cond) {
1340 i_push_errorf(handle->load_cond, "error loading names (%#x)",
1341 (unsigned)handle->load_cond);
1342 return 0;
1343 }
1344
1345 index = TT_Char_Index(handle->char_map, ch);
1346 if (!index) {
1347 i_push_error(0, "no such character");
1348 return 0;
1349 }
1350
1351 rc = TT_Get_PS_Name(handle->face, index, &psname);
1352
1353 if (rc) {
1354 i_push_error(rc, "error getting name");
1355 return 0;
1356 }
1357
1358 strncpy(name_buf, psname, name_buf_size);
1359 name_buf[name_buf_size-1] = '\0';
1360
1361 return strlen(psname) + 1;
1362 #else
1363 mm_log((1, "FTXPOST extension not enabled\n"));
1364 i_clear_error();
1365 i_push_error(0, "Use of FTXPOST extension disabled");
1366
1367 return 0;
1368 #endif
1369 }
1370
1371 /*
1372 =item i_tt_push_error(code)
1373
1374 Push an error message and code onto the Imager error stack.
1375
1376 =cut
1377 */
1378 static void
1379 i_tt_push_error(TT_Error rc) {
1380 #ifdef FTXERR18
1381 TT_String const *msg = TT_ErrToString18(rc);
1382
1383 i_push_error(rc, msg);
1384 #else
1385 i_push_errorf(rc, "Error code 0x%04x", (unsigned)rc);
1386 #endif
1387 }
1388
1389
1390 /*
1391 =back
1392
1393 =head1 AUTHOR
1394
1395 Arnar M. Hrafnkelsson <addi@umich.edu>
1396
1397 =head1 SEE ALSO
1398
1399 Imager(3)
1400
1401 =cut
1402 */
0 #define IMAGER_NO_CONTEXT
01 #include "imager.h"
12 #include <math.h>
23
2425 double res[MAXCHANNELS];
2526 i_img *timg;
2627 int radius, diameter;
28 dIMCTXim(im);
2729
28 mm_log((1,"i_gaussian(im %p, stdev %.2f)\n",im,stddev));
30 im_log((aIMCTX, 1,"i_gaussian(im %p, stdev %.2f)\n",im,stddev));
2931 i_clear_error();
3032
3133 if (stddev <= 0) {
0 #define IMAGER_NO_CONTEXT
01 #include "imageri.h"
12 #include <stdlib.h>
23
6768 size_t bytes = count_y * sizeof(i_int_hline_entry *);
6869
6970 if (bytes / count_y != sizeof(i_int_hline_entry *)) {
70 i_fatal(3, "integer overflow calculating memory allocation\n");
71 dIMCTX;
72 im_fatal(aIMCTX, 3, "integer overflow calculating memory allocation\n");
7173 }
7274
7375 hlines->start_y = start_y;
110112 i_img_dim x_limit = x + width;
111113
112114 if (width < 0) {
113 i_fatal(3, "negative width %d passed to i_int_hlines_add\n", width);
115 dIMCTX;
116 im_fatal(aIMCTX, 3, "negative width %d passed to i_int_hlines_add\n", width);
114117 }
115118
116119 /* just return if out of range */
0 #define IMAGER_NO_CONTEXT
1
02 #include "imager.h"
13 #include "imageri.h"
24
1113 i_color *c;
1214 c = i_color_new(red, green, blue, alpha);
1315 ICL_DESTROY(c);
14 i = i_img_new();
16 i = i_img_8_new();
1517 i_img_destroy(i);
1618 // and much more
1719
2830
2931 =cut
3032 */
33
34 im_context_t (*im_get_context)(void) = NULL;
3135
3236 #define XAXIS 0
3337 #define YAXIS 1
3943 void i_linker_bug_fake(void) { ceil(1); }
4044
4145 /*
42 =item i_img_alloc()
46 =item im_img_alloc(aIMCTX)
47 X<im_img_alloc API>X<i_img_alloc API>
4348 =category Image Implementation
49 =synopsis i_img *im = im_img_alloc(aIMCTX);
50 =synopsis i_img *im = i_img_alloc();
4451
4552 Allocates a new i_img structure.
4653
6976 */
7077
7178 i_img *
72 i_img_alloc(void) {
79 im_img_alloc(pIMCTX) {
7380 return mymalloc(sizeof(i_img));
7481 }
7582
7683 /*
77 =item i_img_init(C<img>)
84 =item im_img_init(aIMCTX, image)
85 X<im_img_init API>X<i_img_init API>
7886 =category Image Implementation
87 =synopsis im_img_init(aIMCTX, im);
88 =synopsis i_img_init(im);
7989
8090 Imager internal initialization of images.
8191
82 Currently this does very little, in the future it may be used to
83 support threads, or color profiles.
92 See L</im_img_alloc(aIMCTX)> for more information.
8493
8594 =cut
8695 */
8796
8897 void
89 i_img_init(i_img *img) {
98 im_img_init(pIMCTX, i_img *img) {
9099 img->im_data = NULL;
100 img->context = aIMCTX;
101 im_context_refinc(aIMCTX, "img_init");
91102 }
92103
93104 /*
106117 i_color *
107118 ICL_new_internal(unsigned char r,unsigned char g,unsigned char b,unsigned char a) {
108119 i_color *cl = NULL;
109
110 mm_log((1,"ICL_new_internal(r %d,g %d,b %d,a %d)\n", r, g, b, a));
111
112 if ( (cl=mymalloc(sizeof(i_color))) == NULL) i_fatal(2,"malloc() error\n");
120 dIMCTX;
121
122 im_log((aIMCTX,1,"ICL_new_internal(r %d,g %d,b %d,a %d)\n", r, g, b, a));
123
124 if ( (cl=mymalloc(sizeof(i_color))) == NULL) im_fatal(aIMCTX, 2,"malloc() error\n");
113125 cl->rgba.r = r;
114126 cl->rgba.g = g;
115127 cl->rgba.b = b;
116128 cl->rgba.a = a;
117 mm_log((1,"(%p) <- ICL_new_internal\n",cl));
129 im_log((aIMCTX,1,"(%p) <- ICL_new_internal\n",cl));
118130 return cl;
119131 }
120132
135147
136148 i_color *
137149 ICL_set_internal(i_color *cl,unsigned char r,unsigned char g,unsigned char b,unsigned char a) {
138 mm_log((1,"ICL_set_internal(cl* %p,r %d,g %d,b %d,a %d)\n",cl,r,g,b,a));
150 dIMCTX;
151 im_log((aIMCTX,1,"ICL_set_internal(cl* %p,r %d,g %d,b %d,a %d)\n",cl,r,g,b,a));
139152 if (cl == NULL)
140153 if ( (cl=mymalloc(sizeof(i_color))) == NULL)
141 i_fatal(2,"malloc() error\n");
154 im_fatal(aIMCTX, 2,"malloc() error\n");
142155 cl->rgba.r=r;
143156 cl->rgba.g=g;
144157 cl->rgba.b=b;
145158 cl->rgba.a=a;
146 mm_log((1,"(%p) <- ICL_set_internal\n",cl));
159 im_log((aIMCTX,1,"(%p) <- ICL_set_internal\n",cl));
147160 return cl;
148161 }
149162
181194
182195 void
183196 ICL_info(i_color const *cl) {
184 mm_log((1,"i_color_info(cl* %p)\n",cl));
185 mm_log((1,"i_color_info: (%d,%d,%d,%d)\n",cl->rgba.r,cl->rgba.g,cl->rgba.b,cl->rgba.a));
197 dIMCTX;
198 im_log((aIMCTX, 1,"i_color_info(cl* %p)\n",cl));
199 im_log((aIMCTX, 1,"i_color_info: (%d,%d,%d,%d)\n",cl->rgba.r,cl->rgba.g,cl->rgba.b,cl->rgba.a));
186200 }
187201
188202 /*
197211
198212 void
199213 ICL_DESTROY(i_color *cl) {
200 mm_log((1,"ICL_DESTROY(cl* %p)\n",cl));
214 dIMCTX;
215 im_log((aIMCTX, 1,"ICL_DESTROY(cl* %p)\n",cl));
201216 myfree(cl);
202217 }
203218
208223 */
209224 i_fcolor *i_fcolor_new(double r, double g, double b, double a) {
210225 i_fcolor *cl = NULL;
211
212 mm_log((1,"i_fcolor_new(r %g,g %g,b %g,a %g)\n", r, g, b, a));
213
214 if ( (cl=mymalloc(sizeof(i_fcolor))) == NULL) i_fatal(2,"malloc() error\n");
226 dIMCTX;
227
228 im_log((aIMCTX, 1,"i_fcolor_new(r %g,g %g,b %g,a %g)\n", r, g, b, a));
229
230 if ( (cl=mymalloc(sizeof(i_fcolor))) == NULL) im_fatal(aIMCTX, 2,"malloc() error\n");
215231 cl->rgba.r = r;
216232 cl->rgba.g = g;
217233 cl->rgba.b = b;
218234 cl->rgba.a = a;
219 mm_log((1,"(%p) <- i_fcolor_new\n",cl));
235 im_log((aIMCTX, 1,"(%p) <- i_fcolor_new\n",cl));
220236
221237 return cl;
222238 }
242258
243259 void
244260 i_img_exorcise(i_img *im) {
245 mm_log((1,"i_img_exorcise(im* %p)\n",im));
261 dIMCTXim(im);
262 im_log((aIMCTX,1,"i_img_exorcise(im* %p)\n",im));
246263 i_tags_destroy(&im->tags);
247264 if (im->i_f_destroy)
248265 (im->i_f_destroy)(im);
268285
269286 void
270287 i_img_destroy(i_img *im) {
271 mm_log((1,"i_img_destroy(im %p)\n",im));
288 dIMCTXim(im);
289 im_log((aIMCTX, 1,"i_img_destroy(im %p)\n",im));
272290 i_img_exorcise(im);
273291 if (im) { myfree(im); }
292 im_context_refdec(aIMCTX, "img_destroy");
274293 }
275294
276295 /*
296315
297316 void
298317 i_img_info(i_img *im, i_img_dim *info) {
299 mm_log((1,"i_img_info(im %p)\n",im));
318 dIMCTXim(im);
319 im_log((aIMCTX,1,"i_img_info(im %p)\n",im));
300320 if (im != NULL) {
301 mm_log((1,"i_img_info: xsize=%" i_DF " ysize=%" i_DF " channels=%d "
321 im_log((aIMCTX,1,"i_img_info: xsize=%" i_DF " ysize=%" i_DF " channels=%d "
302322 "mask=%ud\n",
303323 i_DFc(im->xsize), i_DFc(im->ysize), im->channels,im->ch_mask));
304 mm_log((1,"i_img_info: idata=%p\n",im->idata));
324 im_log((aIMCTX,1,"i_img_info: idata=%p\n",im->idata));
305325 info[0] = im->xsize;
306326 info[1] = im->ysize;
307327 info[2] = im->channels;
400420 i_color pv;
401421 i_img_dim x,y,t,ttx,tty,tt;
402422 int ch;
403
404 mm_log((1,"i_copyto_trans(im* %p,src %p, p1(" i_DFp "), p2(" i_DFp "), "
423 dIMCTXim(im);
424
425 im_log((aIMCTX, 1,"i_copyto_trans(im* %p,src %p, p1(" i_DFp "), p2(" i_DFp "), "
405426 "to(" i_DFp "), trans* %p)\n",
406427 im, src, i_DFcp(x1, y1), i_DFcp(x2, y2), i_DFcp(tx, ty), trans));
407428
444465 i_img *
445466 i_copy(i_img *src) {
446467 i_img_dim y, y1, x1;
468 dIMCTXim(src);
447469 i_img *im = i_sametype(src, src->xsize, src->ysize);
448470
449 mm_log((1,"i_copy(src %p)\n", src));
471 im_log((aIMCTX,1,"i_copy(src %p)\n", src));
450472
451473 if (!im)
452474 return NULL;
532554 i_img *new_img;
533555 int has_alpha = i_img_has_alpha(im);
534556 int color_chans = i_img_color_channels(im);
557 dIMCTXim(im);
535558
536559 i_clear_error();
537 mm_log((1,"i_scaleaxis(im %p,Value %.2f,Axis %d)\n",im,Value,Axis));
560 im_log((aIMCTX, 1,"i_scaleaxis(im %p,Value %.2f,Axis %d)\n",im,Value,Axis));
538561
539562 if (Axis == XAXIS) {
540563 hsize = (i_img_dim)(0.5 + im->xsize * Value);
559582 iEnd = hsize;
560583 }
561584
562 new_img = i_img_empty_ch(NULL, hsize, vsize, im->channels);
585 new_img = i_img_8_new(hsize, vsize, im->channels);
563586 if (!new_img) {
564587 i_push_error(0, "cannot create output image");
565588 return NULL;
709732 myfree(l0);
710733 myfree(l1);
711734
712 mm_log((1,"(%p) <- i_scaleaxis\n", new_img));
735 im_log((aIMCTX, 1,"(%p) <- i_scaleaxis\n", new_img));
713736
714737 return new_img;
715738 }
732755 i_img_dim nxsize,nysize,nx,ny;
733756 i_img *new_img;
734757 i_color val;
735
736 mm_log((1,"i_scale_nn(im %p,scx %.2f,scy %.2f)\n",im,scx,scy));
758 dIMCTXim(im);
759
760 im_log((aIMCTX, 1,"i_scale_nn(im %p,scx %.2f,scy %.2f)\n",im,scx,scy));
737761
738762 nxsize = (i_img_dim) ((double) im->xsize * scx);
739763 if (nxsize < 1) {
754778 i_ppix(new_img,nx,ny,&val);
755779 }
756780
757 mm_log((1,"(%p) <- i_scale_nn\n",new_img));
781 im_log((aIMCTX, 1,"(%p) <- i_scale_nn\n",new_img));
758782
759783 return new_img;
760784 }
772796 =cut
773797 */
774798
775 i_img *i_sametype(i_img *src, i_img_dim xsize, i_img_dim ysize) {
799 i_img *
800 i_sametype(i_img *src, i_img_dim xsize, i_img_dim ysize) {
801 dIMCTXim(src);
802
776803 if (src->type == i_direct_type) {
777804 if (src->bits == 8) {
778805 return i_img_empty_ch(NULL, xsize, ysize, src->channels);
815842 =cut
816843 */
817844
818 i_img *i_sametype_chans(i_img *src, i_img_dim xsize, i_img_dim ysize, int channels) {
845 i_img *
846 i_sametype_chans(i_img *src, i_img_dim xsize, i_img_dim ysize, int channels) {
847 dIMCTXim(src);
848
819849 if (src->bits == 8) {
820850 return i_img_empty_ch(NULL, xsize, ysize, channels);
821851 }
856886 i_img_dim nxsize,nysize,nx,ny;
857887 i_img *new_img;
858888 i_color val;
889 dIMCTXim(im);
859890
860 mm_log((1,"i_transform(im %p, opx %p, opxl %d, opy %p, opyl %d, parm %p, parmlen %d)\n",im,opx,opxl,opy,opyl,parm,parmlen));
891 im_log((aIMCTX, 1,"i_transform(im %p, opx %p, opxl %d, opy %p, opyl %d, parm %p, parmlen %d)\n",im,opx,opxl,opy,opyl,parm,parmlen));
861892
862893 nxsize = im->xsize;
863894 nysize = im->ysize ;
879910 i_ppix(new_img,nx,ny,&val);
880911 }
881912
882 mm_log((1,"(%p) <- i_transform\n",new_img));
913 im_log((aIMCTX, 1,"(%p) <- i_transform\n",new_img));
883914 return new_img;
884915 }
885916
902933 int ch, chb;
903934 float tdiff;
904935 i_color val1,val2;
905
906 mm_log((1,"i_img_diff(im1 %p,im2 %p)\n",im1,im2));
936 dIMCTXim(im1);
937
938 im_log((aIMCTX, 1,"i_img_diff(im1 %p,im2 %p)\n",im1,im2));
907939
908940 xb=(im1->xsize<im2->xsize)?im1->xsize:im2->xsize;
909941 yb=(im1->ysize<im2->ysize)?im1->ysize:im2->ysize;
910942 chb=(im1->channels<im2->channels)?im1->channels:im2->channels;
911943
912 mm_log((1,"i_img_diff: b=(" i_DFp ") chb=%d\n",
944 im_log((aIMCTX, 1,"i_img_diff: b=(" i_DFp ") chb=%d\n",
913945 i_DFcp(xb,yb), chb));
914946
915947 tdiff=0;
919951
920952 for(ch=0;ch<chb;ch++) tdiff+=(val1.channel[ch]-val2.channel[ch])*(val1.channel[ch]-val2.channel[ch]);
921953 }
922 mm_log((1,"i_img_diff <- (%.2f)\n",tdiff));
954 im_log((aIMCTX, 1,"i_img_diff <- (%.2f)\n",tdiff));
923955 return tdiff;
924956 }
925957
944976 int ch, chb;
945977 double tdiff;
946978 i_fcolor val1,val2;
947
948 mm_log((1,"i_img_diffd(im1 %p,im2 %p)\n",im1,im2));
979 dIMCTXim(im1);
980
981 im_log((aIMCTX, 1,"i_img_diffd(im1 %p,im2 %p)\n",im1,im2));
949982
950983 xb=(im1->xsize<im2->xsize)?im1->xsize:im2->xsize;
951984 yb=(im1->ysize<im2->ysize)?im1->ysize:im2->ysize;
952985 chb=(im1->channels<im2->channels)?im1->channels:im2->channels;
953986
954 mm_log((1,"i_img_diffd: b(" i_DFp ") chb=%d\n",
987 im_log((aIMCTX, 1,"i_img_diffd: b(" i_DFp ") chb=%d\n",
955988 i_DFcp(xb, yb), chb));
956989
957990 tdiff=0;
964997 tdiff += sdiff * sdiff;
965998 }
966999 }
967 mm_log((1,"i_img_diffd <- (%.2f)\n",tdiff));
1000 im_log((aIMCTX, 1,"i_img_diffd <- (%.2f)\n",tdiff));
9681001
9691002 return tdiff;
9701003 }
9741007 i_img_dim x,y,xb,yb;
9751008 int ch, chb;
9761009 i_fcolor val1,val2;
1010 dIMCTXim(im1);
9771011
9781012 if (what == NULL)
9791013 what = "(null)";
9801014
981 mm_log((1,"i_img_samef(im1 %p,im2 %p, epsilon %g, what '%s')\n", im1, im2, epsilon, what));
1015 im_log((aIMCTX,1,"i_img_samef(im1 %p,im2 %p, epsilon %g, what '%s')\n", im1, im2, epsilon, what));
9821016
9831017 xb=(im1->xsize<im2->xsize)?im1->xsize:im2->xsize;
9841018 yb=(im1->ysize<im2->ysize)?im1->ysize:im2->ysize;
9851019 chb=(im1->channels<im2->channels)?im1->channels:im2->channels;
9861020
987 mm_log((1,"i_img_samef: b(" i_DFp ") chb=%d\n",
1021 im_log((aIMCTX, 1,"i_img_samef: b(" i_DFp ") chb=%d\n",
9881022 i_DFcp(xb, yb), chb));
9891023
9901024 for(y = 0; y < yb; y++) {
9951029 for(ch = 0; ch < chb; ch++) {
9961030 double sdiff = val1.channel[ch] - val2.channel[ch];
9971031 if (fabs(sdiff) > epsilon) {
998 mm_log((1,"i_img_samef <- different %g @(" i_DFp ")\n",
1032 im_log((aIMCTX, 1,"i_img_samef <- different %g @(" i_DFp ")\n",
9991033 sdiff, i_DFcp(x, y)));
10001034 return 0;
10011035 }
10021036 }
10031037 }
10041038 }
1005 mm_log((1,"i_img_samef <- same\n"));
1039 im_log((aIMCTX, 1,"i_img_samef <- same\n"));
10061040
10071041 return 1;
10081042 }
10171051 int ch,c;
10181052 i_img *new_img,*new_img2;
10191053 i_color val1,val2,dval1,dval2;
1054 dIMCTXim(im);
10201055
10211056 mx=im->xsize;
10221057 my=im->ysize;
14281463 i_img_dim
14291464 i_gsamp_bits_fb(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, unsigned *samps,
14301465 const int *chans, int chan_count, int bits) {
1466 dIMCTXim(im);
1467
14311468 if (bits < 1 || bits > 32) {
14321469 i_push_error(0, "Invalid bits, must be 1..32");
14331470 return -1;
14521489 /* make sure we have good channel numbers */
14531490 for (ch = 0; ch < chan_count; ++ch) {
14541491 if (chans[ch] < 0 || chans[ch] >= im->channels) {
1455 i_push_errorf(0, "No channel %d in this image", chans[ch]);
1492 im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
14561493 return -1;
14571494 }
14581495 }
11 #define _IMAGE_H_
22
33 #include "imconfig.h"
4 #include "immacros.h"
45 #include "imio.h"
56 #include "iolayer.h"
6 #include "log.h"
77 #include "stackmach.h"
8
98
109 #ifndef _MSC_VER
1110 #include <unistd.h>
4746 extern void i_rgb_to_hsv(i_color *color);
4847 extern void i_hsv_to_rgb(i_color *color);
4948
50 i_img *i_img_8_new(i_img_dim x,i_img_dim y,int ch);
51 i_img *i_img_new( void );
52 i_img *i_img_empty(i_img *im,i_img_dim x,i_img_dim y);
53 i_img *i_img_empty_ch(i_img *im,i_img_dim x,i_img_dim y,int ch);
49 i_img *im_img_8_new(pIMCTX, i_img_dim x,i_img_dim y,int ch);
50 #define i_img_empty(im, x, y) i_img_empty_ch((im), (x), (y), 3)
51 i_img *im_img_empty_ch(pIMCTX, i_img *im,i_img_dim x,i_img_dim y,int ch);
52 #define i_img_empty_ch(im, x, y, ch) im_img_empty_ch(aIMCTX, (im), (x), (y), (ch))
5453 void i_img_exorcise(i_img *im);
5554 void i_img_destroy(i_img *im);
56 i_img *i_img_alloc(void);
57 void i_img_init(i_img *im);
55 i_img *im_img_alloc(pIMCTX);
56 void im_img_init(pIMCTX, i_img *im);
5857
5958 void i_img_info(i_img *im,i_img_dim *info);
6059
6160 extern i_img *i_sametype(i_img *im, i_img_dim xsize, i_img_dim ysize);
6261 extern i_img *i_sametype_chans(i_img *im, i_img_dim xsize, i_img_dim ysize, int channels);
63
64 i_img *i_img_pal_new(i_img_dim x, i_img_dim y, int ch, int maxpal);
6562
6663 /* Image feature settings */
6764
7370
7471 /* Base functions */
7572
76 extern int i_ppix(i_img *im,i_img_dim x,i_img_dim y, const i_color *val);
77 extern int i_gpix(i_img *im,i_img_dim x,i_img_dim y,i_color *val);
78 extern int i_ppixf(i_img *im,i_img_dim x,i_img_dim y, const i_fcolor *val);
79 extern int i_gpixf(i_img *im,i_img_dim x,i_img_dim y,i_fcolor *val);
80
81 #define i_ppix(im, x, y, val) (((im)->i_f_ppix)((im), (x), (y), (val)))
82 #define i_gpix(im, x, y, val) (((im)->i_f_gpix)((im), (x), (y), (val)))
83 #define i_ppixf(im, x, y, val) (((im)->i_f_ppixf)((im), (x), (y), (val)))
84 #define i_gpixf(im, x, y, val) (((im)->i_f_gpixf)((im), (x), (y), (val)))
85
86 extern i_img_dim i_plin(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_color *vals);
87 extern i_img_dim i_glin(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_color *vals);
88 extern i_img_dim i_plinf(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_fcolor *vals);
89 extern i_img_dim i_glinf(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *vals);
90 extern i_img_dim i_gsamp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_sample_t *samp,
91 const int *chans, int chan_count);
92 extern i_img_dim i_gsampf(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samp,
93 const int *chans, int chan_count);
94 extern i_img_dim i_gpal(i_img *im, i_img_dim x, i_img_dim r, i_img_dim y, i_palidx *vals);
95 extern i_img_dim i_ppal(i_img *im, i_img_dim x, i_img_dim r, i_img_dim y, const i_palidx *vals);
96 extern int i_addcolors(i_img *im, const i_color *colors, int count);
97 extern int i_getcolors(i_img *im, int i, i_color *, int count);
98 extern int i_colorcount(i_img *im);
99 extern int i_maxcolors(i_img *im);
100 extern int i_findcolor(i_img *im, const i_color *color, i_palidx *entry);
101 extern int i_setcolors(i_img *im, int index, const i_color *colors,
73 extern int (i_ppix)(i_img *im,i_img_dim x,i_img_dim y, const i_color *val);
74 extern int (i_gpix)(i_img *im,i_img_dim x,i_img_dim y,i_color *val);
75 extern int (i_ppixf)(i_img *im,i_img_dim x,i_img_dim y, const i_fcolor *val);
76 extern int (i_gpixf)(i_img *im,i_img_dim x,i_img_dim y,i_fcolor *val);
77
78 extern i_img_dim (i_plin)(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y,
79 const i_color *vals);
80 extern i_img_dim (i_glin)(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y,
81 i_color *vals);
82 extern i_img_dim (i_plinf)(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y,
83 const i_fcolor *vals);
84 extern i_img_dim (i_glinf)(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y,
85 i_fcolor *vals);
86 extern i_img_dim (i_gsamp)(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y,
87 i_sample_t *samp, const int *chans, int chan_count);
88 extern i_img_dim
89 (i_gsampf)(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samp,
90 const int *chans, int chan_count);
91 extern i_img_dim
92 (i_gpal)(i_img *im, i_img_dim x, i_img_dim r, i_img_dim y, i_palidx *vals);
93 extern i_img_dim
94 (i_ppal)(i_img *im, i_img_dim x, i_img_dim r, i_img_dim y, const i_palidx *vals);
95 extern int (i_addcolors)(i_img *im, const i_color *colors, int count);
96 extern int (i_getcolors)(i_img *im, int i, i_color *, int count);
97 extern int (i_colorcount)(i_img *im);
98 extern int (i_maxcolors)(i_img *im);
99 extern int (i_findcolor)(i_img *im, const i_color *color, i_palidx *entry);
100 extern int (i_setcolors)(i_img *im, int index, const i_color *colors,
102101 int count);
103102
104 #define i_plin(im, l, r, y, val) (((im)->i_f_plin)(im, l, r, y, val))
105 #define i_glin(im, l, r, y, val) (((im)->i_f_glin)(im, l, r, y, val))
106 #define i_plinf(im, l, r, y, val) (((im)->i_f_plinf)(im, l, r, y, val))
107 #define i_glinf(im, l, r, y, val) (((im)->i_f_glinf)(im, l, r, y, val))
108
109 #define i_gsamp(im, l, r, y, samps, chans, count) \
110 (((im)->i_f_gsamp)((im), (l), (r), (y), (samps), (chans), (count)))
111 #define i_gsampf(im, l, r, y, samps, chans, count) \
112 (((im)->i_f_gsampf)((im), (l), (r), (y), (samps), (chans), (count)))
113
114 #define i_gsamp_bits(im, l, r, y, samps, chans, count, bits) \
115 (((im)->i_f_gsamp_bits) ? ((im)->i_f_gsamp_bits)((im), (l), (r), (y), (samps), (chans), (count), (bits)) : -1)
116 #define i_psamp_bits(im, l, r, y, samps, chans, count, bits) \
117 (((im)->i_f_psamp_bits) ? ((im)->i_f_psamp_bits)((im), (l), (r), (y), (samps), (chans), (count), (bits)) : -1)
118
119 #define i_findcolor(im, color, entry) \
120 (((im)->i_f_findcolor) ? ((im)->i_f_findcolor)((im), (color), (entry)) : 0)
121
122 #define i_gpal(im, l, r, y, vals) \
123 (((im)->i_f_gpal) ? ((im)->i_f_gpal)((im), (l), (r), (y), (vals)) : 0)
124 #define i_ppal(im, l, r, y, vals) \
125 (((im)->i_f_ppal) ? ((im)->i_f_ppal)((im), (l), (r), (y), (vals)) : 0)
126 #define i_addcolors(im, colors, count) \
127 (((im)->i_f_addcolors) ? ((im)->i_f_addcolors)((im), (colors), (count)) : -1)
128 #define i_getcolors(im, index, color, count) \
129 (((im)->i_f_getcolors) ? \
130 ((im)->i_f_getcolors)((im), (index), (color), (count)) : 0)
131 #define i_setcolors(im, index, color, count) \
132 (((im)->i_f_setcolors) ? \
133 ((im)->i_f_setcolors)((im), (index), (color), (count)) : 0)
134 #define i_colorcount(im) \
135 (((im)->i_f_colorcount) ? ((im)->i_f_colorcount)(im) : -1)
136 #define i_maxcolors(im) \
137 (((im)->i_f_maxcolors) ? ((im)->i_f_maxcolors)(im) : -1)
138 #define i_findcolor(im, color, entry) \
139 (((im)->i_f_findcolor) ? ((im)->i_f_findcolor)((im), (color), (entry)) : 0)
140
141 #define i_img_virtual(im) ((im)->virtual)
142 #define i_img_type(im) ((im)->type)
143 #define i_img_bits(im) ((im)->bits)
144103
145104 extern i_fill_t *i_new_fill_solidf(const i_fcolor *c, int combine);
146105 extern i_fill_t *i_new_fill_solid(const i_color *c, int combine);
224183
225184 /* font routines */
226185
227 undef_int i_init_fonts( int t1log );
228
229186 #ifdef HAVE_LIBTT
187
188 extern void i_tt_start(void);
230189
231190 TT_Fonthandle* i_tt_new(const char *fontname);
232191 void i_tt_destroy( TT_Fonthandle *handle );
246205 extern i_palidx *i_quant_translate(i_quantize *quant, i_img *img);
247206 extern void i_quant_transparent(i_quantize *quant, i_palidx *indices, i_img *img, i_palidx trans_index);
248207
249 extern i_img *i_img_pal_new(i_img_dim x, i_img_dim y, int channels, int maxpal);
208 i_img *im_img_pal_new(pIMCTX, i_img_dim x, i_img_dim y, int ch, int maxpal);
209
250210 extern i_img *i_img_to_pal(i_img *src, i_quantize *quant);
251211 extern i_img *i_img_to_rgb(i_img *src);
252212 extern i_img *i_img_masked_new(i_img *targ, i_img *mask, i_img_dim x, i_img_dim y,
253213 i_img_dim w, i_img_dim h);
254 extern i_img *i_img_16_new(i_img_dim x, i_img_dim y, int ch);
214 extern i_img *im_img_16_new(pIMCTX, i_img_dim x, i_img_dim y, int ch);
255215 extern i_img *i_img_to_rgb16(i_img *im);
256 extern i_img *i_img_double_new(i_img_dim x, i_img_dim y, int ch);
216 extern i_img *im_img_double_new(pIMCTX, i_img_dim x, i_img_dim y, int ch);
257217 extern i_img *i_img_to_drgb(i_img *im);
258218
259219 extern int i_img_is_monochrome(i_img *im, int *zero_is_white);
329289 /* Debug only functions */
330290
331291 void malloc_state( void );
332
333 /* this is sort of obsolete now */
334
335 typedef struct {
336 undef_int (*i_has_format)(char *frmt);
337 i_color*(*ICL_set)(i_color *cl,unsigned char r,unsigned char g,unsigned char b,unsigned char a);
338 void (*ICL_info)(const i_color *cl);
339
340 i_img*(*i_img_new)( void );
341 i_img*(*i_img_empty)(i_img *im,i_img_dim x,i_img_dim y);
342 i_img*(*i_img_empty_ch)(i_img *im,i_img_dim x,i_img_dim y,int ch);
343 void(*i_img_exorcise)(i_img *im);
344
345 void(*i_img_info)(i_img *im,i_img_dim *info);
346
347 void(*i_img_setmask)(i_img *im,int ch_mask);
348 int (*i_img_getmask)(i_img *im);
349
350 /*
351 int (*i_ppix)(i_img *im,i_img_dim x,i_img_dim y,i_color *val);
352 int (*i_gpix)(i_img *im,i_img_dim x,i_img_dim y,i_color *val);
353 */
354 void(*i_box)(i_img *im,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img_dim y2,const i_color *val);
355 void(*i_line)(i_img *im,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img_dim y2,const i_color *val,int endp);
356 void(*i_arc)(i_img *im,i_img_dim x,i_img_dim y,double rad,double d1,double d2,const i_color *val);
357 void(*i_copyto)(i_img *im,i_img *src,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img_dim y2,i_img_dim tx,i_img_dim ty);
358 void(*i_copyto_trans)(i_img *im,i_img *src,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img_dim y2,i_img_dim tx,i_img_dim ty,const i_color *trans);
359 int(*i_rubthru)(i_img *im,i_img *src,i_img_dim tx,i_img_dim ty, i_img_dim src_minx, i_img_dim src_miny, i_img_dim src_maxx, i_img_dim src_maxy);
360
361 } symbol_table_t;
362292
363293 #include "imerror.h"
364294
397327
398328 /* image file limits */
399329 extern int
400 i_set_image_file_limits(i_img_dim width, i_img_dim height, size_t bytes);
330 im_set_image_file_limits(im_context_t ctx, i_img_dim width, i_img_dim height, size_t bytes);
401331 extern int
402 i_get_image_file_limits(i_img_dim *width, i_img_dim *height, size_t *bytes);
332 im_get_image_file_limits(im_context_t ctx, i_img_dim *width, i_img_dim *height, size_t *bytes);
403333 extern int
404 i_int_check_image_file_limits(i_img_dim width, i_img_dim height, int channels, size_t sample_size);
334 im_int_check_image_file_limits(im_context_t ctx, i_img_dim width, i_img_dim height, int channels, size_t sample_size);
405335
406336 /* memory allocation */
407337 void* mymalloc(size_t size);
427357 #endif /* IMAGER_MALLOC_DEBUG */
428358
429359 #include "imrender.h"
430 #include "immacros.h"
431360
432361 extern void
433362 i_adapt_colors(int dest_channels, int src_channels, i_color *colors,
451380 i_gsampf_bg(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samples,
452381 int out_channels, i_fcolor const *bg);
453382
383 /* context object management */
384 extern im_context_t im_context_new(void);
385 extern void im_context_refinc(im_context_t ctx, const char *where);
386 extern void im_context_refdec(im_context_t ctx, const char *where);
387 extern im_context_t im_context_clone(im_context_t ctx, const char *where);
388 extern im_slot_t im_context_slot_new(im_slot_destroy_t);
389 extern void *im_context_slot_get(im_context_t ctx, im_slot_t slot);
390 extern int im_context_slot_set(im_context_t ctx, im_slot_t slot, void *);
391
392 extern im_context_t (*im_get_context)(void);
393
394 /* mutex API */
395 extern i_mutex_t i_mutex_new(void);
396 extern void i_mutex_destroy(i_mutex_t m);
397 extern void i_mutex_lock(i_mutex_t m);
398 extern void i_mutex_unlock(i_mutex_t m);
399
454400 #include "imio.h"
455401
456402 #endif
55 #define IMAGEI_H_
66
77 #include "imager.h"
8 #include <stddef.h>
89
910 /* wrapper functions that implement the floating point sample version of a
1011 function in terms of the 8-bit sample version
110111
111112 #define color_to_grey(col) ((col)->rgb.r * 0.222 + (col)->rgb.g * 0.707 + (col)->rgb.b * 0.071)
112113
114 #define IM_ERROR_COUNT 20
115 typedef struct im_context_tag {
116 int error_sp;
117 size_t error_alloc[IM_ERROR_COUNT];
118 i_errmsg error_stack[IM_ERROR_COUNT];
119 #ifdef IMAGER_LOG
120 /* the log file and level for this context */
121 FILE *lg_file;
122 int log_level;
123
124 /* whether we own the lg_file, false for stderr and for cloned contexts */
125 int own_log;
126
127 /* values supplied by lhead */
128 const char *filename;
129 int line;
113130 #endif
131
132 /* file size limits */
133 i_img_dim max_width, max_height;
134 size_t max_bytes;
135
136 /* per context storage */
137 size_t slot_alloc;
138 void **slots;
139
140 ptrdiff_t refcount;
141 } im_context_struct;
142
143 #define DEF_BYTES_LIMIT 0x40000000
144
145 #endif
44 #include "imconfig.h"
55
66 #define MAXCHANNELS 4
7
8 typedef struct im_context_tag *im_context_t;
9
10 typedef ptrdiff_t im_slot_t;
11 typedef void (*im_slot_destroy_t)(void *);
712
813 /* used for palette indices in some internal code (which might be
914 exposed at some point
3540 */
3641
3742 typedef ptrdiff_t i_img_dim;
43 typedef size_t i_img_dim_u;
3844
3945 /*
4046 =item i_color
281287 =item *
282288
283289 i_f_psampf - implements psamp() for this image.
290
291 =item *
292
293 C<im_data> - image specific data internal to Imager.
294
295 =item *
296
297 C<context> - the Imager API context this image belongs to.
284298
285299 =back
286300
334348 i_f_psampf_t i_f_psampf;
335349
336350 void *im_data;
351
352 /* 0.91 */
353 im_context_t context;
337354 };
338355
339356 /* ext_data for paletted images
540557 } i_combine_t;
541558
542559 /*
560 =item i_mutex_t
561 X<i_mutex>
562 =category mutex
563 =synopsis i_mutex_t mutex;
564
565 Opaque type for Imager's mutex API.
566
567 =cut
568 */
569 typedef struct i_mutex_tag *i_mutex_t;
570
571 /*
543572 describes an axis of a MM font.
544573 Modelled on FT2's FT_MM_Axis.
545574 It would be nice to have a default entry too, but FT2
680709
681710 #include "iolayert.h"
682711
712 /* error message information returned by im_errors() */
713
714 typedef struct {
715 char *msg;
716 int code;
717 } i_errmsg;
718
683719 typedef struct i_render_tag i_render;
684720
685721 #ifdef IMAGER_FORMAT_ATTR
44 see error.c for documentation
55 the error information is currently global
66 */
7 typedef struct {
8 char *msg;
9 int code;
10 } i_errmsg;
11
127 typedef void (*i_error_cb)(int code, char const *msg);
138 typedef void (*i_failed_cb)(i_errmsg *msgs);
149 extern i_error_cb i_set_error_cb(i_error_cb);
1510 extern i_failed_cb i_set_failed_cb(i_failed_cb);
1611 extern void i_set_argv0(char const *);
1712 extern int i_set_errors_fatal(int new_fatal);
18 extern i_errmsg *i_errors(void);
13 extern i_errmsg *im_errors(pIMCTX);
1914
20 extern void i_push_error(int code, char const *msg);
15 extern void im_push_error(pIMCTX, int code, char const *msg);
16 #ifndef IMAGER_NO_CONTEXT
2117 extern void i_push_errorf(int code, char const *fmt, ...) I_FORMAT_ATTR(2, 3);
22 extern void i_push_errorvf(int code, char const *fmt, va_list);
23 extern void i_clear_error(void);
18 #endif
19 extern void im_push_errorf(pIMCTX, int code, char const *fmt, ...) I_FORMAT_ATTR(3, 4);
20 extern void im_push_errorvf(im_context_t ctx, int code, char const *fmt, va_list);
21 extern void im_clear_error(pIMCTX);
2422 extern int i_failed(int code, char const *msg);
2523
2624 #endif
00 #include "imexttypes.h"
11 #include "imager.h"
22 #include "imio.h"
3
4 static im_context_t get_context(void);
5 static i_img *mathom_i_img_8_new(i_img_dim, i_img_dim, int);
6 static i_img *mathom_i_img_16_new(i_img_dim, i_img_dim, int);
7 static i_img *mathom_i_img_double_new(i_img_dim, i_img_dim, int);
8 static i_img *mathom_i_img_pal_new(i_img_dim, i_img_dim, int, int);
9 static void mathom_i_clear_error(void);
10 static void mathom_i_push_error(int, const char *);
11 static void mathom_i_push_errorvf(int, const char *, va_list);
12 static int mathom_i_set_image_file_limits(i_img_dim, i_img_dim, size_t);
13 static int mathom_i_get_image_file_limits(i_img_dim*, i_img_dim*, size_t*);
14 static int
15 mathom_i_int_check_image_file_limits(i_img_dim, i_img_dim, int, size_t);
16 static i_img *mathom_i_img_alloc(void);
17 static void mathom_i_img_init(i_img *);
18 static i_io_glue_t *mathom_io_new_fd(int);
19 static i_io_glue_t *mathom_io_new_bufchain(void);
20 static i_io_glue_t *
21 mathom_io_new_buffer(const char *data, size_t, i_io_closebufp_t, void *);
22 static i_io_glue_t *
23 mathom_io_new_cb(void *, i_io_readl_t, i_io_writel_t, i_io_seekl_t,
24 i_io_closel_t, i_io_destroyl_t);
325
426 /*
527 DON'T ADD CASTS TO THESE
1739 myfree_file_line,
1840 myrealloc_file_line,
1941
20 i_img_8_new,
21 i_img_16_new,
22 i_img_double_new,
23 i_img_pal_new,
42 mathom_i_img_8_new,
43 mathom_i_img_16_new,
44 mathom_i_img_double_new,
45 mathom_i_img_pal_new,
2446 i_img_destroy,
2547 i_sametype,
2648 i_sametype_chans,
5779 i_quant_translate,
5880 i_quant_transparent,
5981
60 i_clear_error,
61 i_push_error,
82 mathom_i_clear_error,
83 mathom_i_push_error,
6284 i_push_errorf,
63 i_push_errorvf,
85 mathom_i_push_errorvf,
6486
6587 i_tags_new,
6688 i_tags_set,
98120 i_rubthru,
99121
100122 /* IMAGER_API_LEVEL 2 functions */
101 i_set_image_file_limits,
102 i_get_image_file_limits,
103 i_int_check_image_file_limits,
123 mathom_i_set_image_file_limits,
124 mathom_i_get_image_file_limits,
125 mathom_i_int_check_image_file_limits,
104126
105127 i_flood_fill_border,
106128 i_flood_cfill_border,
115137 i_loog,
116138
117139 /* IMAGER_API_LEVEL 4 functions */
118 i_img_alloc,
119 i_img_init,
140 mathom_i_img_alloc,
141 mathom_i_img_init,
120142
121143 /* IMAGER_API_LEVEL 5 functions */
122144 i_img_is_monochrome,
144166 i_io_close,
145167 i_io_set_buffered,
146168 i_io_gets,
147 io_new_fd,
148 io_new_bufchain,
149 io_new_buffer,
150 io_new_cb,
169 mathom_io_new_fd,
170 mathom_io_new_bufchain,
171 mathom_io_new_buffer,
172 mathom_io_new_cb,
151173 io_slurp,
152 io_glue_destroy
174 io_glue_destroy,
175
176 /* level 8 */
177 im_img_8_new,
178 im_img_16_new,
179 im_img_double_new,
180 im_img_pal_new,
181 im_clear_error,
182 im_push_error,
183 im_push_errorvf,
184 im_push_errorf,
185 im_set_image_file_limits,
186 im_get_image_file_limits,
187 im_int_check_image_file_limits,
188 im_img_alloc,
189 im_img_init,
190 im_io_new_fd,
191 im_io_new_bufchain,
192 im_io_new_buffer,
193 im_io_new_cb,
194 get_context,
195 im_lhead,
196 im_loog,
197 im_context_refinc,
198 im_context_refdec,
199 im_errors,
200 i_mutex_new,
201 i_mutex_destroy,
202 i_mutex_lock,
203 i_mutex_unlock,
204 im_context_slot_new,
205 im_context_slot_set,
206 im_context_slot_get
153207 };
154208
155209 /* in general these functions aren't called by Imager internally, but
549603 return i_setcolors(im, index, colors, count);
550604 }
551605
606 /*
607 =item im_get_context()
608
609 Retrieve the context object for the current thread.
610
611 Inside Imager itself this is just a function pointer, which the
612 F<Imager.xs> BOOT handler initializes for use within perl. If you're
613 taking the Imager code and embedding it elsewhere you need to
614 initialize the C<im_get_context> pointer at some point.
615
616 =cut
617 */
618
619 static im_context_t
620 get_context(void) {
621 return im_get_context();
622 }
623
624 static i_img *
625 mathom_i_img_8_new(i_img_dim xsize, i_img_dim ysize, int channels) {
626 return i_img_8_new(xsize, ysize, channels);
627 }
628
629 static i_img *
630 mathom_i_img_16_new(i_img_dim xsize, i_img_dim ysize, int channels) {
631 return i_img_16_new(xsize, ysize, channels);
632 }
633
634 static i_img *
635 mathom_i_img_double_new(i_img_dim xsize, i_img_dim ysize, int channels) {
636 return i_img_double_new(xsize, ysize, channels);
637 }
638
639 static i_img *
640 mathom_i_img_pal_new(i_img_dim xsize, i_img_dim ysize, int channels,
641 int maxpal) {
642 return i_img_pal_new(xsize, ysize, channels, maxpal);
643 }
644
645 static void
646 mathom_i_clear_error(void) {
647 i_clear_error();
648 }
649
650 static void
651 mathom_i_push_error(int code, const char *msg) {
652 i_push_error(code, msg);
653 }
654
655 static void
656 mathom_i_push_errorvf(int code, const char *fmt, va_list args) {
657 i_push_errorvf(code, fmt, args);
658 }
659
660 static int
661 mathom_i_set_image_file_limits(i_img_dim max_width, i_img_dim max_height,
662 size_t max_bytes) {
663 return i_set_image_file_limits(max_width, max_height, max_bytes);
664 }
665
666 static int
667 mathom_i_get_image_file_limits(i_img_dim *pmax_width, i_img_dim *pmax_height,
668 size_t *pmax_bytes) {
669 return i_get_image_file_limits(pmax_width, pmax_height, pmax_bytes);
670 }
671
672 static int
673 mathom_i_int_check_image_file_limits(i_img_dim width, i_img_dim height,
674 int channels, size_t sample_size) {
675 return i_int_check_image_file_limits(width, height, channels, sample_size);
676 }
677
678 static i_img *
679 mathom_i_img_alloc(void) {
680 return i_img_alloc();
681 }
682
683 static void
684 mathom_i_img_init(i_img *im) {
685 i_img_init(im);
686 }
687
688 static i_io_glue_t *
689 mathom_io_new_fd(int fd) {
690 return io_new_fd(fd);
691 }
692 static i_io_glue_t *
693 mathom_io_new_bufchain(void) {
694 return io_new_bufchain();
695 }
696
697 static i_io_glue_t *
698 mathom_io_new_buffer(const char *data, size_t size, i_io_closebufp_t closefp,
699 void *close_data) {
700 return io_new_buffer(data, size, closefp, close_data);
701 }
702
703 static i_io_glue_t *
704 mathom_io_new_cb(void *p, i_io_readl_t readcb, i_io_writel_t writecb,
705 i_io_seekl_t seekcb, i_io_closel_t closecb,
706 i_io_destroyl_t destroycb) {
707 return io_new_cb(p, readcb, writecb, seekcb, closecb, destroycb);
708 }
2929 /* just for use here */
3030 #define im_extt imager_function_ext_table
3131
32 #define im_get_context() ((im_extt->f_im_get_context)())
33 #define im_context_refinc(ctx, where) ((im_extt->f_im_context_refinc)((ctx), (where)))
34 #define im_context_refdec(ctx, where) ((im_extt->f_im_context_refdec)((ctx), (where)))
35
3236 #ifdef IMAGER_DEBUG_MALLOC
3337
3438 #define mymalloc(size) ((im_extt->f_mymalloc_file_line)((size), __FILE__, __LINE__))
4347
4448 #endif
4549
46 #define i_img_8_new(xsize, ysize, channels) ((im_extt->f_i_img_8_new)((xsize), (ysize), (channels)))
47 #define i_img_16_new(xsize, ysize, channels) ((im_extt->f_i_img_16_new)((xsize), (ysize), (channels)))
48 #define i_img_double_new(xsize, ysize, channels) ((im_extt->f_i_img_double_new)((xsize), (ysize), (channels)))
49 #define i_img_pal_new(xsize, ysize, channels, maxpal) ((im_extt->f_i_img_pal_new)((xsize), (ysize), (channels), (maxpal)))
50 #define im_img_8_new(ctx, xsize, ysize, channels) ((im_extt->f_im_img_8_new)((ctx), (xsize), (ysize), (channels)))
51 #define im_img_16_new(ctx, xsize, ysize, channels) ((im_extt->f_im_img_16_new)((ctx), (xsize), (ysize), (channels)))
52 #define im_img_double_new(ctx, xsize, ysize, channels) ((im_extt->f_im_img_double_new)((ctx), (xsize), (ysize), (channels)))
53 #define im_img_pal_new(ctx, xsize, ysize, channels, maxpal) ((im_extt->f_im_img_pal_new)((ctx), (xsize), (ysize), (channels), (maxpal)))
5054
5155 #define i_img_destroy(im) ((im_extt->f_i_img_destroy)(im))
5256 #define i_sametype(im, xsize, ysize) ((im_extt->f_i_sametype)((im), (xsize), (ysize)))
5761 #define IMAGER_DIRECT_IMAGE_CALLS 1
5862 #endif
5963
60 #if IMAGER_DIRECT_IMAGE_CALLS
61 #define i_ppix(im, x, y, val) (((im)->i_f_ppix)((im), (x), (y), (val)))
62 #define i_gpix(im, x, y, val) (((im)->i_f_gpix)((im), (x), (y), (val)))
63 #define i_ppixf(im, x, y, val) (((im)->i_f_ppixf)((im), (x), (y), (val)))
64 #define i_gpixf(im, x, y, val) (((im)->i_f_gpixf)((im), (x), (y), (val)))
65 #define i_plin(im, l, r, y, val) (((im)->i_f_plin)(im, l, r, y, val))
66 #define i_glin(im, l, r, y, val) (((im)->i_f_glin)(im, l, r, y, val))
67 #define i_plinf(im, l, r, y, val) (((im)->i_f_plinf)(im, l, r, y, val))
68 #define i_glinf(im, l, r, y, val) (((im)->i_f_glinf)(im, l, r, y, val))
69
70 #define i_gsamp(im, l, r, y, samps, chans, count) \
71 (((im)->i_f_gsamp)((im), (l), (r), (y), (samps), (chans), (count)))
72 #define i_gsampf(im, l, r, y, samps, chans, count) \
73 (((im)->i_f_gsampf)((im), (l), (r), (y), (samps), (chans), (count)))
74
75 #define i_findcolor(im, color, entry) \
76 (((im)->i_f_findcolor) ? ((im)->i_f_findcolor)((im), (color), (entry)) : 0)
77
78 #define i_gpal(im, l, r, y, vals) \
79 (((im)->i_f_gpal) ? ((im)->i_f_gpal)((im), (l), (r), (y), (vals)) : 0)
80 #define i_ppal(im, l, r, y, vals) \
81 (((im)->i_f_ppal) ? ((im)->i_f_ppal)((im), (l), (r), (y), (vals)) : 0)
82 #define i_addcolors(im, colors, count) \
83 (((im)->i_f_addcolors) ? ((im)->i_f_addcolors)((im), (colors), (count)) : -1)
84 #define i_getcolors(im, index, color, count) \
85 (((im)->i_f_getcolors) ? \
86 ((im)->i_f_getcolors)((im), (index), (color), (count)) : 0)
87 #define i_setcolors(im, index, color, count) \
88 (((im)->i_f_setcolors) ? \
89 ((im)->i_f_setcolors)((im), (index), (color), (count)) : 0)
90 #define i_colorcount(im) \
91 (((im)->i_f_colorcount) ? ((im)->i_f_colorcount)(im) : -1)
92 #define i_maxcolors(im) \
93 (((im)->i_f_maxcolors) ? ((im)->i_f_maxcolors)(im) : -1)
94 #define i_findcolor(im, color, entry) \
95 (((im)->i_f_findcolor) ? ((im)->i_f_findcolor)((im), (color), (entry)) : 0)
96 #else
64 #if !IMAGER_DIRECT_IMAGE_CALLS
65
9766 #define i_ppix(im, x, y, val) ((im_extt->f_i_ppix)((im), (x), (y), (val)))
9867 #define i_gpix(im, x, y, val) ((im_extt->f_i_gpix)((im), (x), (y), (val)))
9968 #define i_ppixf(im, x, y, val) ((im_extt->f_i_ppixf)((im), (x), (y), (val)))
133102 #define i_quant_transparent(quant, indices, img, trans_index) \
134103 ((im_extt->f_i_quant_transparent)((quant), (indices), (img), (trans_index)))
135104
136 #define i_clear_error() ((im_extt->f_i_clear_error)())
137 #define i_push_error(code, msg) ((im_extt->f_i_push_error)((code), (msg)))
105 #define im_clear_error(ctx) ((im_extt->f_im_clear_error)(ctx))
106 #define im_push_error(ctx, code, msg) ((im_extt->f_im_push_error)((ctx), (code), (msg)))
138107 #define i_push_errorf (im_extt->f_i_push_errorf)
139 #define i_push_errorvf(code, fmt, list) \
140 ((im_extt->f_i_push_errorvf)((code), (fmt), (list)))
108 #define im_push_errorvf(ctx, code, fmt, list) \
109 ((im_extt->f_im_push_errorvf)((ctx), (code), (fmt), (list)))
141110
142111 #define i_tags_new(tags) ((im_extt->f_i_tags_new)(tags))
143112 #define i_tags_set(tags, name, data, size) \
193162 #define i_rubthru(im, src, tx, ty, src_minx, src_miny, src_maxx, src_maxy) \
194163 ((im_extt->f_i_rubthru)((im), (src), (tx), (ty), (src_minx), (src_miny), (src_maxx), (src_maxy)))
195164
196 #define i_set_image_file_limits(max_width, max_height, max_bytes) \
197 ((im_extt->f_i_set_image_file_limits)((max_width), (max_height), (max_bytes)))
198 #define i_get_image_file_limits(pmax_width, pmax_height, pmax_bytes) \
199 ((im_extt->f_i_get_image_file_limits)((pmax_width), (pmax_height), (pmax_bytes)))
200 #define i_int_check_image_file_limits(width, height, channels, sample_size) \
201 ((im_extt->f_i_int_check_image_file_limits)((width), (height), (channels), (sample_size)))
165 #define im_set_image_file_limits(ctx, max_width, max_height, max_bytes) \
166 ((im_extt->f_im_set_image_file_limits)((max_width), (max_height), (max_bytes)))
167 #define im_get_image_file_limits(ctx, pmax_width, pmax_height, pmax_bytes) \
168 ((im_extt->f_im_get_image_file_limits)((ctx), (pmax_width), (pmax_height), (pmax_bytes)))
169 #define im_int_check_image_file_limits(ctx, width, height, channels, sample_size) \
170 ((im_extt->f_im_int_check_image_file_limits)((ctx), (width), (height), (channels), (sample_size)))
202171
203172 #define i_img_setmask(img, mask) ((im_extt->f_i_img_setmask)((img), (mask)))
204173 #define i_img_getmask(img) ((im_extt->f_i_img_getmask)(img))
207176 #define i_img_get_height(img) ((im_extt->f_i_img_get_height)(img))
208177 #define i_lhead(file, line) ((im_extt->f_i_lhead)((file), (line)))
209178 #define i_loog (im_extt->f_i_loog)
210
211 #define i_img_alloc() ((im_extt->f_i_img_alloc)())
212 #define i_img_init(img) ((im_extt->f_i_img_init)(img))
179 #define im_lhead(ctx, file, line) ((im_extt->f_im_lhead)((ctx), (file), (line)))
180 #define im_loog (im_extt->f_im_loog)
181
182 #define im_img_alloc(ctx) ((im_extt->f_im_img_alloc)(ctx))
183 #define im_img_init(ctx, img) ((im_extt->fm_i_img_init)((ctx), (img)))
213184
214185 #define i_img_is_monochrome(img, zero_is_white) ((im_extt->f_i_img_is_monochrome)((img), (zero_is_white)))
215186
246217 #define i_io_close (im_extt->f_i_io_close)
247218 #define i_io_set_buffered (im_extt->f_i_io_set_buffered)
248219 #define i_io_gets (im_extt->f_i_io_gets)
249 #define io_new_fd(fd) ((im_extt->f_io_new_fd)(fd))
250 #define io_new_bufchain() ((im_extt->f_io_new_bufchain)())
251 #define io_new_buffer(data, len, closecb, closedata) \
252 ((im_extt->f_io_new_buffer)((data), (len), (closecb), (closedata)))
253 #define io_new_cb(p, readcb, writecb, seekcb, closecb, destroycb) \
254 ((im_extt->f_io_new_cb)((p), (readcb), (writecb), (seekcb), (closecb), (destroycb)))
220 #define im_io_new_fd(ctx, fd) ((im_extt->f_im_io_new_fd)(ctx, fd))
221 #define im_io_new_bufchain(ctx) ((im_extt->f_im_io_new_bufchain)(ctx))
222 #define im_io_new_buffer(ctx, data, len, closecb, closedata) \
223 ((im_extt->f_im_io_new_buffer)((ctx), (data), (len), (closecb), (closedata)))
224 #define im_io_new_cb(ctx, p, readcb, writecb, seekcb, closecb, destroycb) \
225 ((im_extt->f_im_io_new_cb)((ctx), (p), (readcb), (writecb), (seekcb), (closecb), (destroycb)))
255226 #define io_slurp(ig, datap) ((im_extt->f_io_slurp)((ig), (datap)))
256227 #define io_glue_destroy(ig) ((im_extt->f_io_glue_destroy)(ig))
257228
229 #define i_mutex_new() ((im_extt->f_i_mutex_new)())
230 #define i_mutex_destroy(m) ((im_extt->f_i_mutex_destroy)(m))
231 #define i_mutex_lock(m) ((im_extt->f_i_mutex_lock)(m))
232 #define i_mutex_unlock(m) ((im_extt->f_i_mutex_unlock)(m))
233
234 #define im_context_slot_new(destructor) ((im_extt->f_im_context_slot_new)(destructor))
235 #define im_context_slot_get(ctx, slot) ((im_extt->f_im_context_slot_get)((ctx), (slot)))
236 #define im_context_slot_set(ctx, slot, value) ((im_extt->f_im_context_slot_set)((ctx), (slot), (value)))
237
238 #define im_push_errorf (im_extt->f_im_push_errorf)
239
258240 #ifdef IMAGER_LOG
241 #ifndef IMAGER_NO_CONTEXT
259242 #define mm_log(x) { i_lhead(__FILE__,__LINE__); i_loog x; }
243 #endif
244 #define im_log(x) { im_lhead(aIMCTX, __FILE__,__LINE__); im_loog x; }
260245 #else
261246 #define mm_log(x)
262247 #endif
263248
264
265 #endif
249 #endif
3333 will result in an increment of IMAGER_API_LEVEL.
3434 */
3535
36 #define IMAGER_API_LEVEL 7
36 #define IMAGER_API_LEVEL 8
3737
3838 typedef struct {
3939 int version;
4747 void (*f_myfree_file_line)(void *p, char*file, int line);
4848 void* (*f_myrealloc_file_line)(void *p, size_t newsize, char* file,int line);
4949
50 i_img *(*f_i_img_8_new)(i_img_dim xsize, i_img_dim ysize, int channels);
51 i_img *(*f_i_img_16_new)(i_img_dim xsize, i_img_dim ysize, int channels);
52 i_img *(*f_i_img_double_new)(i_img_dim xsize, i_img_dim ysize, int channels);
53 i_img *(*f_i_img_pal_new)(i_img_dim xsize, i_img_dim ysize, int channels, int maxpal);
50 i_img *(*f_i_img_8_new)(i_img_dim xsize, i_img_dim ysize, int channels); /* SKIP */
51 i_img *(*f_i_img_16_new)(i_img_dim xsize, i_img_dim ysize, int channels); /* SKIP */
52 i_img *(*f_i_img_double_new)(i_img_dim xsize, i_img_dim ysize, int channels); /* SKIP */
53 i_img *(*f_i_img_pal_new)(i_img_dim xsize, i_img_dim ysize, int channels, int maxpal); /* SKIP */
5454 void (*f_i_img_destroy)(i_img *im);
5555 i_img *(*f_i_sametype)(i_img *im, i_img_dim xsize, i_img_dim ysize);
5656 i_img *(*f_i_sametype_chans)(i_img *im, i_img_dim xsize, i_img_dim ysize, int channels);
101101 void (*f_i_quant_transparent)(i_quantize *quant, i_palidx *indices,
102102 i_img *img, i_palidx trans_index);
103103
104 void (*f_i_clear_error)(void);
105 void (*f_i_push_error)(int code, char const *msg);
106 void (*f_i_push_errorf)(int code, char const *fmt, ...);
107 void (*f_i_push_errorvf)(int code, char const *fmt, va_list);
104 void (*f_i_clear_error)(void); /* SKIP */
105 void (*f_i_push_error)(int code, char const *msg); /* SKIP */
106 void (*f_i_push_errorf)(int code, char const *fmt, ...) I_FORMAT_ATTR(2,3);
107 void (*f_i_push_errorvf)(int code, char const *fmt, va_list); /* SKIP */
108108
109109 void (*f_i_tags_new)(i_img_tags *tags);
110110 int (*f_i_tags_set)(i_img_tags *tags, char const *name, char const *data,
151151 int (*f_i_rubthru)(i_img *im, i_img *src, i_img_dim tx, i_img_dim ty, i_img_dim src_minx, i_img_dim src_miny, i_img_dim src_maxx, i_img_dim src_maxy);
152152
153153 /* IMAGER_API_LEVEL 2 functions */
154 int (*f_i_set_image_file_limits)(i_img_dim width, i_img_dim height, size_t bytes);
155 int (*f_i_get_image_file_limits)(i_img_dim *width, i_img_dim *height, size_t *bytes);
156 int (*f_i_int_check_image_file_limits)(i_img_dim width, i_img_dim height, int channels, size_t sample_size);
154 int (*f_i_set_image_file_limits)(i_img_dim width, i_img_dim height, size_t bytes); /* SKIP */
155 int (*f_i_get_image_file_limits)(i_img_dim *width, i_img_dim *height, size_t *bytes); /* SKIP */
156 int (*f_i_int_check_image_file_limits)(i_img_dim width, i_img_dim height, int channels, size_t sample_size); /* SKIP */
157157 int (*f_i_flood_fill_border)(i_img *im, i_img_dim seedx, i_img_dim seedy, const i_color *dcol, const i_color *border);
158158 int (*f_i_flood_cfill_border)(i_img *im, i_img_dim seedx, i_img_dim seedy, i_fill_t *fill, const i_color *border);
159159
164164 i_img_dim (*f_i_img_get_width)(i_img *im);
165165 i_img_dim (*f_i_img_get_height)(i_img *im);
166166 void (*f_i_lhead)(const char *file, int line_number);
167 void (*f_i_loog)(int level, const char *msg, ...);
167 void (*f_i_loog)(int level, const char *msg, ...) I_FORMAT_ATTR(2,3);
168168
169169 /* IMAGER_API_LEVEL 4 functions will be added here */
170 i_img *(*f_i_img_alloc)(void);
171 void (*f_i_img_init)(i_img *);
170 i_img *(*f_i_img_alloc)(void); /* SKIP */
171 void (*f_i_img_init)(i_img *); /* SKIP */
172172
173173 /* IMAGER_API_LEVEL 5 functions will be added here */
174174 /* added i_psampf?_bits macros */
209209 int (*f_i_io_set_buffered)(io_glue *ig, int buffered);
210210 ssize_t (*f_i_io_gets)(io_glue *ig, char *, size_t, int);
211211
212 i_io_glue_t *(*f_io_new_fd)(int fd);
213 i_io_glue_t *(*f_io_new_bufchain)(void);
214 i_io_glue_t *(*f_io_new_buffer)(const char *data, size_t len, i_io_closebufp_t closecb, void *closedata);
215 i_io_glue_t *(*f_io_new_cb)(void *p, i_io_readl_t readcb, i_io_writel_t writecb, i_io_seekl_t seekcb, i_io_closel_t closecb, i_io_destroyl_t destroycb);
212 i_io_glue_t *(*f_io_new_fd)(int fd); /* SKIP */
213 i_io_glue_t *(*f_io_new_bufchain)(void); /* SKIP */
214 i_io_glue_t *(*f_io_new_buffer)(const char *data, size_t len, i_io_closebufp_t closecb, void *closedata); /* SKIP */
215 i_io_glue_t *(*f_io_new_cb)(void *p, i_io_readl_t readcb, i_io_writel_t writecb, i_io_seekl_t seekcb, i_io_closel_t closecb, i_io_destroyl_t destroycb); /* SKIP */
216216 size_t (*f_io_slurp)(i_io_glue_t *ig, unsigned char **c);
217217 void (*f_io_glue_destroy)(i_io_glue_t *ig);
218218
219219 /* IMAGER_API_LEVEL 8 functions will be added here */
220
220 i_img *(*f_im_img_8_new)(im_context_t ctx, i_img_dim xsize, i_img_dim ysize, int channels);
221 i_img *(*f_im_img_16_new)(im_context_t ctx, i_img_dim xsize, i_img_dim ysize, int channels);
222 i_img *(*f_im_img_double_new)(im_context_t ctx, i_img_dim xsize, i_img_dim ysize, int channels);
223 i_img *(*f_im_img_pal_new)(im_context_t ctx, i_img_dim xsize, i_img_dim ysize, int channels, int maxpal);
224
225 void (*f_im_clear_error)(im_context_t ctx);
226 void (*f_im_push_error)(im_context_t ctx, int code, char const *msg);
227 void (*f_im_push_errorvf)(im_context_t ctx, int code, char const *fmt, va_list);
228 void (*f_im_push_errorf)(im_context_t , int code, char const *fmt, ...) I_FORMAT_ATTR(3,4);
229
230 int (*f_im_set_image_file_limits)(im_context_t ctx, i_img_dim width, i_img_dim height, size_t bytes);
231 int (*f_im_get_image_file_limits)(im_context_t ctx, i_img_dim *width, i_img_dim *height, size_t *bytes);
232 int (*f_im_int_check_image_file_limits)(im_context_t ctx, i_img_dim width, i_img_dim height, int channels, size_t sample_size);
233
234 i_img *(*f_im_img_alloc)(im_context_t ctx);
235 void (*f_im_img_init)(im_context_t ctx, i_img *);
236
237 i_io_glue_t *(*f_im_io_new_fd)(im_context_t ctx, int fd);
238 i_io_glue_t *(*f_im_io_new_bufchain)(im_context_t ctx);
239 i_io_glue_t *(*f_im_io_new_buffer)(im_context_t ctx, const char *data, size_t len, i_io_closebufp_t closecb, void *closedata);
240 i_io_glue_t *(*f_im_io_new_cb)(im_context_t ctx, void *p, i_io_readl_t readcb, i_io_writel_t writecb, i_io_seekl_t seekcb, i_io_closel_t closecb, i_io_destroyl_t destroycb);
241
242 im_context_t (*f_im_get_context)(void);
243
244 void (*f_im_lhead)( im_context_t, const char *file, int line );
245 void (*f_im_loog)(im_context_t, int level,const char *msg, ... ) I_FORMAT_ATTR(3,4);
246 void (*f_im_context_refinc)(im_context_t, const char *where);
247 void (*f_im_context_refdec)(im_context_t, const char *where);
248 i_errmsg *(*f_im_errors)(im_context_t);
249 i_mutex_t (*f_i_mutex_new)(void);
250 void (*f_i_mutex_destroy)(i_mutex_t m);
251 void (*f_i_mutex_lock)(i_mutex_t m);
252 void (*f_i_mutex_unlock)(i_mutex_t m);
253 im_slot_t (*f_im_context_slot_new)(im_slot_destroy_t);
254 int (*f_im_context_slot_set)(im_context_t, im_slot_t, void *);
255 void *(*f_im_context_slot_get)(im_context_t, im_slot_t);
221256 } im_ext_funcs;
222257
223258 #define PERL_FUNCTION_TABLE_NAME "Imager::__ext_func_table"
1818
1919 =cut
2020 */
21
22 #define IMAGER_NO_CONTEXT
2123
2224 #include "imager.h"
2325 #include "imageri.h"
147149 ((((i_sample16_t *)(bytes))[offset]+127) / 257)
148150
149151 /*
150 =item i_img_16_new(x, y, ch)
151
152 =item im_img_16_new(ctx, x, y, ch)
153 X<im_img_16_new API>X<i_img_16_new API>
152154 =category Image creation/destruction
155 =synopsis i_img *img = im_img_16_new(aIMCTX, width, height, channels);
153156 =synopsis i_img *img = i_img_16_new(width, height, channels);
154157
155158 Create a new 16-bit/sample image.
156159
157160 Returns the image on success, or NULL on failure.
161
162 Also callable as C<i_img_16_new(x, y, ch)>
158163
159164 =cut
160165 */
161166
162 i_img *i_img_16_new(i_img_dim x, i_img_dim y, int ch) {
167 i_img *
168 im_img_16_new(pIMCTX, i_img_dim x, i_img_dim y, int ch) {
163169 i_img *im;
164170 size_t bytes, line_bytes;
165171
166 mm_log((1,"i_img_16_new(x %" i_DF ", y %" i_DF ", ch %d)\n",
172 im_log((aIMCTX, 1,"i_img_16_new(x %" i_DF ", y %" i_DF ", ch %d)\n",
167173 i_DFc(x), i_DFc(y), ch));
168174
169175 if (x < 1 || y < 1) {
170 i_push_error(0, "Image sizes must be positive");
176 im_push_error(aIMCTX, 0, "Image sizes must be positive");
171177 return NULL;
172178 }
173179 if (ch < 1 || ch > MAXCHANNELS) {
174 i_push_errorf(0, "channels must be between 1 and %d", MAXCHANNELS);
180 im_push_errorf(aIMCTX, 0, "channels must be between 1 and %d", MAXCHANNELS);
175181 return NULL;
176182 }
177183 bytes = x * y * ch * 2;
178184 if (bytes / y / ch / 2 != x) {
179 i_push_errorf(0, "integer overflow calculating image allocation");
185 im_push_errorf(aIMCTX, 0, "integer overflow calculating image allocation");
180186 return NULL;
181187 }
182188
185191 working with the image */
186192 line_bytes = sizeof(i_fcolor) * x;
187193 if (line_bytes / x != sizeof(i_fcolor)) {
188 i_push_error(0, "integer overflow calculating scanline allocation");
194 im_push_error(aIMCTX, 0, "integer overflow calculating scanline allocation");
189195 return NULL;
190196 }
191197
192 im = i_img_alloc();
198 im = im_img_alloc(aIMCTX);
193199 *im = IIM_base_16bit_direct;
194200 i_tags_new(&im->tags);
195201 im->xsize = x;
200206 im->idata = mymalloc(im->bytes);
201207 memset(im->idata, 0, im->bytes);
202208
203 i_img_init(im);
209 im_img_init(aIMCTX, im);
204210
205211 return im;
206212 }
222228 i_img *targ;
223229 i_fcolor *line;
224230 i_img_dim y;
225
226 targ = i_img_16_new(im->xsize, im->ysize, im->channels);
231 dIMCTXim(im);
232
233 targ = im_img_16_new(aIMCTX, im->xsize, im->ysize, im->channels);
227234 if (!targ)
228235 return NULL;
229236 line = mymalloc(sizeof(i_fcolor) * im->xsize);
434441 /* make sure we have good channel numbers */
435442 for (ch = 0; ch < chan_count; ++ch) {
436443 if (chans[ch] < 0 || chans[ch] >= im->channels) {
437 i_push_errorf(0, "No channel %d in this image", chans[ch]);
444 dIMCTXim(im);
445 im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
438446 return 0;
439447 }
440448 }
448456 }
449457 else {
450458 if (chan_count <= 0 || chan_count > im->channels) {
451 i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels",
459 dIMCTXim(im);
460 im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels",
452461 chan_count);
453462 return 0;
454463 }
485494 /* make sure we have good channel numbers */
486495 for (ch = 0; ch < chan_count; ++ch) {
487496 if (chans[ch] < 0 || chans[ch] >= im->channels) {
488 i_push_errorf(0, "No channel %d in this image", chans[ch]);
497 dIMCTXim(im);
498 im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
489499 return 0;
490500 }
491501 }
499509 }
500510 else {
501511 if (chan_count <= 0 || chan_count > im->channels) {
502 i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels",
512 dIMCTXim(im);
513 im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels",
503514 chan_count);
504515 return 0;
505516 }
541552 /* make sure we have good channel numbers */
542553 for (ch = 0; ch < chan_count; ++ch) {
543554 if (chans[ch] < 0 || chans[ch] >= im->channels) {
544 i_push_errorf(0, "No channel %d in this image", chans[ch]);
555 dIMCTXim(im);
556 im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
545557 return -1;
546558 }
547559 }
555567 }
556568 else {
557569 if (chan_count <= 0 || chan_count > im->channels) {
570 dIMCTXim(im);
558571 i_push_error(0, "Invalid channel count");
559572 return -1;
560573 }
570583 return count;
571584 }
572585 else {
586 dIMCTXim(im);
573587 i_push_error(0, "Image position outside of image");
574588 return -1;
575589 }
583597 i_img_dim off;
584598
585599 if (bits != 16) {
600 dIMCTXim(im);
586601 i_push_error(0, "Invalid bits for 16-bit image");
587602 return -1;
588603 }
598613 /* make sure we have good channel numbers */
599614 for (ch = 0; ch < chan_count; ++ch) {
600615 if (chans[ch] < 0 || chans[ch] >= im->channels) {
601 i_push_errorf(0, "No channel %d in this image", chans[ch]);
616 dIMCTXim(im);
617 im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
602618 return -1;
603619 }
604620 }
614630 }
615631 else {
616632 if (chan_count <= 0 || chan_count > im->channels) {
633 dIMCTXim(im);
617634 i_push_error(0, "Invalid channel count");
618635 return -1;
619636 }
631648 return count;
632649 }
633650 else {
651 dIMCTXim(im);
634652 i_push_error(0, "Image position outside of image");
635653 return -1;
636654 }
670688 int all_in_mask = 1;
671689 for (ch = 0; ch < chan_count; ++ch) {
672690 if (chans[ch] < 0 || chans[ch] >= im->channels) {
673 i_push_errorf(0, "No channel %d in this image", chans[ch]);
691 dIMCTXim(im);
692 im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
674693 return -1;
675694 }
676695 if (!((1 << chans[ch]) & im->ch_mask))
700719 }
701720 else {
702721 if (chan_count <= 0 || chan_count > im->channels) {
703 i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels",
722 dIMCTXim(im);
723 im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels",
704724 chan_count);
705725 return -1;
706726 }
720740 return count;
721741 }
722742 else {
743 dIMCTXim(im);
723744 i_push_error(0, "Image position outside of image");
724745 return -1;
725746 }
759780 int all_in_mask = 1;
760781 for (ch = 0; ch < chan_count; ++ch) {
761782 if (chans[ch] < 0 || chans[ch] >= im->channels) {
762 i_push_errorf(0, "No channel %d in this image", chans[ch]);
783 dIMCTXim(im);
784 im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
763785 return -1;
764786 }
765787 if (!((1 << chans[ch]) & im->ch_mask))
792814 }
793815 else {
794816 if (chan_count <= 0 || chan_count > im->channels) {
795 i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels",
817 dIMCTXim(im);
818 im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels",
796819 chan_count);
797820 return -1;
798821 }
814837 return count;
815838 }
816839 else {
840 dIMCTXim(im);
817841 i_push_error(0, "Image position outside of image");
818842 return -1;
819843 }
0 #define IMAGER_NO_CONTEXT
1
02 #include "imager.h"
13 #include "imageri.h"
24
7981 }*/
8082
8183 /*
82 =item i_img_8_new(x, y, ch)
83
84 =item im_img_8_new(ctx, x, y, ch)
85 X<im_img_8_new API>X<i_img_8_new API>
8486 =category Image creation/destruction
85
87 =synopsis i_img *img = im_img_8_new(aIMCTX, width, height, channels);
8688 =synopsis i_img *img = i_img_8_new(width, height, channels);
8789
8890 Creates a new image object I<x> pixels wide, and I<y> pixels high with
9193 =cut
9294 */
9395
94
9596 i_img *
96 i_img_8_new(i_img_dim x,i_img_dim y,int ch) {
97 im_img_8_new(pIMCTX, i_img_dim x,i_img_dim y,int ch) {
9798 i_img *im;
9899
99 mm_log((1,"IIM_new(x %" i_DF ", y %" i_DF ", ch %d)\n",
100 im_log((aIMCTX, 1,"im_img_8_new(x %" i_DF ", y %" i_DF ", ch %d)\n",
100101 i_DFc(x), i_DFc(y), ch));
101102
102 im=i_img_empty_ch(NULL,x,y,ch);
103 im = im_img_empty_ch(aIMCTX, NULL,x,y,ch);
103104
104 mm_log((1,"(%p) <- IIM_new\n",im));
105 return im;
106 }
107
108 /*
109 =item i_img_new()
110
111 Create new image reference - notice that this isn't an object yet and
112 this should be fixed asap.
113
114 =cut
115 */
116
117
118 i_img *
119 i_img_new() {
120 i_img *im;
121
122 mm_log((1,"i_img_struct()\n"));
123
124 im = i_img_alloc();
125
126 *im = IIM_base_8bit_direct;
127 im->xsize=0;
128 im->ysize=0;
129 im->channels=3;
130 im->ch_mask=MAXINT;
131 im->bytes=0;
132 im->idata=NULL;
133
134 i_img_init(im);
135
136 mm_log((1,"(%p) <- i_img_struct\n",im));
105 im_log((aIMCTX, 1,"(%p) <- IIM_new\n",im));
137106 return im;
138107 }
139108
154123 */
155124
156125 i_img *
157 i_img_empty(i_img *im,i_img_dim x,i_img_dim y) {
158 mm_log((1,"i_img_empty(*im %p, x %" i_DF ", y %" i_DF ")\n",
126 im_img_empty(pIMCTX, i_img *im,i_img_dim x,i_img_dim y) {
127 im_log((aIMCTX, 1,"i_img_empty(*im %p, x %" i_DF ", y %" i_DF ")\n",
159128 im, i_DFc(x), i_DFc(y)));
160 return i_img_empty_ch(im, x, y, 3);
129 return im_img_empty_ch(aIMCTX, im, x, y, 3);
161130 }
162131
163132 /*
174143 */
175144
176145 i_img *
177 i_img_empty_ch(i_img *im,i_img_dim x,i_img_dim y,int ch) {
146 im_img_empty_ch(pIMCTX, i_img *im,i_img_dim x,i_img_dim y,int ch) {
178147 size_t bytes;
179148
180 mm_log((1,"i_img_empty_ch(*im %p, x %" i_DF ", y %" i_DF ", ch %d)\n",
149 im_log((aIMCTX, 1,"i_img_empty_ch(*im %p, x %" i_DF ", y %" i_DF ", ch %d)\n",
181150 im, i_DFc(x), i_DFc(y), ch));
182151
183152 if (x < 1 || y < 1) {
184 i_push_error(0, "Image sizes must be positive");
153 im_push_error(aIMCTX, 0, "Image sizes must be positive");
185154 return NULL;
186155 }
187156 if (ch < 1 || ch > MAXCHANNELS) {
188 i_push_errorf(0, "channels must be between 1 and %d", MAXCHANNELS);
157 im_push_errorf(aIMCTX, 0, "channels must be between 1 and %d", MAXCHANNELS);
189158 return NULL;
190159 }
191160 /* check this multiplication doesn't overflow */
192161 bytes = x*y*ch;
193162 if (bytes / y / ch != x) {
194 i_push_errorf(0, "integer overflow calculating image allocation");
163 im_push_errorf(aIMCTX, 0, "integer overflow calculating image allocation");
195164 return NULL;
196165 }
197166
198167 if (im == NULL)
199 im = i_img_alloc();
168 im = im_img_alloc(aIMCTX);
200169
201170 memcpy(im, &IIM_base_8bit_direct, sizeof(i_img));
202171 i_tags_new(&im->tags);
206175 im->ch_mask = MAXINT;
207176 im->bytes=bytes;
208177 if ( (im->idata=mymalloc(im->bytes)) == NULL)
209 i_fatal(2,"malloc() error\n");
178 im_fatal(aIMCTX, 2,"malloc() error\n");
210179 memset(im->idata,0,(size_t)im->bytes);
211180
212181 im->ext_data = NULL;
213182
214 i_img_init(im);
183 im_img_init(aIMCTX, im);
215184
216 mm_log((1,"(%p) <- i_img_empty_ch\n",im));
185 im_log((aIMCTX, 1,"(%p) <- i_img_empty_ch\n",im));
217186 return im;
218187 }
219188
502471 /* make sure we have good channel numbers */
503472 for (ch = 0; ch < chan_count; ++ch) {
504473 if (chans[ch] < 0 || chans[ch] >= im->channels) {
505 i_push_errorf(0, "No channel %d in this image", chans[ch]);
474 dIMCTXim(im);
475 im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
506476 return 0;
507477 }
508478 }
516486 }
517487 else {
518488 if (chan_count <= 0 || chan_count > im->channels) {
519 i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels",
489 dIMCTXim(im);
490 im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels",
520491 chan_count);
521492 return 0;
522493 }
556527 unsigned char *data;
557528 for (ch = 0; ch < chan_count; ++ch) {
558529 if (chans[ch] < 0 || chans[ch] >= im->channels) {
559 i_push_errorf(0, "No channel %d in this image", chans[ch]);
530 dIMCTXim(im);
531 im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
560532 }
561533 }
562534 if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
570542 /* make sure we have good channel numbers */
571543 for (ch = 0; ch < chan_count; ++ch) {
572544 if (chans[ch] < 0 || chans[ch] >= im->channels) {
573 i_push_errorf(0, "No channel %d in this image", chans[ch]);
545 dIMCTXim(im);
546 im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
574547 return 0;
575548 }
576549 }
584557 }
585558 else {
586559 if (chan_count <= 0 || chan_count > im->channels) {
587 i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels",
560 dIMCTXim(im);
561 im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels",
588562 chan_count);
589563 return 0;
590564 }
637611 int all_in_mask = 1;
638612 for (ch = 0; ch < chan_count; ++ch) {
639613 if (chans[ch] < 0 || chans[ch] >= im->channels) {
640 i_push_errorf(0, "No channel %d in this image", chans[ch]);
614 dIMCTXim(im);
615 im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
641616 return -1;
642617 }
643618 if (!((1 << chans[ch]) & im->ch_mask))
666641 }
667642 else {
668643 if (chan_count <= 0 || chan_count > im->channels) {
669 i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels",
644 dIMCTXim(im);
645 im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels",
670646 chan_count);
671647 return -1;
672648 }
686662 return count;
687663 }
688664 else {
665 dIMCTXim(im);
689666 i_push_error(0, "Image position outside of image");
690667 return -1;
691668 }
725702 int all_in_mask = 1;
726703 for (ch = 0; ch < chan_count; ++ch) {
727704 if (chans[ch] < 0 || chans[ch] >= im->channels) {
728 i_push_errorf(0, "No channel %d in this image", chans[ch]);
705 dIMCTXim(im);
706 im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
729707 return -1;
730708 }
731709 if (!((1 << chans[ch]) & im->ch_mask))
755733 }
756734 else {
757735 if (chan_count <= 0 || chan_count > im->channels) {
758 i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels",
736 dIMCTXim(im);
737 im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels",
759738 chan_count);
760739 return -1;
761740 }
775754 return count;
776755 }
777756 else {
757 dIMCTXim(im);
778758 i_push_error(0, "Image position outside of image");
779759 return -1;
780760 }
1919 =cut
2020 */
2121
22 #define IMAGER_NO_CONTEXT
2223 #include "imager.h"
2324 #include "imageri.h"
2425
9091 };
9192
9293 /*
93 =item i_img_double_new(i_img_dim x, i_img_dim y, int ch)
94 =item im_img_double_new(ctx, x, y, ch)
95 X<im_img_double_new API>X<i_img_double_new API>
9496 =category Image creation/destruction
97 =synopsis i_img *img = im_img_double_new(aIMCTX, width, height, channels);
9598 =synopsis i_img *img = i_img_double_new(width, height, channels);
9699
97100 Creates a new double per sample image.
101
102 Also callable as C<i_img_double_new(width, height, channels)>.
98103
99104 =cut
100105 */
101 i_img *i_img_double_new(i_img_dim x, i_img_dim y, int ch) {
106 i_img *
107 im_img_double_new(pIMCTX, i_img_dim x, i_img_dim y, int ch) {
102108 size_t bytes;
103109 i_img *im;
104110
105 mm_log((1,"i_img_double_new(x %" i_DF ", y %" i_DF ", ch %d)\n",
111 im_log((aIMCTX, 1,"i_img_double_new(x %" i_DF ", y %" i_DF ", ch %d)\n",
106112 i_DFc(x), i_DFc(y), ch));
107113
108114 if (x < 1 || y < 1) {
109 i_push_error(0, "Image sizes must be positive");
115 im_push_error(aIMCTX, 0, "Image sizes must be positive");
110116 return NULL;
111117 }
112118 if (ch < 1 || ch > MAXCHANNELS) {
113 i_push_errorf(0, "channels must be between 1 and %d", MAXCHANNELS);
119 im_push_errorf(aIMCTX, 0, "channels must be between 1 and %d", MAXCHANNELS);
114120 return NULL;
115121 }
116122 bytes = x * y * ch * sizeof(double);
117123 if (bytes / y / ch / sizeof(double) != x) {
118 i_push_errorf(0, "integer overflow calculating image allocation");
124 im_push_errorf(aIMCTX, 0, "integer overflow calculating image allocation");
119125 return NULL;
120126 }
121127
122 im = i_img_alloc();
128 im = im_img_alloc(aIMCTX);
123129 *im = IIM_base_double_direct;
124130 i_tags_new(&im->tags);
125131 im->xsize = x;
129135 im->ext_data = NULL;
130136 im->idata = mymalloc(im->bytes);
131137 memset(im->idata, 0, im->bytes);
132 i_img_init(im);
138 im_img_init(aIMCTX, im);
133139
134140 return im;
135141 }
331337 /* make sure we have good channel numbers */
332338 for (ch = 0; ch < chan_count; ++ch) {
333339 if (chans[ch] < 0 || chans[ch] >= im->channels) {
334 i_push_errorf(0, "No channel %d in this image", chans[ch]);
340 dIMCTXim(im);
341 im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
335342 return 0;
336343 }
337344 }
345352 }
346353 else {
347354 if (chan_count <= 0 || chan_count > im->channels) {
348 i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels",
355 dIMCTXim(im);
356 im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels",
349357 chan_count);
350358 return 0;
351359 }
382390 /* make sure we have good channel numbers */
383391 for (ch = 0; ch < chan_count; ++ch) {
384392 if (chans[ch] < 0 || chans[ch] >= im->channels) {
385 i_push_errorf(0, "No channel %d in this image", chans[ch]);
393 dIMCTXim(im);
394 im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
386395 return 0;
387396 }
388397 }
396405 }
397406 else {
398407 if (chan_count <= 0 || chan_count > im->channels) {
399 i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels",
408 dIMCTXim(im);
409 im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels",
400410 chan_count);
401411 return 0;
402412 }
450460 int all_in_mask = 1;
451461 for (ch = 0; ch < chan_count; ++ch) {
452462 if (chans[ch] < 0 || chans[ch] >= im->channels) {
453 i_push_errorf(0, "No channel %d in this image", chans[ch]);
463 dIMCTXim(im);
464 im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
454465 return -1;
455466 }
456467 if (!((1 << chans[ch]) & im->ch_mask))
481492 }
482493 else {
483494 if (chan_count <= 0 || chan_count > im->channels) {
484 i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels",
495 dIMCTXim(im);
496 im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels",
485497 chan_count);
486498 return -1;
487499 }
502514 return count;
503515 }
504516 else {
517 dIMCTXim(im);
505518 i_push_error(0, "Image position outside of image");
506519 return -1;
507520 }
541554 int all_in_mask = 1;
542555 for (ch = 0; ch < chan_count; ++ch) {
543556 if (chans[ch] < 0 || chans[ch] >= im->channels) {
544 i_push_errorf(0, "No channel %d in this image", chans[ch]);
557 dIMCTXim(im);
558 im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
545559 return -1;
546560 }
547561 if (!((1 << chans[ch]) & im->ch_mask))
572586 }
573587 else {
574588 if (chan_count <= 0 || chan_count > im->channels) {
575 i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels",
589 dIMCTXim(im);
590 im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels",
576591 chan_count);
577592 return -1;
578593 }
593608 return count;
594609 }
595610 else {
611 dIMCTXim(im);
596612 i_push_error(0, "Image position outside of image");
597613 return -1;
598614 }
615631 i_img *targ;
616632 i_fcolor *line;
617633 i_img_dim y;
618
619 targ = i_img_double_new(im->xsize, im->ysize, im->channels);
634 dIMCTXim(im);
635
636 targ = im_img_double_new(aIMCTX, im->xsize, im->ysize, im->channels);
620637 if (!targ)
621638 return NULL;
622639 line = mymalloc(sizeof(i_fcolor) * im->xsize);
7474 #define i_psampf(im, l, r, y, samps, chans, count) \
7575 (((im)->i_f_psampf)((im), (l), (r), (y), (samps), (chans), (count)))
7676
77 #ifndef IMAGER_DIRECT_IMAGE_CALLS
78 #define IMAGER_DIRECT_IMAGE_CALLS 1
7779 #endif
80
81 #if IMAGER_DIRECT_IMAGE_CALLS
82
83 #define i_ppix(im, x, y, val) (((im)->i_f_ppix)((im), (x), (y), (val)))
84 #define i_gpix(im, x, y, val) (((im)->i_f_gpix)((im), (x), (y), (val)))
85 #define i_ppixf(im, x, y, val) (((im)->i_f_ppixf)((im), (x), (y), (val)))
86 #define i_gpixf(im, x, y, val) (((im)->i_f_gpixf)((im), (x), (y), (val)))
87 #define i_plin(im, l, r, y, val) (((im)->i_f_plin)(im, l, r, y, val))
88 #define i_glin(im, l, r, y, val) (((im)->i_f_glin)(im, l, r, y, val))
89 #define i_plinf(im, l, r, y, val) (((im)->i_f_plinf)(im, l, r, y, val))
90 #define i_glinf(im, l, r, y, val) (((im)->i_f_glinf)(im, l, r, y, val))
91
92 #define i_gsamp(im, l, r, y, samps, chans, count) \
93 (((im)->i_f_gsamp)((im), (l), (r), (y), (samps), (chans), (count)))
94 #define i_gsampf(im, l, r, y, samps, chans, count) \
95 (((im)->i_f_gsampf)((im), (l), (r), (y), (samps), (chans), (count)))
96
97 #endif
98
99 #define i_gsamp_bits(im, l, r, y, samps, chans, count, bits) \
100 (((im)->i_f_gsamp_bits) ? ((im)->i_f_gsamp_bits)((im), (l), (r), (y), (samps), (chans), (count), (bits)) : -1)
101 #define i_psamp_bits(im, l, r, y, samps, chans, count, bits) \
102 (((im)->i_f_psamp_bits) ? ((im)->i_f_psamp_bits)((im), (l), (r), (y), (samps), (chans), (count), (bits)) : -1)
103
104 #define i_findcolor(im, color, entry) \
105 (((im)->i_f_findcolor) ? ((im)->i_f_findcolor)((im), (color), (entry)) : 0)
106
107 #define i_gpal(im, l, r, y, vals) \
108 (((im)->i_f_gpal) ? ((im)->i_f_gpal)((im), (l), (r), (y), (vals)) : 0)
109 #define i_ppal(im, l, r, y, vals) \
110 (((im)->i_f_ppal) ? ((im)->i_f_ppal)((im), (l), (r), (y), (vals)) : 0)
111 #define i_addcolors(im, colors, count) \
112 (((im)->i_f_addcolors) ? ((im)->i_f_addcolors)((im), (colors), (count)) : -1)
113 #define i_getcolors(im, index, color, count) \
114 (((im)->i_f_getcolors) ? \
115 ((im)->i_f_getcolors)((im), (index), (color), (count)) : 0)
116 #define i_setcolors(im, index, color, count) \
117 (((im)->i_f_setcolors) ? \
118 ((im)->i_f_setcolors)((im), (index), (color), (count)) : 0)
119 #define i_colorcount(im) \
120 (((im)->i_f_colorcount) ? ((im)->i_f_colorcount)(im) : -1)
121 #define i_maxcolors(im) \
122 (((im)->i_f_maxcolors) ? ((im)->i_f_maxcolors)(im) : -1)
123 #define i_findcolor(im, color, entry) \
124 (((im)->i_f_findcolor) ? ((im)->i_f_findcolor)((im), (color), (entry)) : 0)
125
126 #define i_img_virtual(im) ((im)->virtual)
127 #define i_img_type(im) ((im)->type)
128 #define i_img_bits(im) ((im)->bits)
129
130 #define pIMCTX im_context_t my_im_ctx
131
132 #ifdef IMAGER_NO_CONTEXT
133 #define dIMCTXctx(ctx) pIMCTX = (ctx)
134 #define dIMCTX dIMCTXctx(im_get_context())
135 #define dIMCTXim(im) dIMCTXctx((im)->context)
136 #define dIMCTXio(io) dIMCTXctx((io)->context)
137 #define aIMCTX my_im_ctx
138 #else
139 #define aIMCTX im_get_context()
140 #endif
141
142 #define i_img_8_new(xsize, ysize, channels) im_img_8_new(aIMCTX, (xsize), (ysize), (channels))
143 #define i_img_16_new(xsize, ysize, channels) im_img_16_new(aIMCTX, (xsize), (ysize), (channels))
144 #define i_img_double_new(xsize, ysize, channels) im_img_double_new(aIMCTX, (xsize), (ysize), (channels))
145 #define i_img_pal_new(xsize, ysize, channels, maxpal) im_img_pal_new(aIMCTX, (xsize), (ysize), (channels), (maxpal))
146
147 #define i_img_alloc() im_img_alloc(aIMCTX)
148 #define i_img_init(im) im_img_init(aIMCTX, im)
149
150 #define i_set_image_file_limits(width, height, bytes) im_set_image_file_limits(aIMCTX, width, height, bytes)
151 #define i_get_image_file_limits(width, height, bytes) im_get_image_file_limits(aIMCTX, width, height, bytes)
152 #define i_int_check_image_file_limits(width, height, channels, sample_size) im_int_check_image_file_limits(aIMCTX, width, height, channels, sample_size)
153
154 #define i_clear_error() im_clear_error(aIMCTX)
155 #define i_push_errorvf(code, fmt, args) im_push_errorvf(aIMCTX, code, fmt, args)
156 #define i_push_error(code, msg) im_push_error(aIMCTX, code, msg)
157 #define i_errors() im_errors(aIMCTX)
158
159 #define io_new_fd(fd) im_io_new_fd(aIMCTX, (fd))
160 #define io_new_bufchain() im_io_new_bufchain(aIMCTX)
161 #define io_new_buffer(data, len, closecb, closectx) im_io_new_buffer(aIMCTX, (data), (len), (closecb), (closectx))
162 #define io_new_cb(p, readcb, writecb, seekcb, closecb, destroycb) \
163 im_io_new_cb(aIMCTX, (p), (readcb), (writecb), (seekcb), (closecb), (destroycb))
164
165 #endif
0 #ifndef IMAGER_IMPERLIO_H
1 #define IMAGER_IMPERLIO_H
2
3 extern i_io_glue_t *
4 im_io_new_perlio(pTHX_ PerlIO *handle);
5
6 #endif
0 #define IMAGER_NO_CONTEXT
01 #include "imager.h"
12 #include "iolayer.h"
23 #include "imerror.h"
112113 */
113114
114115 static void
115 i_io_init(io_glue *ig, int type, i_io_readp_t readcb, i_io_writep_t writecb,
116 i_io_seekp_t seekcb);
116 i_io_init(pIMCTX, io_glue *ig, int type, i_io_readp_t readcb,
117 i_io_writep_t writecb, i_io_seekp_t seekcb);
117118
118119 static ssize_t fd_read(io_glue *ig, void *buf, size_t count);
119120 static ssize_t fd_write(io_glue *ig, const void *buf, size_t count);
152153 */
153154
154155 /*
155 =item io_new_bufchain()
156 =item im_io_new_bufchain(ctx)
157 X<im_io_new_bufchain API>X<i_io_new_bufchain API>
156158 =order 10
157159 =category I/O Layers
158160
159 returns a new io_glue object that has the 'empty' source and but can
161 Returns a new io_glue object that has the 'empty' source and but can
160162 be written to and read from later (like a pseudo file).
161163
164 Also callable as C<io_new_bufchain()>.
165
162166 =cut
163167 */
164168
165169 io_glue *
166 io_new_bufchain() {
170 im_io_new_bufchain(pIMCTX) {
167171 io_glue *ig;
168172 io_ex_bchain *ieb = mymalloc(sizeof(io_ex_bchain));
169173
170 mm_log((1, "io_new_bufchain()\n"));
174 im_log((aIMCTX, 1, "io_new_bufchain()\n"));
171175
172176 ig = mymalloc(sizeof(io_glue));
173177 memset(ig, 0, sizeof(*ig));
174 i_io_init(ig, BUFCHAIN, bufchain_read, bufchain_write, bufchain_seek);
178 i_io_init(aIMCTX, ig, BUFCHAIN, bufchain_read, bufchain_write, bufchain_seek);
175179
176180 ieb->offset = 0;
177181 ieb->length = 0;
187191 ig->closecb = bufchain_close;
188192 ig->destroycb = bufchain_destroy;
189193
194 im_context_refinc(aIMCTX, "im_io_new_bufchain");
195
190196 return ig;
191197 }
192198
193199 /*
194 =item io_new_buffer(data, length)
200 =item im_io_new_buffer(ctx, data, length)
201 X<im_io_new_buffer API>X<io_new_buffer API>
195202 =order 10
196203 =category I/O Layers
197204
198205 Returns a new io_glue object that has the source defined as reading
199206 from specified buffer. Note that the buffer is not copied.
200207
208 ctx - an Imager context object
201209 data - buffer to read from
202210 length - length of buffer
203211
212 Also callable as C<io_new_buffer(data, length>.
213
204214 =cut
205215 */
206216
207217 io_glue *
208 io_new_buffer(const char *data, size_t len, i_io_closebufp_t closecb, void *closedata) {
218 im_io_new_buffer(pIMCTX, const char *data, size_t len, i_io_closebufp_t closecb, void *closedata) {
209219 io_buffer *ig;
210220
211 mm_log((1, "io_new_buffer(data %p, len %ld, closecb %p, closedata %p)\n", data, (long)len, closecb, closedata));
221 im_log((aIMCTX, 1, "io_new_buffer(data %p, len %ld, closecb %p, closedata %p)\n", data, (long)len, closecb, closedata));
212222
213223 ig = mymalloc(sizeof(io_buffer));
214224 memset(ig, 0, sizeof(*ig));
215 i_io_init(&ig->base, BUFFER, buffer_read, buffer_write, buffer_seek);
225 i_io_init(aIMCTX, &ig->base, BUFFER, buffer_read, buffer_write, buffer_seek);
216226 ig->data = data;
217227 ig->len = len;
218228 ig->closecb = closecb;
223233 ig->base.closecb = buffer_close;
224234 ig->base.destroycb = buffer_destroy;
225235
236 im_context_refinc(aIMCTX, "im_io_new_bufchain");
237
226238 return (io_glue *)ig;
227239 }
228240
229241
230242 /*
231 =item io_new_fd(fd)
243 =item im_io_new_fd(ctx, file)
244 X<io_new_fd API>X<im_io_new_fd API>
232245 =order 10
233246 =category I/O Layers
234247
235 returns a new io_glue object that has the source defined as reading
248 Returns a new io_glue object that has the source defined as reading
236249 from specified file descriptor. Note that the the interface to receiving
237250 data from the io_glue callbacks hasn't been done yet.
238251
239 fd - file descriptor to read/write from
252 ctx - and Imager context object
253 file - file descriptor to read/write from
254
255 Also callable as C<io_new_fd(file)>.
240256
241257 =cut
242258 */
243259
244260 io_glue *
245 io_new_fd(int fd) {
261 im_io_new_fd(pIMCTX, int fd) {
246262 io_fdseek *ig;
247263
248 mm_log((1, "io_new_fd(fd %d)\n", fd));
264 im_log((aIMCTX, 1, "io_new_fd(fd %d)\n", fd));
249265
250266 ig = mymalloc(sizeof(io_fdseek));
251267 memset(ig, 0, sizeof(*ig));
252 i_io_init(&ig->base, FDSEEK, fd_read, fd_write, fd_seek);
268 i_io_init(aIMCTX, &ig->base, FDSEEK, fd_read, fd_write, fd_seek);
253269 ig->fd = fd;
254270
255271 ig->base.closecb = fd_close;
256272 ig->base.sizecb = fd_size;
257273 ig->base.destroycb = NULL;
258
259 mm_log((1, "(%p) <- io_new_fd\n", ig));
274 im_context_refinc(aIMCTX, "im_io_new_bufchain");
275
276 im_log((aIMCTX, 1, "(%p) <- io_new_fd\n", ig));
260277 return (io_glue *)ig;
261278 }
262279
263280 /*
264 =item io_new_cb(p, read_cb, write_cb, seek_cb, close_cb, destroy_cb)
281 =item im_io_new_cb(ctx, p, read_cb, write_cb, seek_cb, close_cb, destroy_cb)
282 X<im_io_new_cb API>X<io_new_cb API>
265283 =category I/O Layers
266284 =order 10
267285
299317
300318 =back
301319
320 Also callable as C<io_new_cb(p, readcb, writecb, seekcb, closecb,
321 destroycb)>.
322
302323 =cut
303324 */
304325
305326 io_glue *
306 io_new_cb(void *p, i_io_readl_t readcb, i_io_writel_t writecb,
327 im_io_new_cb(pIMCTX, void *p, i_io_readl_t readcb, i_io_writel_t writecb,
307328 i_io_seekl_t seekcb, i_io_closel_t closecb,
308329 i_io_destroyl_t destroycb) {
309330 io_cb *ig;
310331
311 mm_log((1, "io_new_cb(p %p, readcb %p, writecb %p, seekcb %p, closecb %p, "
332 im_log((aIMCTX, 1, "io_new_cb(p %p, readcb %p, writecb %p, seekcb %p, closecb %p, "
312333 "destroycb %p)\n", p, readcb, writecb, seekcb, closecb, destroycb));
313334 ig = mymalloc(sizeof(io_cb));
314335 memset(ig, 0, sizeof(*ig));
315 i_io_init(&ig->base, CBSEEK, realseek_read, realseek_write, realseek_seek);
316 mm_log((1, "(%p) <- io_new_cb\n", ig));
336 i_io_init(aIMCTX, &ig->base, CBSEEK, realseek_read, realseek_write, realseek_seek);
337 im_log((aIMCTX, 1, "(%p) <- io_new_cb\n", ig));
317338
318339 ig->base.closecb = realseek_close;
319340 ig->base.destroycb = realseek_destroy;
324345 ig->seekcb = seekcb;
325346 ig->closecb = closecb;
326347 ig->destroycb = destroycb;
348
349 im_context_refinc(aIMCTX, "im_io_new_bufchain");
327350
328351 return (io_glue *)ig;
329352 }
330353
331354 /*
332355 =item io_slurp(ig, c)
356 X<io_slurp API>
333357 =category I/O Layers
334358
335359 Takes the source that the io_glue is bound to and allocates space for
360384 io_type inn = ig->type;
361385
362386 if ( inn != BUFCHAIN ) {
363 i_fatal(0, "io_slurp: called on a source that is not from a bufchain\n");
387 dIMCTXio(ig);
388 im_fatal(aIMCTX, 0, "io_slurp: called on a source that is not from a bufchain\n");
364389 }
365390
366391 ieb = ig->exdata;
372397
373398 rc = bufchain_read(ig, cc, ieb->length);
374399
375 if (rc != ieb->length)
376 i_fatal(1, "io_slurp: bufchain_read returned an incomplete read: rc = %d, request was %d\n", rc, ieb->length);
400 if (rc != ieb->length) {
401 dIMCTXio(ig);
402 im_fatal(aIMCTX,1, "io_slurp: bufchain_read returned an incomplete read: rc = %d, request was %d\n", rc, ieb->length);
403 }
377404
378405 return rc;
379406 }
380407
381408 /*
382409 =item io_glue_destroy(ig)
410 X<io_glue_destroy API>
383411 =category I/O Layers
384412 =order 90
385413 =synopsis io_glue_destroy(ig);
393421
394422 void
395423 io_glue_destroy(io_glue *ig) {
396 mm_log((1, "io_glue_DESTROY(ig %p)\n", ig));
424 dIMCTXio(ig);
425 im_log((aIMCTX, 1, "io_glue_DESTROY(ig %p)\n", ig));
397426
398427 if (ig->destroycb)
399428 ig->destroycb(ig);
402431 myfree(ig->buffer);
403432
404433 myfree(ig);
434
435 im_context_refdec(aIMCTX, "io_glue_destroy");
405436 }
406437
407438 /*
526557 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn(%p, %p, %d)\n", ig, buf, (int)size));
527558
528559 if (size == 0) {
560 dIMCTXio(ig);
529561 i_push_error(0, "peekn size must be positive");
530562 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => -1 (zero size)\n"));
531563 return -1;
9731005 */
9741006
9751007 static void
976 i_io_init(io_glue *ig, int type, i_io_readp_t readcb, i_io_writep_t writecb,
1008 i_io_init(pIMCTX, io_glue *ig, int type, i_io_readp_t readcb, i_io_writep_t writecb,
9771009 i_io_seekp_t seekcb) {
9781010 ig->type = type;
9791011 ig->exdata = NULL;
9831015 ig->closecb = NULL;
9841016 ig->sizecb = NULL;
9851017 ig->destroycb = NULL;
1018 ig->context = aIMCTX;
9861019
9871020 ig->buffer = NULL;
9881021 ig->read_ptr = NULL;
11531186 work = ig->buffer;
11541187 }
11551188
1189 /* there should always be buffer space the first time around, but
1190 avoid a compiler warning here */
1191 rc = -1;
11561192 while (work < buf_end && (rc = i_io_raw_read(ig, work, buf_end - work)) > 0) {
11571193 work += rc;
11581194 good = 1;
13271363 int
13281364 realseek_close(io_glue *igo) {
13291365 io_cb *ig = (io_cb *)igo;
1366 dIMCTXio(igo);
13301367
13311368 IOL_DEB(fprintf(IOL_DEBs, "realseek_close(%p)\n", ig));
1332 mm_log((1, "realseek_close(ig %p)\n", ig));
1369 im_log((aIMCTX,1, "realseek_close(ig %p)\n", ig));
13331370 if (ig->closecb)
13341371 return ig->closecb(ig->p);
13351372 else
13961433 IOL_DEB( fprintf(IOL_DEBs, "buffer_read: ig->cpos = %ld, buf = %p, count = %u\n", (long) ig->cpos, buf, (unsigned)count) );
13971434
13981435 if ( ig->cpos+count > ig->len ) {
1399 mm_log((1,"buffer_read: short read: cpos=%ld, len=%ld, count=%ld\n", (long)ig->cpos, (long)ig->len, (long)count));
1436 dIMCTXio(igo);
1437 im_log((aIMCTX, 1,"buffer_read: short read: cpos=%ld, len=%ld, count=%ld\n", (long)ig->cpos, (long)ig->len, (long)count));
14001438 count = ig->len - ig->cpos;
14011439 }
14021440
14221460 static
14231461 ssize_t
14241462 buffer_write(io_glue *ig, const void *buf, size_t count) {
1425 mm_log((1, "buffer_write called, this method should never be called.\n"));
1463 dIMCTXio(ig);
1464 im_log((aIMCTX, 1, "buffer_write called, this method should never be called.\n"));
14261465 return -1;
14271466 }
14281467
14411480 static
14421481 int
14431482 buffer_close(io_glue *ig) {
1444 mm_log((1, "buffer_close(ig %p)\n", ig));
1483 dIMCTXio(ig);
1484 im_log((aIMCTX, 1, "buffer_close(ig %p)\n", ig));
14451485
14461486 return 0;
14471487 }
14661506 calc_seek_offset(ig->cpos, ig->len, offset, whence);
14671507
14681508 if (reqpos > ig->len) {
1469 mm_log((1, "seeking out of readable range\n"));
1509 dIMCTXio(igo);
1510 im_log((aIMCTX, 1, "seeking out of readable range\n"));
14701511 return (off_t)-1;
14711512 }
14721513 if (reqpos < 0) {
1514 dIMCTXio(igo);
14731515 i_push_error(0, "seek before beginning of file");
14741516 return (off_t)-1;
14751517 }
14871529 io_buffer *ig = (io_buffer *)igo;
14881530
14891531 if (ig->closecb) {
1490 mm_log((1,"calling close callback %p for io_buffer\n",
1532 dIMCTXio(igo);
1533 im_log((aIMCTX, 1,"calling close callback %p for io_buffer\n",
14911534 ig->closecb));
14921535 ig->closecb(ig->closedata);
14931536 }
15081551 io_blink_new(void) {
15091552 io_blink *ib;
15101553
1511 mm_log((1, "io_blink_new()\n"));
1554 #if 0
1555 im_log((aIMCTX, 1, "io_blink_new()\n"));
1556 #endif
15121557
15131558 ib = mymalloc(sizeof(io_blink));
15141559
15601605 static void
15611606 io_destroy_bufchain(io_ex_bchain *ieb) {
15621607 io_blink *cp;
1608 #if 0
15631609 mm_log((1, "io_destroy_bufchain(ieb %p)\n", ieb));
1610 #endif
15641611 cp = ieb->head;
15651612
15661613 while(cp) {
16911738 size_t scount = count;
16921739 char *cbuf = buf;
16931740 size_t sk;
1694
1695 mm_log((1, "bufchain_read(ig %p, buf %p, count %ld)\n", ig, buf, (long)count));
1741 dIMCTXio(ig);
1742
1743 im_log((aIMCTX, 1, "bufchain_read(ig %p, buf %p, count %ld)\n", ig, buf, (long)count));
16961744
16971745 while( scount ) {
16981746 int clen = (ieb->cp == ieb->tail) ? ieb->tfill : ieb->cp->len;
17121760 ieb->gpos += sk;
17131761 }
17141762
1715 mm_log((1, "bufchain_read: returning %ld\n", (long)(count-scount)));
1763 im_log((aIMCTX, 1, "bufchain_read: returning %ld\n", (long)(count-scount)));
17161764 return count-scount;
17171765 }
17181766
17391787 io_ex_bchain *ieb = ig->exdata;
17401788 size_t ocount = count;
17411789 size_t sk;
1742
1743 mm_log((1, "bufchain_write: ig = %p, buf = %p, count = %ld\n", ig, buf, (long)count));
1790 dIMCTXio(ig);
1791
1792 im_log((aIMCTX, 1, "bufchain_write: ig = %p, buf = %p, count = %ld\n", ig, buf, (long)count));
17441793
17451794 IOL_DEB( fprintf(IOL_DEBs, "bufchain_write: ig = %p, ieb->cpos = %ld, buf = %p, count = %ld\n", ig, (long) ieb->cpos, buf, (long)count) );
17461795
17471796 while(count) {
1748 mm_log((2, "bufchain_write: - looping - count = %ld\n", (long)count));
1797 im_log((aIMCTX, 2, "bufchain_write: - looping - count = %ld\n", (long)count));
17491798 if (ieb->cp->len == ieb->cpos) {
1750 mm_log((1, "bufchain_write: cp->len == ieb->cpos = %ld - advancing chain\n", (long) ieb->cpos));
1799 im_log((aIMCTX, 1, "bufchain_write: cp->len == ieb->cpos = %ld - advancing chain\n", (long) ieb->cpos));
17511800 io_bchain_advance(ieb);
17521801 }
17531802
17571806
17581807 if (ieb->cp == ieb->tail) {
17591808 int extend = ieb->cpos + sk - ieb->tfill;
1760 mm_log((2, "bufchain_write: extending tail by %d\n", extend));
1809 im_log((aIMCTX, 2, "bufchain_write: extending tail by %d\n", extend));
17611810 if (extend > 0) {
17621811 ieb->length += extend;
17631812 ieb->tfill += extend;
17851834 static
17861835 int
17871836 bufchain_close(io_glue *ig) {
1788 mm_log((1, "bufchain_close(ig %p)\n",ig));
1837 dIMCTXio(ig);
1838 im_log((aIMCTX, 1, "bufchain_close(ig %p)\n",ig));
17891839 IOL_DEB( fprintf(IOL_DEBs, "bufchain_close(ig %p)\n", ig) );
17901840
17911841 return 0;
18121862
18131863 off_t scount = calc_seek_offset(ieb->gpos, ieb->length, offset, whence);
18141864 off_t sk;
1815
1816 mm_log((1, "bufchain_seek(ig %p, offset %ld, whence %d)\n", ig, (long)offset, whence));
1865 dIMCTXio(ig);
1866
1867 im_log((aIMCTX, 1, "bufchain_seek(ig %p, offset %ld, whence %d)\n", ig, (long)offset, whence));
18171868
18181869 if (scount < 0) {
18191870 i_push_error(0, "invalid whence supplied or seek before start of file");
18551906
18561907 while(wrlen > 0) {
18571908 ssize_t rc, wl = i_min(wrlen, BBSIZ);
1858 mm_log((1, "bufchain_seek: wrlen = %d, wl = %ld\n", wrlen, (long)wl));
1909 im_log((aIMCTX, 1, "bufchain_seek: wrlen = %d, wl = %ld\n", wrlen, (long)wl));
18591910 rc = bufchain_write( ig, TB, wl );
1860 if (rc != wl) i_fatal(0, "bufchain_seek: Unable to extend file\n");
1911 if (rc != wl) im_fatal(aIMCTX, 0, "bufchain_seek: Unable to extend file\n");
18611912 wrlen -= rc;
18621913 }
18631914 }
18641915
1865 mm_log((2, "bufchain_seek: returning ieb->gpos = %ld\n", (long)ieb->gpos));
1916 im_log((aIMCTX, 2, "bufchain_seek: returning ieb->gpos = %ld\n", (long)ieb->gpos));
18661917 return ieb->gpos;
18671918 }
18681919
18971948
18981949 /* 0 is valid - means EOF */
18991950 if (result < 0) {
1900 i_push_errorf(0, "read() failure: %s (%d)", my_strerror(errno), errno);
1951 dIMCTXio(igo);
1952 im_push_errorf(aIMCTX, 0, "read() failure: %s (%d)", my_strerror(errno), errno);
19011953 }
19021954
19031955 return result;
19161968 (unsigned)count, (int)result));
19171969
19181970 if (result <= 0) {
1919 i_push_errorf(errno, "write() failure: %s (%d)", my_strerror(errno), errno);
1971 dIMCTXio(igo);
1972 im_push_errorf(aIMCTX, errno, "write() failure: %s (%d)", my_strerror(errno), errno);
19201973 }
19211974
19221975 return result;
19321985 #endif
19331986
19341987 if (result == (off_t)-1) {
1935 i_push_errorf(errno, "lseek() failure: %s (%d)", my_strerror(errno), errno);
1988 dIMCTXio(igo);
1989 im_push_errorf(aIMCTX, errno, "lseek() failure: %s (%d)", my_strerror(errno), errno);
19361990 }
19371991
19381992 return result;
19441998 }
19451999
19462000 static ssize_t fd_size(io_glue *ig) {
1947 mm_log((1, "fd_size(ig %p) unimplemented\n", ig));
2001 dIMCTXio(ig);
2002 im_log((aIMCTX, 1, "fd_size(ig %p) unimplemented\n", ig));
19482003
19492004 return -1;
19502005 }
2121 void io_glue_gettypes (io_glue *ig, int reqmeth);
2222
2323 /* XS functions */
24 io_glue *io_new_fd(int fd);
25 io_glue *io_new_bufchain(void);
26 io_glue *io_new_buffer(const char *data, size_t len, i_io_closebufp_t closecb, void *closedata);
27 io_glue *io_new_cb(void *p, i_io_readl_t readcb, i_io_writel_t writecb, i_io_seekl_t seekcb, i_io_closel_t closecb, i_io_destroyl_t destroycb);
24 io_glue *im_io_new_fd(pIMCTX, int fd);
25 io_glue *im_io_new_bufchain(pIMCTX);
26 io_glue *im_io_new_buffer(pIMCTX, const char *data, size_t len, i_io_closebufp_t closecb, void *closedata);
27 io_glue *im_io_new_cb(pIMCTX, void *p, i_io_readl_t readcb, i_io_writel_t writecb, i_io_seekl_t seekcb, i_io_closel_t closecb, i_io_destroyl_t destroycb);
2828 size_t io_slurp(io_glue *ig, unsigned char **c);
2929 void io_glue_destroy(io_glue *ig);
3030
6969
7070 /* if non-zero we do write buffering (enabled by default) */
7171 int buffered;
72
73 im_context_t context;
7274 };
7375
7476 #define I_IO_DUMP_CALLBACKS 1
2424 =for stopwords XS
2525
2626 The API allows you to access Imager functions at the C level from XS
27 and from Inline::C.
27 and from C<Inline::C>.
2828
2929 The intent is to allow users to:
3030
3333 =item *
3434
3535 write C code that does Imager operations the user might do from Perl,
36 but faster, for example, the Imager::CountColor example.
36 but faster, for example, the L<Imager::CountColor> example.
3737
3838 =item *
3939
6969
7070 =item *
7171
72 i_img - used to represent an image
73
74 =item *
75
76 i_color - used to represent a color with up to 8 bits per sample.
77
78 =item *
79
80 i_fcolor - used to represent a color with a double per sample.
81
82 =item *
83
84 i_fill_t - an abstract fill
72 L</i_img> - used to represent an image
73
74 =item *
75
76 L</i_color> - used to represent a color with up
77 to 8 bits per sample.
78
79 =item *
80
81 L</i_fcolor> - used to represent
82 a color with a double per sample.
83
84 =item *
85
86 L</i_fill_t> - fill objects>> - an abstract fill
87
88 =item *
89
90 L</im_context_t> - Imager's per-thread state.
8591
8692 =back
8793
8894 At this point there is no consolidated font object type, and hence the
8995 font functions are not visible through Imager's API.
9096
91 =head2 i_img - images
97 =head2 i_img
9298
9399 This contains the dimensions of the image (C<xsize>, C<ysize>,
94100 C<channels>), image metadata (C<ch_mask>, C<bits>, C<type>,
95 C<virtual>), potentially image data (C<idata>) and the a function
96 table, with pointers to functions to perform various low level image
101 C<virtual>), potentially image data (C<idata>) and a function table,
102 with pointers to functions to perform various low level image
97103 operations.
98104
99105 The only time you should directly write to any value in this type is
109115 Imager return type and a raw image object for an Imager::ImgRaw return
110116 type.
111117
112 =head2 C<i_color> - 8-bit color
118 =head2 i_color
113119
114120 Represents an 8-bit per sample color. This is a union containing
115121 several different structs for access to components of a color:
134140
135141 =back
136142
137 Use Imager::Color for parameter and return value types.
138
139 =head2 C<i_fcolor> - floating point color
143 Use C<Imager::Color> for parameter and return value types.
144
145 =head2 i_fcolor
140146
141147 Similar to C<i_color> except that each component is a double instead of
142148 an unsigned char.
143149
144150 Use Imager::Color::Float for parameter and return value types.
145151
146 =head2 C<i_fill_t> - fill objects
152 =head2 i_fill_t
147153
148154 Abstract type containing pointers called to perform low level fill
149155 operations.
154160 Use Imager::FillHandle for parameter and return value types. At the
155161 Perl level this is stored in the C<fill> member of the Perl level
156162 Imager::Fill object.
163
164 =head2 i_io_glue_t
165
166 C<i_io_glue_t> is Imager's I/O abstraction.
167
168 Historically named C<io_glue>, and this name is available for backward
169 compatibility.
170
171 =head2 im_context_t
172
173 This new type is an opaque type that stores Imager's per-thread state,
174 including the error message stack, the current log file state and
175 image size file limits.
176
177 While Imager's internal typemap provides a C<T_PTROBJ> mapping and a
178 DESTROY method for this type you B<must> never return objects of this
179 type back to perl.
180
181 See L</Context objects> for more information.
157182
158183 =head1 Create an XS module using the Imager API
159184
258283
259284 =back
260285
286 =head1 Context objects
287
288 Starting with Imager 0.93, Imager keeps some state per-thread rather
289 than storing it in global (or static) variables. The intent is to
290 improve support for multi-threaded perl programs.
291
292 For the typical XS or Inline::C module using Imager's API this won't
293 matter - the changes are hidden behind macros and rebuilding your
294 module should require no source code changes.
295
296 Some operations will be slightly slower, these include:
297
298 =over
299
300 =item *
301
302 creating an image
303
304 =item *
305
306 reporting errors
307
308 =item *
309
310 creating I/O objects
311
312 =item *
313
314 setting/getting/testing image file limits
315
316 =item *
317
318 logging
319
320 =back
321
322 You can avoid this fairly minor overhead by adding a C<#define>:
323
324 #define IMAGER_NO_CONTEXT
325
326 before including any Imager header files, but you will need to manage
327 context objects yourself.
328
329 Some functions and macros that are available without
330 C<IMAGER_NO_CONTEXT> are not available with it defined, these are:
331
332 =over
333
334 =item *
335
336 mm_log() - to avoid using a different context object for the line
337 header and the line text you need to use im_log() instead, with a
338 context object visible in scope.
339
340 =back
341
342 =head2 C<aIMCTX>
343
344 With C<IMAGER_NO_CONTEXT> defined, C<aIMCTX> refers to the locally
345 defined context object, either via one the of the C<dIMCTX> macros or
346 as a parameter with the C<pIMCTX> macro.
347
348 Without C<IMAGER_NO_CONTEXT>, C<aIMCTX> is a call to
349 C<im_get_context()> which retrieves the context object for the current
350 thread.
351
352 There is no C<aIMCTX_> macro, any Imager function that can accept a
353 context parameter always accepts it.
354
355 =head2 C<pIMCTX>
356
357 This macro declares a variable of type L</im_context_t> that's
358 accessible via the C<aIMCTX> macro. This is intended for use as a
359 parameter declaration for functions:
360
361 void f(pIMCTX) {
362 ... use aIMCTX here
363 }
364
365 void g(...) {
366 ...
367 f(aIMCTX);
368 }
369
370 =head2 C<dIMCTX>
371
372 Defines a local context variable and initializes it via
373 L<im_get_context()|Imager::APIRef/im_get_context()>.
374
375 =head2 C<dIMCTXim>
376
377 Defines a local context variable and initializes it from the context
378 stored in an L<image object|/i_img>, eg:
379
380 void f(i_img *im) {
381 dIMCTXim(im);
382 ...
383 }
384
385 =head2 C<dIMCTXio>
386
387 Defines a local context variable and initializes it from the context
388 stored in an L<I/O object|/i_io_glue_t> object.
389
390 void f(i_io_glue_t *io) {
391 dIMCTXio(io);
392 ...
393 }
394
395 =head2 C<dIMCTXctx>
396
397 Defines a local context variable accessible via C<aIMCTX> in terms of
398 an expression you supply:
399
400 void f(my_object *p) {
401 dIMCTXctx(p->context);
402 ...
403 }
404
405 This can be used to define your own local context macro:
406
407 #define dIMCTXmine(mine) ((mine)->context)
408
409 void f(my_object *p) {
410 dIMCTXmine(p);
411 ...
412 }
413
414 =head1 Mutex Functions
415
416 Since some libraries are not thread safe, Imager's API includes some
417 simple mutex functions.
418
419 To create a mutex:
420
421 i_mutex_t m = i_mutex_new();
422
423 To control or lock the mutex:
424
425 i_mutex_lock(m);
426
427 To release or unlock the mutex:
428
429 i_mutex_unlock(m);
430
431 To free any resources used by the mutex:
432
433 i_mutex_destroy(m);
434
435 I most cases where you'd use these functions, your code would create
436 the mutex in your BOOT section, then lock and unlock the mutex as
437 needed to control access to the library.
438
439 =head1 Context slots
440
441 =for stopwords
442 TLS APIs
443
444 To avoid abstracting the platform TLS and thread clean up handling,
445 Imager provides simple APIs for storing per-context information.
446
447 To allocate a slot:
448
449 im_slot_t slot = im_context_slot_new(callback)
450
451 where callback is a (possibly NULL) function pointer called when the
452 context object is destroyed.
453
454 By default, the stored value for a slot is NULL, whether for a new
455 context or for a cloned context.
456
457 To store a value:
458
459 im_context_slot_set(aIMCTX, slot, somevalue);
460
461 where C<somevalue> can be represented as a C<void *>.
462
463 To retrieve the value:
464
465 value = im_context_slot_get(aIMCTX, slot);
466
261467 =head1 AUTHOR
262468
263469 Tony Cook <tonyc@cpan.org>
3939 i_flood_cfill_border(im, 50, 50, fill, border);
4040
4141 # Error handling
42 im_clear_error(aIMCTX);
4243 i_clear_error();
4344 i_push_error(0, "Yep, it's broken");
4445 i_push_error(errno, "Error writing");
46 im_push_error(aIMCTX, 0, "Something is wrong");
47 va_args args;
48 va_start(args, lastarg);
49 im_push_errorvf(ctx, code, format, args);
4550 i_push_errorf(errno, "Cannot open file %s: %d", filename, errno);
51 im_push_errorf(aIMCTX, errno, "Cannot open file %s: %d", filename, errno);
4652
4753 # Files
54 im_set_image_file_limits(aIMCTX, 500, 500, 1000000);
4855 i_set_image_file_limits(500, 500, 1000000);
56 im_get_image_file_limits(aIMCTX, &width, &height, &bytes)
4957 i_get_image_file_limits(&width, &height, &bytes)
50 i_i_int_check_image_file_limits(width, height, channels, sizeof(i_sample_t))
58 im_int_check_image_file_limits(aIMCTX, width, height, channels, sizeof(i_sample_t))
59 i_int_check_image_file_limits(width, height, channels, sizeof(i_sample_t))
5160
5261 # Fills
5362 i_fill_t *fill = i_new_fill_solidf(&fcolor, combine);
7180 # Image creation/destruction
7281 i_img *img = i_sametype(src, width, height);
7382 i_img *img = i_sametype_chans(src, width, height, channels);
83 i_img *img = im_img_16_new(aIMCTX, width, height, channels);
7484 i_img *img = i_img_16_new(width, height, channels);
85 i_img *img = im_img_8_new(aIMCTX, width, height, channels);
7586 i_img *img = i_img_8_new(width, height, channels);
87 i_img *img = im_img_double_new(aIMCTX, width, height, channels);
7688 i_img *img = i_img_double_new(width, height, channels);
89 i_img *img = im_img_pal_new(aIMCTX, width, height, channels, max_palette_size)
7790 i_img *img = i_img_pal_new(width, height, channels, max_palette_size)
7891 i_img_destroy(img)
7992
8093 # Image Implementation
94 i_img *im = im_img_alloc(aIMCTX);
95 i_img *im = i_img_alloc();
96 im_img_init(aIMCTX, im);
97 i_img_init(im);
8198
8299 # Image Information
83100 // only channel 0 writable
91108
92109 # Logging
93110
111 # Mutex functions
112 i_mutex_t m = i_mutex_new();
113 i_mutex_destroy(m);
114 i_mutex_lock(m);
115 i_mutex_unlock(m);
116
94117 # Paletted images
95118
96119 # Tags
263286 =item *
264287
265288 i_f_psampf - implements psamp() for this image.
289
290 =item *
291
292 C<im_data> - image specific data internal to Imager.
293
294 =item *
295
296 C<context> - the Imager API context this image belongs to.
266297
267298 =back
268299
841872
842873 =over
843874
844 =item i_clear_error()
845
875 =item i_push_errorf(int code, char const *fmt, ...)
876
877 i_push_errorf(errno, "Cannot open file %s: %d", filename, errno);
878
879 A version of i_push_error() that does printf() like formatting.
880
881 Does not support perl specific format codes.
882
883
884 =for comment
885 From: File error.c
886
887 =item im_clear_error(ctx)
888 X<im_clear_error API>X<i_clear_error API>
889
890 im_clear_error(aIMCTX);
846891 i_clear_error();
847892
848893 Clears the error stack.
849894
850895 Called by any Imager function before doing any other processing.
851896
897 Also callable as C<i_clear_error()>.
898
852899
853900 =for comment
854901 From: File error.c
855902
856 =item i_push_error(int code, char const *msg)
903 =item im_push_error(ctx, code, message)
904 X<im_push_error API>X<i_push_error API>
857905
858906 i_push_error(0, "Yep, it's broken");
859907 i_push_error(errno, "Error writing");
908 im_push_error(aIMCTX, 0, "Something is wrong");
860909
861910 Called by an Imager function to push an error message onto the stack.
862911
868917 =for comment
869918 From: File error.c
870919
871 =item i_push_errorf(int code, char const *fmt, ...)
872
873 i_push_errorf(errno, "Cannot open file %s: %d", filename, errno);
874
875 A version of i_push_error() that does printf() like formatting.
920 =item im_push_errorf(ctx, code, char const *fmt, ...)
921
922 im_push_errorf(aIMCTX, errno, "Cannot open file %s: %d", filename, errno);
923
924 A version of im_push_error() that does printf() like formatting.
876925
877926 Does not support perl specific format codes.
878927
880929 =for comment
881930 From: File error.c
882931
883 =item i_push_errorvf(int C<code>, char const *C<fmt>, va_list C<ap>)
884
932 =item im_push_errorvf(ctx, code, format, args)
933 X<im_push_error_vf API>X<i_push_errorvf API>
934
935 va_args args;
936 va_start(args, lastarg);
937 im_push_errorvf(ctx, code, format, args);
885938
886939 Intended for use by higher level functions, takes a varargs pointer
887940 and a format to produce the finally pushed error message.
888941
889942 Does not support perl specific format codes.
890943
944 Also callable as C<i_push_errorvf(code, format, args)>
945
891946
892947 =for comment
893948 From: File error.c
928983 =for comment
929984 From: File image.c
930985
931 =item i_get_image_file_limits(&width, &height, &bytes)
932
933
986 =item im_get_image_file_limits(ctx, &width, &height, &bytes)
987 X<im_get_image_file_limits API>X<i_get_image_file_limits>
988
989 im_get_image_file_limits(aIMCTX, &width, &height, &bytes)
934990 i_get_image_file_limits(&width, &height, &bytes)
935991
936992 Retrieves the file limits set by i_set_image_file_limits().
9471003
9481004 =back
9491005
1006 Also callable as C<i_get_image_file_limits(&width, &height, &bytes)>.
1007
9501008
9511009 =for comment
9521010 From: File limits.c
9531011
954 =item i_int_check_image_file_limits(width, height, channels, sample_size)
955
956
957 i_i_int_check_image_file_limits(width, height, channels, sizeof(i_sample_t))
1012 =item im_int_check_image_file_limits(width, height, channels, sample_size)
1013 X<im_int_check_image_file_limits API>X<i_int_check_image_file_limits>
1014
1015 im_int_check_image_file_limits(aIMCTX, width, height, channels, sizeof(i_sample_t))
1016 i_int_check_image_file_limits(width, height, channels, sizeof(i_sample_t))
9581017
9591018 Checks the size of a file in memory against the configured image file
9601019 limits.
9661025
9671026 This function is intended to be called by image file read functions.
9681027
1028 Also callable as C<i_int_check_image_file_limits(width, height, channels, sizeof(i_sample_t)>.
1029
9691030
9701031 =for comment
9711032 From: File limits.c
9721033
973 =item i_set_image_file_limits(width, height, bytes)
974
975
1034 =item im_set_image_file_limits(ctx, width, height, bytes)
1035 X<im_set_image_file_limits API>X<i_set_image_file_limits API>
1036
1037 im_set_image_file_limits(aIMCTX, 500, 500, 1000000);
9761038 i_set_image_file_limits(500, 500, 1000000);
9771039
9781040 Set limits on the sizes of images read by Imager.
9971059 =back
9981060
9991061 Returns non-zero on success.
1062
1063 Also callable as C<i_set_image_file_limits(width, height, bytes)>.
10001064
10011065
10021066 =for comment
11241188
11251189 =over
11261190
1127 =item io_new_bufchain()
1128
1129 returns a new io_glue object that has the 'empty' source and but can
1191 =item im_io_new_bufchain(ctx)
1192 X<im_io_new_bufchain API>X<i_io_new_bufchain API>
1193
1194 Returns a new io_glue object that has the 'empty' source and but can
11301195 be written to and read from later (like a pseudo file).
11311196
1197 Also callable as C<io_new_bufchain()>.
1198
11321199
11331200 =for comment
11341201 From: File iolayer.c
11351202
1136 =item io_new_buffer(data, length)
1203 =item im_io_new_buffer(ctx, data, length)
1204 X<im_io_new_buffer API>X<io_new_buffer API>
11371205
11381206 Returns a new io_glue object that has the source defined as reading
11391207 from specified buffer. Note that the buffer is not copied.
11401208
1209 ctx - an Imager context object
11411210 data - buffer to read from
11421211 length - length of buffer
11431212
1213 Also callable as C<io_new_buffer(data, length>.
1214
11441215
11451216 =for comment
11461217 From: File iolayer.c
11471218
1148 =item io_new_cb(p, read_cb, write_cb, seek_cb, close_cb, destroy_cb)
1219 =item im_io_new_cb(ctx, p, read_cb, write_cb, seek_cb, close_cb, destroy_cb)
1220 X<im_io_new_cb API>X<io_new_cb API>
11491221
11501222 Create a new I/O layer object that calls your supplied callbacks.
11511223
11811253
11821254 =back
11831255
1256 Also callable as C<io_new_cb(p, readcb, writecb, seekcb, closecb,
1257 destroycb)>.
1258
11841259
11851260 =for comment
11861261 From: File iolayer.c
11871262
1188 =item io_new_fd(fd)
1189
1190 returns a new io_glue object that has the source defined as reading
1263 =item im_io_new_fd(ctx, file)
1264 X<io_new_fd API>X<im_io_new_fd API>
1265
1266 Returns a new io_glue object that has the source defined as reading
11911267 from specified file descriptor. Note that the the interface to receiving
11921268 data from the io_glue callbacks hasn't been done yet.
11931269
1194 fd - file descriptor to read/write from
1270 ctx - and Imager context object
1271 file - file descriptor to read/write from
1272
1273 Also callable as C<io_new_fd(file)>.
11951274
11961275
11971276 =for comment
13481427 From: File iolayer.c
13491428
13501429 =item io_slurp(ig, c)
1430 X<io_slurp API>
13511431
13521432 Takes the source that the io_glue is bound to and allocates space for
13531433 a return buffer and returns the entire content in a single buffer.
13701450 From: File iolayer.c
13711451
13721452 =item io_glue_destroy(ig)
1453 X<io_glue_destroy API>
13731454
13741455 io_glue_destroy(ig);
13751456
14671548
14681549 =over
14691550
1470 =item i_img_16_new(x, y, ch)
1471
1472
1551 =item i_sametype(C<im>, C<xsize>, C<ysize>)
1552
1553
1554 i_img *img = i_sametype(src, width, height);
1555
1556 Returns an image of the same type (sample size, channels, paletted/direct).
1557
1558 For paletted images the palette is copied from the source.
1559
1560
1561 =for comment
1562 From: File image.c
1563
1564 =item i_sametype_chans(C<im>, C<xsize>, C<ysize>, C<channels>)
1565
1566
1567 i_img *img = i_sametype_chans(src, width, height, channels);
1568
1569 Returns an image of the same type (sample size).
1570
1571 For paletted images the equivalent direct type is returned.
1572
1573
1574 =for comment
1575 From: File image.c
1576
1577 =item im_img_16_new(ctx, x, y, ch)
1578 X<im_img_16_new API>X<i_img_16_new API>
1579
1580 i_img *img = im_img_16_new(aIMCTX, width, height, channels);
14731581 i_img *img = i_img_16_new(width, height, channels);
14741582
14751583 Create a new 16-bit/sample image.
14761584
14771585 Returns the image on success, or NULL on failure.
14781586
1587 Also callable as C<i_img_16_new(x, y, ch)>
1588
14791589
14801590 =for comment
14811591 From: File img16.c
14821592
1483 =item i_img_8_new(x, y, ch)
1484
1485
1486
1593 =item im_img_8_new(ctx, x, y, ch)
1594 X<im_img_8_new API>X<i_img_8_new API>
1595
1596 i_img *img = im_img_8_new(aIMCTX, width, height, channels);
14871597 i_img *img = i_img_8_new(width, height, channels);
14881598
14891599 Creates a new image object I<x> pixels wide, and I<y> pixels high with
14931603 =for comment
14941604 From: File img8.c
14951605
1496 =item i_img_double_new(i_img_dim x, i_img_dim y, int ch)
1497
1606 =item im_img_double_new(ctx, x, y, ch)
1607 X<im_img_double_new API>X<i_img_double_new API>
1608
1609 i_img *img = im_img_double_new(aIMCTX, width, height, channels);
14981610 i_img *img = i_img_double_new(width, height, channels);
14991611
15001612 Creates a new double per sample image.
15011613
1614 Also callable as C<i_img_double_new(width, height, channels)>.
1615
15021616
15031617 =for comment
15041618 From: File imgdouble.c
15051619
1506 =item i_img_pal_new(C<x>, C<y>, C<channels>, C<maxpal>)
1507
1508
1620 =item im_img_pal_new(ctx, C<x>, C<y>, C<channels>, C<maxpal>)
1621 X<im_img_pal_new API>X<i_img_pal_new API>
1622
1623 i_img *img = im_img_pal_new(aIMCTX, width, height, channels, max_palette_size)
15091624 i_img *img = i_img_pal_new(width, height, channels, max_palette_size)
15101625
15111626 Creates a new paletted image of the supplied dimensions.
15141629
15151630 Returns a new image or NULL on failure.
15161631
1632 Also callable as C<i_img_pal_new(width, height, channels, max_palette_size)>.
1633
15171634
15181635 =for comment
15191636 From: File palimg.c
15201637
1521 =item i_sametype(C<im>, C<xsize>, C<ysize>)
1522
1523
1524 i_img *img = i_sametype(src, width, height);
1525
1526 Returns an image of the same type (sample size, channels, paletted/direct).
1527
1528 For paletted images the palette is copied from the source.
1638 =item i_img_destroy(C<img>)
1639
1640 i_img_destroy(img)
1641
1642 Destroy an image object
15291643
15301644
15311645 =for comment
15321646 From: File image.c
15331647
1534 =item i_sametype_chans(C<im>, C<xsize>, C<ysize>, C<channels>)
1535
1536
1537 i_img *img = i_sametype_chans(src, width, height, channels);
1538
1539 Returns an image of the same type (sample size).
1540
1541 For paletted images the equivalent direct type is returned.
1542
1543
1544 =for comment
1545 From: File image.c
1546
1547 =item i_img_destroy(C<img>)
1548
1549 i_img_destroy(img)
1550
1551 Destroy an image object
1552
1553
1554 =for comment
1555 From: File image.c
1556
15571648
15581649 =back
15591650
15611652
15621653 =over
15631654
1564 =item i_img_alloc()
1655 =item im_img_alloc(aIMCTX)
1656 X<im_img_alloc API>X<i_img_alloc API>
1657
1658 i_img *im = im_img_alloc(aIMCTX);
1659 i_img *im = i_img_alloc();
15651660
15661661 Allocates a new i_img structure.
15671662
15901685 =for comment
15911686 From: File image.c
15921687
1593 =item i_img_init(C<img>)
1688 =item im_img_init(aIMCTX, image)
1689 X<im_img_init API>X<i_img_init API>
1690
1691 im_img_init(aIMCTX, im);
1692 i_img_init(im);
15941693
15951694 Imager internal initialization of images.
15961695
1597 Currently this does very little, in the future it may be used to
1598 support threads, or color profiles.
1696 See L</im_img_alloc(aIMCTX)> for more information.
15991697
16001698
16011699 =for comment
17821880 =for comment
17831881 From: File log.c
17841882
1785 =item mm_log((level, format, ...))
1786
1787 This is the main entry point to logging. Note that the extra set of
1788 parentheses are required due to limitations in C89 macros.
1789
1790 This will format a string with the current file and line number to the
1791 log file if logging is enabled.
1792
1793
1794 =for comment
1795 From: File log.h
1883
1884 =back
1885
1886 =head2 Mutex functions
1887
1888 =over
1889
1890 =item i_mutex_new()
1891
1892 i_mutex_t m = i_mutex_new();
1893
1894 Create a mutex.
1895
1896 If a critical section cannot be created for whatever reason, Imager
1897 will abort.
1898
1899
1900 =for comment
1901 From: File mutexwin.c
1902
1903 =item i_mutex_destroy(m)
1904
1905 i_mutex_destroy(m);
1906
1907 Destroy a mutex.
1908
1909
1910 =for comment
1911 From: File mutexwin.c
1912
1913 =item i_mutex_lock(m)
1914
1915 i_mutex_lock(m);
1916
1917 Lock the mutex, waiting if another thread has the mutex locked.
1918
1919
1920 =for comment
1921 From: File mutexwin.c
1922
1923 =item i_mutex_unlock(m)
1924
1925 i_mutex_unlock(m);
1926
1927 Release the mutex.
1928
1929 The behavior of releasing a mutex you don't hold is unspecified.
1930
1931
1932 =for comment
1933 From: File mutexwin.c
17961934
17971935
17981936 =back
21292267 =for comment
21302268 From: File io.c
21312269
2270 =item im_context_refdec(ctx, where)
2271 X<im_context_refdec API>
2272 =section Context objects
2273
2274 im_context_refdec(aIMCTX, "a description");
2275
2276 Remove a reference to the context, releasing it if all references have
2277 been removed.
2278
2279
2280 =for comment
2281 From: File context.c
2282
2283 =item im_context_refinc(ctx, where)
2284 X<im_context_refinc API>
2285 =section Context objects
2286
2287 im_context_refinc(aIMCTX, "a description");
2288
2289 Add a new reference to the context.
2290
2291
2292 =for comment
2293 From: File context.c
2294
2295 =item im_context_slot_get(ctx, slot)
2296
2297 Retrieve the value previously stored in the given slot of the context
2298 object.
2299
2300
2301 =for comment
2302 From: File context.c
2303
2304 =item im_context_slot_new(destructor)
2305
2306 Allocate a new context-local-storage slot.
2307
2308 C<desctructor> will be called when the context is destroyed if the
2309 corresponding slot is non-NULL.
2310
2311
2312 =for comment
2313 From: File context.c
2314
2315 =item im_context_slot_set(slot, value)
2316
2317 Set the value of a slot.
2318
2319 Returns true on success.
2320
2321 Aborts if the slot supplied is invalid.
2322
2323 If reallocation of slot storage fails, returns false.
2324
2325
2326 =for comment
2327 From: File context.c
2328
2329 =item im_errors(ctx)
2330
2331 i_errmsg *errors = im_errors(aIMCTX);
2332 i_errmsg *errors = i_errors();
2333
2334 Returns a pointer to the first element of an array of error messages,
2335 terminated by a NULL pointer. The highest level message is first.
2336
2337 Also callable as C<i_errors()>.
2338
2339
2340 =for comment
2341 From: File error.c
2342
2343 =item im_get_context()
2344
2345 Retrieve the context object for the current thread.
2346
2347 Inside Imager itself this is just a function pointer, which the
2348 F<Imager.xs> BOOT handler initializes for use within perl. If you're
2349 taking the Imager code and embedding it elsewhere you need to
2350 initialize the C<im_get_context> pointer at some point.
2351
2352
2353 =for comment
2354 From: File imext.c
2355
2356
2357
2358 =back
2359
2360
2361 =head1 UNDOCUMENTED
2362
2363 The following API functions are undocumented so far, hopefully this
2364 will change:
2365
2366 =over
2367
2368 =item *
2369
2370 B<im_lhead>
2371
2372 =item *
2373
2374 B<im_loog>
2375
2376 =item *
2377
2378 B<mm_log>
2379
21322380
21332381
21342382 =back
21402388
21412389 =head1 SEE ALSO
21422390
2143 Imager, Imager::ExtUtils, Imager::Inline
2391 Imager, Imager::API, Imager::ExtUtils, Imager::Inline
21442392
21452393 =cut
590590
591591 =item *
592592
593 x, y - either integers giving the co-ordinates of the pixel to set or
593 C<x>, C<y> - either integers giving the co-ordinates of the pixel to set or
594594 array references containing a set of pixels to be set.
595595
596596 =item *
597597
598 type - the type of color object to return, either C<'8bit'> for
599 Imager::Color objects or C<'float'> for Imager::Color::Float objects.
600 Default: C<'8bit'>.
598 C<type> - the type of color object to return, either C<'8bit'> for
599 L<Imager::Color> objects or C<'float'> for L<Imager::Color::Float>
600 objects. Default: C<'8bit'>.
601601
602602 =back
603603
607607
608608 If a supplied co-ordinate is outside the image then C<undef> is
609609 returned for the pixel.
610
611 Each color is returned as an L<Imager::Color> object or as an
612 L<Imager::Color::Float> object if C<type> is set to C<"float">.
610613
611614 Possible errors conditions include:
612615
13771377
13781378 =back
13791379
1380 Each of these tags has a corresponding C< I<base-tag-name>_compressed
1380 Each of these tags has a corresponding C<< I<base-tag-name>_compressed
13811381 >> tag, eg. C<png_comment_compressed>. When reading, if the PNG chunk
13821382 is compressed this tag will be set to 1, but is otherwise unset. When
13831383 writing, Imager will honor the compression tag if set and non-zero,
14351435
14361436 =item *
14371437
1438 C<tags, png_gamma>C<png_gamma> - the gamma of the image. This value is
1438 X<tags, png_gamma>C<png_gamma> - the gamma of the image. This value is
14391439 not currently used by Imager when processing the image, but this may
14401440 change in the future.
14411441
14601460
14611461 =item *
14621462
1463 X<tags, png_time>X<png_time> - the creation time of the file formatted
1463 X<tags, png_time>C<png_time> - the creation time of the file formatted
14641464 as C<< I<year>-I<month>-I<day>TI<hour>:I<minute>:I<second> >>. This
14651465 is stored as time data structure in the file, not a string. If you
14661466 set C<png_time> and it cannot be parsed as above, writing the PNG file
222222
223223 fountain (similar to gradients in paint software)
224224
225 =item *
226
227 image - fill with an image, possibly transformed
228
229 =item *
230
231 opacity - a lower opacity version of some other fill
232
225233 =back
226234
227235 =head1 Common options
235243
236244 =back
237245
238 In general colors can be specified as Imager::Color or
239 Imager::Color::Float objects. The fill object will typically store
246 In general colors can be specified as L<Imager::Color> or
247 L<Imager::Color::Float> objects. The fill object will typically store
240248 both types and convert from one to the other. If a fill takes 2 color
241249 objects they should have the same type.
242250
243251 =head2 Solid fills
244252
245 my $fill = Imager::Fill->new(solid=>$color, $combine =>$combine)
253 my $fill = Imager::Fill->new(solid=>$color, combine =>$combine)
246254
247255 Creates a solid fill, the only required parameter is C<solid> which
248256 should be the color to fill with.
249257
258 A translucent red fill:
259
260 my $red = Imager::Fill->new(solid => "FF000080", combine => "normal");
261
250262 =head2 Hatched fills
251263
252264 my $fill = Imager::Fill->new(hatch=>$type, fg=>$fgcolor, bg=>$bgcolor,
256268
257269 =over
258270
259 =item hatch
260
261 The type of hatch to perform, this can either be the numeric index of
262 the hatch (not recommended), the symbolic name of the hatch, or an
263 array of 8 integers which specify the pattern of the hatch.
271 =item *
272
273 C<hatch> - The type of hatch to perform, this can either be the
274 numeric index of the hatch (not recommended), the symbolic name of the
275 hatch, or an array of 8 integers which specify the pattern of the
276 hatch.
264277
265278 Hatches are represented as cells 8x8 arrays of bits, which limits their
266279 complexity.
340353
341354 =back
342355
356 A blue and white 4-pixel check patten:
357
358 my $fill = Imager::Fill->new(hatch => "check2x2", fg => "blue");
359
343360 You can call Imager::Fill->hatches for a list of hatch names.
344361
345362 =head2 Fountain fills
354371 you are drawing, and the fountain parameter supplies the fill type,
355372 and is required.
356373
374 A radial fill from white to transparent centered on (50, 50) with a 50
375 pixel radius:
376
377 use Imager::Fountain;
378 my $segs = Imager::Fountain->simple(colors => [ "FFFFFF", "FFFFFF00" ],
379 positions => [ 0, 1 ]);
380 my $fill = Imager::Fill->new(fountain => "radial", segments => $segs,
381 xa => 50, ya => 50, xb => 0, yb => 50,
382 combine => "normal");
383
384
357385 =head2 Image Fills
358386
359387 my $fill = Imager::Fill->new(image=>$src, xoff=>$xoff, yoff=>$yoff,
360 matrix=>$matrix, $combine);
388 matrix=>$matrix, combine => $combine);
361389
362390 Fills the given image with a tiled version of the given image. The
363391 first non-zero value of C<xoff> or C<yoff> will provide an offset
370398
371399 The matrix parameter will significantly slow down the fill.
372400
401 # some image to act as a texture
402 my $txim = Imager->new(...);
403
404 # simple tiling
405 my $fill = Imager::Fill->new(image => $txim);
406
407 # tile with a vertical offset
408 my $fill = Imager::Fill->new(image => $txim, yoff => 10);
409
410 # tile with a horizontal offset
411 my $fill = Imager::Fill->new(image => $txim, xoff => 10);
412
413 # rotated
414 use Imager::Matrix2d;
415 my $fill = Imager::Fill->new(image => $txim,
416 matrix => Imager::Matrix2d->rotate(degrees => 20));
417
373418 =head2 Opacity modification fill
374419
375420 my $fill = Imager::Fill->new(type => "opacity",
400445
401446 The source fills combine mode is used.
402447
448 my $hatch = Imager::Fill->new(hatch => "check4x4", combine => "normal");
449 my $fill = Imager::Fill->new(type => "opacity", other => $hatch);
450
403451 =head1 OTHER METHODS
404452
405453 =over
0 package Imager::Font::Test;
1 use strict;
2
3 use base 'Imager::Font';
4
5 sub new {
6 my ($class, %opts) = @_;
7
8 bless \%opts, shift;
9 }
10
11 sub _draw {
12 my ($self, %input) = @_;
13
14 my $text = $input{string};
15
16 my $ppn = int($input{size} * 0.5 + 0.5);
17 my $desc = int($input{size} * 0.3 + 0.5);
18 my $asc = $input{size} - $desc;
19 my $width = $ppn * length $text;
20 my $x = $input{x};
21 my $y = $input{'y'};
22 $input{align} and $y -= $asc;
23
24 $input{image}->box(color => $input{color}, xmin => $x, ymin => $y,
25 xmax => $x + $width-1, ymax => $y + $input{size} - 1);
26
27 return 1;
28 }
29
30 sub _bounding_box {
31 my ($self, %input) = @_;
32
33 my $text = $input{string};
34
35 my $ppn = int($input{size} * 0.5 + 0.5);
36 my $desc = int($input{size} * 0.3 + 0.5);
37 my $asc = $input{size} - $desc;
38
39 return ( 0, -$desc, $ppn * length $text, $asc, -$desc, $asc, $ppn * length $text, 0 );
40 }
41
42 sub has_chars {
43 my ($self, %input) = @_;
44
45 my $text = $input{string};
46 defined $text
47 or return Imager->_set_error("has_chars: No string parameter supplied");
48
49 return (1) x length $text;
50 }
51
52 sub face_name {
53 "test";
54 }
55
56 sub glyph_names {
57 my ($self, %input) = @_;
58
59 my $text = $input{string};
60 defined $text
61 or return Imager->_set_error("glyph_names: No string parameter supplied");
62
63 return (1) x length $text;
64 }
65
66 1;
67
68 =head1 NAME'
69
70 Imager::Font::Test - font driver producing consistent output for tests.
71
72 =head1 SYNOPSIS
73
74 my $font = Imager::Font::Test->new;
75
76 # use $font where you use other fonts
77
78 =head1 DESCRIPTION
79
80 Imager::Font::Test is intended to produce consistent output without
81 being subject to the inconsistent output produced by different
82 versions of font libraries.
83
84 The output is simple box for the whole string.
85
86 =head1 AUTHOR
87
88 Tony Cook <tonyc@cpan.org>
89
90 =cut
91
22 use vars qw(@ISA $VERSION);
33 @ISA = qw(Imager::Font);
44
5 $VERSION = "1.011";
5 $VERSION = "1.012";
66
77 *_first = \&Imager::Font::_first;
88
4343 my $self = shift;
4444 my %input = @_;
4545
46 # note that the string length parameter is ignored and calculated in
47 # XS with SvPV(), since we want the number of bytes rather than the
48 # number of characters, which is what we'd get in perl for a UTF8
49 # encoded string in 5.6 and later
50
5146 if ( exists $input{channel} ) {
5247 Imager::i_tt_cp($self->{id},$input{image}{IMG},
5348 $input{'x'}, $input{'y'}, $input{channel}, $input{size},
54 $input{string}, length($input{string}),$input{aa},
49 $input{string}, $input{aa},
5550 $input{utf8}, $input{align});
5651 } else {
5752 Imager::i_tt_text($self->{id}, $input{image}{IMG},
5853 $input{'x'}, $input{'y'}, $input{color},
5954 $input{size}, $input{string},
60 length($input{string}), $input{aa}, $input{utf8},
55 $input{aa}, $input{utf8},
6156 $input{align});
6257 }
6358 }
6560 sub _bounding_box {
6661 my $self = shift;
6762 my %input = @_;
68 return Imager::i_tt_bbox($self->{id}, $input{size},
69 $input{string}, length($input{string}),
70 $input{utf8});
63 my @result =
64 Imager::i_tt_bbox($self->{id}, $input{size}, $input{string}, $input{utf8});
65 unless (@result) {
66 Imager->_set_error(Imager->_error_as_msg);
67 return;
68 }
69
70 return @result;
7171 }
7272
7373 sub utf8 { 1 }
7676 sub has_chars {
7777 my ($self, %hsh) = @_;
7878
79 unless (defined $hsh{string} && length $hsh{string}) {
79 unless (defined $hsh{string}) {
8080 $Imager::ERRSTR = "No string supplied to \$font->has_chars()";
8181 return;
8282 }
83 return Imager::i_tt_has_chars($self->{id}, $hsh{string},
84 _first($hsh{'utf8'}, $self->{utf8}, 0));
83 if (wantarray) {
84 my @result = Imager::i_tt_has_chars($self->{id}, $hsh{string},
85 _first($hsh{'utf8'}, $self->{utf8}, 0));
86 unless (@result) {
87 Imager->_set_error(Imager->_error_as_msg);
88 return;
89 }
90 return @result;
91 }
92 else {
93 my $result = Imager::i_tt_has_chars($self->{id}, $hsh{string},
94 _first($hsh{'utf8'}, $self->{utf8}, 0));
95 unless (defined $result) {
96 Imager->_set_error(Imager->_error_as_msg);
97 return;
98 }
99
100 return $result;
101 }
85102 }
86103
87104 sub face_name {
88105 my ($self) = @_;
89106
90107 Imager::i_tt_face_name($self->{id});
108 }
109
110 sub can_glyph_names {
111 1;
91112 }
92113
93114 sub glyph_names {
98119 or return Imager->_set_error("no string parameter passed to glyph_names");
99120 my $utf8 = _first($input{utf8} || 0);
100121
101 Imager::i_tt_glyph_name($self->{id}, $string, $utf8);
122 my @names = Imager::i_tt_glyph_name($self->{id}, $string, $utf8);
123 unless (@names) {
124 Imager->_set_error(Imager->_error_as_msg);
125 return;
126 }
127
128 return @names;
102129 }
103130
104131 1;
33 use strict;
44 use vars qw($VERSION);
55
6 $VERSION = "1.035";
6 $VERSION = "1.037";
77
88 # the aim here is that we can:
99 # - add file based types in one place: here
248248 $input{sizew} = _first($input{sizew}, $self->{sizew}, 0);
249249 $input{utf8} = _first($input{utf8}, $self->{utf8}, 0);
250250
251 my @box = $self->_bounding_box(%input);
251 my @box = $self->_bounding_box(%input)
252 or return;
252253
253254 if (wantarray) {
254255 if(@box && exists $input{'x'} and exists $input{'y'}) {
543544
544545 =back
545546
547 Returns the new font object on success. Returns C<undef> on failure
548 and sets an error message readable with C<< Imager->errstr >>.
549
546550 =item bounding_box()
547551
548552 Returns the bounding box for the specified string. Example:
665669
666670 =back
667671
672 On success returns either the list of bounds, or a bounding box object
673 object in scalar context. Returns an empty list or C<undef> on
674 failure and sets an error message readable with C<< Imager->errstr >>.
675
676 The transformation matrix set by L</transform()> has no effect on the
677 result of this method - the bounds of the untransformed text is
678 returned.
679
668680 =item string()
669681
670682 The $img->string(...) method is now documented in
746758
747759 =back
748760
749 Returns a list specifying the bounds of the drawn text.
761 Returns a list specifying the bounds of the drawn text on success.
762 Returns an empty list on failure, if an C<image> parameter was
763 supplied the error message can be read with C<< $image->errstr >>,
764 otherwise it's available as C<< Imager->errstr >>.
750765
751766 =item dpi()
752767
774789
775790 =back
776791
777 Returns a list containing the previous C<xdpi>, C<ydpi> values.
792 Returns a list containing the previous C<xdpi>, C<ydpi> values on
793 success. Returns an empty list on failure, with an error message
794 returned in C<< Imager->errstr >>.
778795
779796 =item transform()
780797
800817 Note that the transformation is done in font co-ordinates where y
801818 increases as you move up, not image co-ordinates where y decreases as
802819 you move up.
820
821 C<transform()> has no effect on the results of L</bounding_box()>.
822
823 Returns true on success. Returns false on failure with the cause
824 readable from C<< Imager->errstr >>.
803825
804826 =item has_chars(string=>$text)
805827
812834
813835 Not all fonts support this method (use $font->can("has_chars") to
814836 check.)
837
838 On error, returns an empty list or undef in scalar context, and sets
839 an error message readable with C<< Imager->errstr >>.
815840
816841 =over
817842
833858 =item face_name()
834859
835860 Returns the internal name of the face. Not all font types support
836 this method yet.
861 this method yet, so you should check with C<< $font->can("face_name")
862 >> before calling C<face_name>.
837863
838864 =item glyph_names(string=>$string [, utf8=>$utf8 ][, reliable_only=>0 ] );
839865
855881 Both FreeType 1.x and 2.x allow support for glyph names to not be
856882 included.
857883
884 If the supplied C<string> is marked as UTF-8 or the C<utf8> parameter
885 is true and the supplied string does not contain valid UTF-8, returns
886 an empty string and set an error message readable from C<<
887 Imager->errstr >>,
888
889 =item can_glyph_names()
890
891 As a class method, returns true if the underlying library supports
892 returning glyph names.
893
894 As an object method, returns true if the supplied font supports
895 returning glyph names.
896
858897 =item draw
859898
860899 This is used by Imager's string() method to implement drawing text.
9661005 # at this point $x is has the UTF-8 flag set, but has 5 characters,
9671006 # none, of which is the constructed UTF-8 character
9681007
969 The test script t/t38ft2font.t has a small example of this after the
1008 The test script t/t38ft2font.t has a small example of this after the
9701009 comment:
9711010
9721011 # an attempt using emulation of UTF-8
4949 L<Imager::Files/"I/O Callbacks"> for details on the behavior of
5050 the callbacks.
5151
52 =item new_fh($fh)
53
54 Create a new I/O layer based on a perl file handle.
55
5256 =item new_bufchain()
5357
5458 Create a new C<bufchain> based I/O layer. This accumulates the file
0 =for stopwords freetype MinGW dfont Redhat SDK IFD GDI TTF preprocessor Redhat-like
1
2 =head1 NAME
3
4 Imager::Install - installation notes for Imager
5
6 =head1 SYNOPSIS
7
8 perl Makefile.PL
9 make
10 make test
11 make install
12
13 =head1 CONFIGURATION
14
15 Assuming you have all of your required libraries in the places Imager
16 looks, you should be able to use the standard mantra:
17
18 perl Makefile.PL
19 make
20 make test
21 make install
22
23 to install Imager.
24
25 If you've installed libraries in places Imager doesn't look, you can
26 supply extra locations either with command-line options:
27
28 perl Makefile.PL --libpath=/home/tony/local/lib --incpath=/home/tony/local/include
29
30 or with environment variables:
31
32 export IM_LIBPATH=/home/tony/local/lib IM_INCPATH=/home/tony/local/include
33 perl Makefile.PL
34
35 Imager's F<Makefile.PL> produces an epilogue indicating which
36 libraries have and haven't been found, for example:
37
38 Libraries found:
39 FT2
40 GIF
41 JPEG
42 PNG
43 T1
44 TIFF
45 Libraries *not* found:
46 Win32
47
48 If a library you expect to be found isn't on this list, use the
49 C<--verbose> or C<-v> option to produce way too much information from
50 Imager's search for the libraries:
51
52 perl Makefile.PL -v
53
54 If you can't resolve this, then run
55
56 perl errep.perl
57
58 and include the (large) generated F<report.txt> in your email to:
59
60 bug-Imager@rt.cpan.org
61
62 There are other options used to configure how Imager is built:
63
64 =over
65
66 =item C<--nolog>
67
68 build Imager without logging support. This will speed up Imager a
69 little. You can also remove logging by setting the C<IMAGER_NOLOG>
70 environment variable to a true value.
71
72 =item C<--coverage>
73
74 used to build Imager for C<gcov> coverage testing. This is intended
75 for development and also requires options supplied to C<make>.
76
77 =item C<--assert>
78
79 build Imager with assertions enabled.
80
81 =item C<--tracecontext>
82
83 build Imager to trace context object management to C<stderr> for
84 debugging.
85
86 =back
87
88 =head2 Build time environment variables
89 X<build time environment variables>
90
91 =over
92
93 =item *
94
95 X<< C<IMAGER_NOLOG> >>C<IMAGER_NOLOG> - build Imager with logging disabled.
96
97 =item *
98
99 X<< C<IMAGER_DEBUG_MALLOC> >>C<IMAGER_DEBUG_MALLOC> - build Imager with it's
100 debug malloc wrappers. This is I<not> compatible with threaded code.
101
102 =item *
103
104 X<< C<IM_INCPATH> >>C<IM_INCPATH> - equivalent to C<--incpath>.
105
106 =item *
107
108 X<< C<IM_LIBPATH> >>C<IM_LIBPATH> - equivalent to C<--libpath>.
109
110 =item *
111
112 X<< C<IM_VERBOSE> >>C<IM_VERBOSE> - equivalent to C<--verbose>
113
114 =item *
115
116 X<< C<IM_CFLAGS> >>C<IM_CFLAGS> - extra C compiler flags.
117
118 =item *
119
120 X<< C<IM_LFLAGS> >>C<IM_LFLAGS> - extra linker flags.
121
122 =item *
123
124 X<< C<IM_DFLAGS> >>C<IM_DFLAGS> - extra preprocessor flags.
125
126 =back
127
128 =head1 EXTERNAL LIBRARIES
129
130 Some of the file format and font modules included with Imager use
131 external libraries, which should be installed before you try to
132 install Imager itself.
133
134 If you don't have the libraries installed then Imager itself will
135 install successfully, but the file format or font support module won't
136 be.
137
138 Preferably the latest version of each library should be used, simple
139 because it has the latest security fixes.
140
141 =head2 PNG - C<libpng>
142
143 X<< C<libpng> >>L<Imager::File::PNG> uses L<< C<libpng>
144 |http://www.libpng.org/pub/png/libpng.html >> for PNG image file
145 support.
146
147 Debian package: C<libpng12-dev>
148
149 Redhat package: C<libpng-devel>
150
151 =head2 TIFF - C<libtiff>
152
153 X<< C<libtiff> >>L<Imager::File::TIFF> uses
154 L<< C<libtiff> |http://www.remotesensing.org/libtiff/ >> for GIF image file
155 support.
156
157 Version 3.6.0 or later is required to avoid an exploit with infinite
158 IFD loops, though it's possible some distributions have applied the
159 fix to older versions as a security fix.
160
161 Version 3.9.0 is rejected during the probe process due to a serious
162 bug, fixed in 3.9.1.
163
164 Debian package: C<libtiff4-dev>
165
166 Redhat package: C<libtiff-devel>
167
168 =head2 GIF - C<libgif>
169
170 X<< C<libgif> >>L<Imager::File::GIF> uses
171 L<< C<libgif> |http://sourceforge.net/projects/giflib/ >> for GIF image file
172 support.
173
174 C<libgif> releases 4.2.0 and 5.0.0 are specifically not supported, due
175 to bugs in those versions.
176
177 Release 4.1.4 or later should be used.
178
179 C<giflib> 3 is no longer supported.
180
181 C<libungif> is no longer supported as an alternative.
182
183 Debian package: C<libgif-dev>
184
185 Redhat package: C<giflib-devel>
186
187 =head2 JPEG - C<libjpeg>
188
189 L<Imager::File::JPEG> uses L<< C<libjpeg> |http://www.ijg.org/ >> for JPEG
190 image file support.
191
192 You may also use
193 L<< C<libjpeg-turbo> |http://sourceforge.net/projects/libjpeg-turbo/ >>.
194
195 To install older releases of C<libjpeg> from source, you'll need to
196 run:
197
198 make install-lib
199
200 to install the libraries. C<make install> only installs the program
201 binaries.
202
203 Redhat package: C<libjpeg-devel>
204
205 Debian package: C<libjpeg8-dev>
206
207 =head2 Freetype 2.x - C<libfreetype>
208
209 L<Imager::Font::FT2> uses L<< Freetype 2
210 (C<libfreetype>)|http://www.freetype.org/ >> for font support, supporting
211 too many font formats to mention here.
212
213 This is the recommended library to use for font support.
214
215 Debian package: C<libfreetype6-dev>
216
217 Redhat package: C<freetype-devel>
218
219 =head2 Win32 GDI fonts
220
221 L<Imager::Font::W32> uses L<Win32
222 GDI|http://msdn.microsoft.com/en-us/library/dd145203%28v=vs.85%29.aspx>
223 to render text using installed Windows fonts.
224
225 This requires Win32 SDK headers and libraries, and is only expected to
226 work on native Win32 or Cygwin.
227
228 For this to work under Cygwin, install the C<w32api-headers> and
229 C<w32api-runtime> packages.
230
231 =head2 C<t1lib>
232
233 L<Imager::Font::T1> uses L<< C<t1lib> |http://www.t1lib.org/ >> for
234 font support, supporting Postscript Type 1 fonts only.
235
236 Debian package: C<libt1-dev>
237
238 Redhat package: C<t1lib-devel>
239
240 =head2 Freetype 1.x - C<libttf>
241
242 Imager uses L<< Freetype 1 (C<libttf>)|http://www.freetype.org/ >> if
243 available for font support, supporting TTF fonts only.
244
245 Freetype 1.x is essentially unsupported and shouldn't be used for new
246 code.
247
248 =head1 PLATFORM SPECIFICS
249
250 =head2 Linux
251
252 Several distributions include an Imager package, but they are
253 typically several releases behind due to the nature of release cycles.
254
255 Imager typically supports the external libraries as packaged with any
256 supported release of Linux.
257
258 =head3 Debian
259
260 To install the libraries used by Imager under Debian (or Ubuntu), run
261 as root (or with sudo):
262
263 apt-get install libgif-dev libjpeg8-dev libtiff4-dev libpng12-dev libfreetype6-dev
264
265 You may also need to install development tools:
266
267 apt-get install build-essential
268
269 =head3 Redhat
270
271 To install the libraries used by Imager under Redhat and related Linux
272 distributions, run as root (or sudo):
273
274 yum install giflib-devel libjpeg-devel libtiff-devel libpng-devel freetype-devel
275
276 To install the development tools needed:
277
278 yum install gcc
279
280 (which appears to be enough on a base Redhat-like install) or the more
281 commonly recommended recipe:
282
283 yum groupinstall "Development Tools"
284
285 which is massive overkill.
286
287 =head2 Mac OS X
288
289 =head3 Building libraries
290
291 The default perl build in Snow Leopard and Lion is a fat binary, and
292 default builds of C<giflib>, C<libpng> and C<libjpeg> (and maybe other
293 libraries) will produce link failures.
294
295 To avoid this you need to supply a C<CFLAGS> parameter to the
296 library's configure script, but since the C<-arch> flag conflicts with
297 the options used to build the dependency files, you need to supply
298 another flag to disable dependency tracking.
299
300 Snow Leopard fat binaries include C<i386>, C<x86_64> and C<PPC>
301 objects, hence you would run configure like:
302
303 ./configure --disable-dependency-tracking CFLAGS='-arch x86_64 -arch i386 -arch ppc'
304
305 Lion doesn't support C<PPC>, so there you run configure like:
306
307 ./configure --disable-dependency-tracking CFLAGS='-arch x86_64 -arch i386'
308
309 For C<libgif> you might also want to supply the C<--without-x> option:
310
311 ./configure --disable-dependency-tracking --without-x CFLAGS='-arch x86_64 -arch i386'
312
313 If you copy library files into place manually, you may need to run
314 C<ranlib> on them in their new location:
315
316 ranlib /usr/local/lib/libgif.a
317
318 =head3 Macintosh C<dfont> and suitcase font support
319
320 Through Freetype 2.1, Imager can use Macintosh C<DFON> (C<.dfont>)
321 fonts and suitcase font files.
322
323 If you want to be able to use more than just the first face in the
324 font file though, you will need to configure C<freetype2> with the
325 --with-old-mac-fonts option:
326
327 ./configure --with-old-mac-fonts
328
329 You can use the index option to get to the other font faces in the
330 file:
331
332 # get the second face from $file
333 my $font = Imager::Font->new(file=>$file, index=>1)
334 or die Imager->errstr;
335
336 If you're using a suitcase font, you will also need to force the use
337 of Freetype 2 with the type argument:
338
339 my $font = Imager::Font->new(file=>$suitcase, type=>'ft2', index=>$index)
340 or die Imager->errstr;
341
342 =head2 Microsoft Windows
343
344 The simplest way to install the libraries used by Imager is to install
345 L<Strawberry perl|http://strawberryperl.com/>.
346
347 You can then use either the bundled Imager, or install from CPAN.
348
349 If you get errors from your make tool, make sure you're using the same
350 make that was used to build your perl - C<nmake> for Visual C/C++ and
351 C<dmake> for MinGW, run:
352
353 perl -V:make
354
355 to see which make was used to build your perl.
356
357 =head2 Cygwin
358
359 To build Imager with as much library support as possible on Cygwin,
360 install the following packages:
361
362 libjpeg-devel libpng-devel libgif-devel libtiff-devel
363 libfreetype-devel t1lib-devel w32api-headers w32api-runtime
364
365 If you see an error under cygwin during testing along the lines of:
366
367 C:\cygwin\bin\perl.exe: *** unable to remap C:\cygwin\...some dll to the
368 same address as parent (0x...) != 0x....
369
370 you will need to install the cygwin C<rebase> package and run:
371
372 $ rebaseall -v
373
374 or possibly, just:
375
376 $ perlrebase
377
378 will fix the problem.
379
380 =head1 Other issues
381
382 =head2 Freetype 1.x vs Freetype 2.x
383
384 Freetype 1.x is no longer recommended, is no longer supported
385 upstream, and receives only limited updates in Imager.
386
387 These two libraries have some conflicting include file names, but as
388 long as you don't put the Freetype 2.x F<freetype.h> directory in the
389 include path it should all work.
390
391 Put the directory containing F<ft2build.h> in the include path, but
392 not the directory containing the freetype 2.x F<freetype.h>.
393
394 If you see compilation errors from font.c you've probably made the
395 mistake of putting the Freetype 2.x F<freetype.h> directory into the
396 include path.
397
398 To see which directories should be in the include path, try:
399
400 freetype-config --cflags
401
402 Ideally, C<freetype-config> should be in the PATH when building Imager
403 with freetype 2.x support, in which case L<Imager::Font::FT2> can
404 configure itself.
405
406 =cut
7676 JPEG 8, 12 8
7777 PBM 1 1
7878 PGM/PPM 1-16 read any, writes 8, 16
79 PNG 1, 2, 4, 8, 16 8
79 PNG 1, 2, 4, 8, 16 1, 2, 4, 8 paletted
80 1, 8, 16 gray (1 for is_monochrome() images)
81 8, 16 RGB
8082 RAW 8
8183 SGI 8, 16 8, 16
8284 TGA 8 8
00 package Imager::Test;
11 use strict;
2 use Test::More;
23 use Test::Builder;
34 require Exporter;
45 use vars qw(@ISA @EXPORT_OK $VERSION);
5 use Carp qw(croak);
6
7 $VERSION = "1.000";
6 use Carp qw(croak carp);
7 use Config;
8
9 $VERSION = "1.002";
810
911 @ISA = qw(Exporter);
1012 @EXPORT_OK =
3436 mask_tests
3537 test_colorf_gpix
3638 test_color_gpix
37 test_colorf_glin);
39 test_colorf_glin
40 can_test_threads
41 std_font_tests
42 std_font_test_count
43 );
3844
3945 sub diff_text_with_nul {
4046 my ($desc, $text1, $text2, @params) = @_;
727733
728734 }
729735
736 sub std_font_test_count {
737 return 21;
738 }
739
740 sub std_font_tests {
741 my ($opts) = @_;
742
743 my $font = $opts->{font}
744 or carp "Missing font parameter";
745
746 my $name_font = $opts->{glyph_name_font} || $font;
747
748 my $has_chars = $opts->{has_chars} || [ 1, '', 1 ];
749
750 my $glyph_names = $opts->{glyph_names} || [ "A", undef, "A" ];
751
752 SKIP:
753 { # check magic is handled correctly
754 # https://rt.cpan.org/Ticket/Display.html?id=83438
755 skip("no native UTF8 support in this version of perl", 11)
756 unless $] >= 5.006;
757 skip("overloading handling of magic is broken in this version of perl", 11)
758 unless $] >= 5.008;
759 Imager->log("utf8 magic tests\n");
760 my $over = bless {}, "Imager::Test::OverUtf8";
761 my $text = "A".chr(0x2010)."A";
762 my $white = Imager::Color->new("#FFF");
763 my $base_draw = Imager->new(xsize => 80, ysize => 20);
764 ok($base_draw->string(font => $font,
765 text => $text,
766 x => 2,
767 y => 18,
768 size => 15,
769 color => $white,
770 aa => 1),
771 "magic: make a base image");
772 my $test_draw = Imager->new(xsize => 80, ysize => 20);
773 ok($test_draw->string(font => $font,
774 text => $over,
775 x => 2,
776 y => 18,
777 size => 15,
778 color => $white,
779 aa => 1),
780 "magic: draw with overload");
781 is_image($base_draw, $test_draw, "check they match");
782 if ($opts->{files}) {
783 $test_draw->write(file => "testout/utf8tdr.ppm");
784 $base_draw->write(file => "testout/utf8bdr.ppm");
785 }
786
787 my $base_cp = Imager->new(xsize => 80, ysize => 20);
788 $base_cp->box(filled => 1, color => "#808080");
789 my $test_cp = $base_cp->copy;
790 ok($base_cp->string(font => $font,
791 text => $text,
792 y => 2,
793 y => 18,
794 size => 16,
795 channel => 2,
796 aa => 1),
797 "magic: make a base image (channel)");
798 Imager->log("magic: draw to channel with overload\n");
799 ok($test_cp->string(font => $font,
800 text => $over,
801 y => 2,
802 y => 18,
803 size => 16,
804 channel => 2,
805 aa => 1),
806 "magic: draw with overload (channel)");
807 is_image($test_cp, $base_cp, "check they match");
808 if ($opts->{files}) {
809 $test_cp->write(file => "testout/utf8tcp.ppm");
810 $base_cp->write(file => "testout/utf8bcp.ppm");
811 }
812
813 SKIP:
814 {
815 Imager->log("magic: has_chars\n");
816 $font->can("has_chars")
817 or skip "No has_chars aupport", 2;
818 is_deeply([ $font->has_chars(string => $text) ], $has_chars,
819 "magic: has_chars with normal utf8 text");
820 is_deeply([ $font->has_chars(string => $over) ], $has_chars,
821 "magic: has_chars with magic utf8 text");
822 }
823
824 Imager->log("magic: bounding_box\n");
825 my @base_bb = $font->bounding_box(string => $text, size => 30);
826 is_deeply([ $font->bounding_box(string => $over, size => 30) ],
827 \@base_bb,
828 "check bounding box magic");
829
830 SKIP:
831 {
832 $font->can_glyph_names
833 or skip "No glyph_names", 2;
834 Imager->log("magic: glyph_names\n");
835 my @text_names = $name_font->glyph_names(string => $text, reliable_only => 0);
836 is_deeply(\@text_names, $glyph_names,
837 "magic: glyph_names with normal utf8 text");
838 my @over_names = $name_font->glyph_names(string => $over, reliable_only => 0);
839 is_deeply(\@over_names, $glyph_names,
840 "magic: glyph_names with magic utf8 text");
841 }
842 }
843
844 { # invalid UTF8 handling at the OO level
845 my $im = Imager->new(xsize => 80, ysize => 20);
846 my $bad_utf8 = pack("C", 0xC0);
847 Imager->_set_error("");
848 ok(!$im->string(font => $font, size => 1, text => $bad_utf8, utf8 => 1,
849 y => 18, x => 2),
850 "drawing invalid utf8 should fail");
851 is($im->errstr, "invalid UTF8 character", "check error message");
852 Imager->_set_error("");
853 ok(!$im->string(font => $font, size => 1, text => $bad_utf8, utf8 => 1,
854 y => 18, x => 2, channel => 1),
855 "drawing invalid utf8 should fail (channel)");
856 is($im->errstr, "invalid UTF8 character", "check error message");
857 Imager->_set_error("");
858 ok(!$font->bounding_box(string => $bad_utf8, size => 30, utf8 => 1),
859 "bounding_box() bad utf8 should fail");
860 is(Imager->errstr, "invalid UTF8 character", "check error message");
861 SKIP:
862 {
863 $font->can_glyph_names
864 or skip "No glyph_names support", 2;
865 Imager->_set_error("");
866 is_deeply([ $font->glyph_names(string => $bad_utf8, utf8 => 1) ],
867 [ ],
868 "glyph_names returns empty list for bad string");
869 is(Imager->errstr, "invalid UTF8 character", "check error message");
870 }
871 SKIP:
872 {
873 $font->can("has_chars")
874 or skip "No has_chars support", 2;
875 Imager->_set_error("");
876 is_deeply([ $font->has_chars(string => $bad_utf8, utf8 => 1) ],
877 [ ],
878 "has_chars returns empty list for bad string");
879 is(Imager->errstr, "invalid UTF8 character", "check error message");
880 }
881 }
882 }
883
884 package Imager::Test::OverUtf8;
885 use overload '""' => sub { "A".chr(0x2010)."A" };
886
887
730888 1;
731889
732890 __END__
8731031
8741032 This was explicitly created for regression tests on #21770.
8751033
1034 =item std_font_tests({ font => $font })
1035
1036 Perform standard font interface tests.
1037
1038 =item std_font_test_count()
1039
1040 The number of tests performed by std_font_tests().
1041
8761042 =back
8771043
8781044 =head2 Helper functions
0 =head1 NAME
1
2 Imager::Threads - Imager and threads
3
4 =head1 SYNOPSIS
5
6 use Imager;
7 use threads;
8 Imager->preload;
9
10 threads->create(...);
11
12 =head1 DESCRIPTION
13
14 Starting from version 0.94 Imager attempts to work safely with perl's
15 C<ithreads>.
16
17 Previous versions stored some state in global variables, in particular
18 the internal error stack.
19
20 However there are some limitations:
21
22 =over
23
24 =item *
25
26 Imager's debug malloc isn't thread safe and will never be. Imager's
27 debug malloc is disabled by default.
28
29 =item *
30
31 C<libtiff>, which Imager uses for TIFF file support is not thread
32 safe, C<Imager::File::TIFF> works around this by single-threading its
33 access to C<libtiff>.
34
35 =item *
36
37 C<giflib>, which Imager uses for GIF support is not thread safe before
38 version 5. C<Imager::File::GIF> works around this by single threading
39 its access to C<giflib>.
40
41 =item *
42
43 C<T1Lib>, used by one of Imager's font drivers, is not thread safe.
44 C<Imager::Font::T1> works around this by single threading access.
45
46 =item *
47
48 killing a thread reading or writing TIFF or GIF files, or using T1
49 fonts through C<Imager::Font::T1> may deadlock other threads when they
50 attempt to read or write TIFF or GIF files, or work with Type 1 fonts.
51
52 =item *
53
54 Fill, font, color or I/O layer objects created in one thread are not
55 valid for use in child threads. If you manage to duplicate such an
56 object in another thread, you get to keep both pieces when it breaks.
57
58 =back
59
60 Note that if you have another module using C<libtiff>, C<giflib> or
61 C<t1lib> it may interact with Imager's use of those libraries in a
62 threaded environment, since there's no way to co-ordinate access to
63 the global information C<libtiff>, C<giflib> and C<t1lib> maintain.
64
65 Imager currently doesn't use threads itself, except for testing its
66 threads support.
67
68 =head1 SEE ALSO
69
70 Imager, C<threads>
71
72 =head1 AUTHOR
73
74 Tony Cook <tony@cpan.org>
75
76 =cut
2323
2424 */
2525
26 #define IMAGER_NO_CONTEXT
2627 #include "imageri.h"
2728
28 #define DEF_BYTES_LIMIT 0x40000000
29
30 static i_img_dim max_width, max_height;
31 static size_t max_bytes = DEF_BYTES_LIMIT;
32
33 /*
34 =item i_set_image_file_limits(width, height, bytes)
35
29 /*
30 =item im_set_image_file_limits(ctx, width, height, bytes)
31 X<im_set_image_file_limits API>X<i_set_image_file_limits API>
3632 =category Files
33 =synopsis im_set_image_file_limits(aIMCTX, 500, 500, 1000000);
3734 =synopsis i_set_image_file_limits(500, 500, 1000000);
3835
3936 Set limits on the sizes of images read by Imager.
5956
6057 Returns non-zero on success.
6158
59 Also callable as C<i_set_image_file_limits(width, height, bytes)>.
60
6261 =cut
6362 */
6463
6564 int
66 i_set_image_file_limits(i_img_dim width, i_img_dim height, size_t bytes) {
65 im_set_image_file_limits(pIMCTX, i_img_dim width, i_img_dim height, size_t bytes) {
6766 i_clear_error();
6867
6968 if (width < 0) {
7978 return 0;
8079 }
8180
82 max_width = width;
83 max_height = height;
84 max_bytes = bytes ? bytes : DEF_BYTES_LIMIT;
81 aIMCTX->max_width = width;
82 aIMCTX->max_height = height;
83 aIMCTX->max_bytes = bytes ? bytes : DEF_BYTES_LIMIT;
8584
8685 return 1;
8786 }
8887
8988 /*
90 =item i_get_image_file_limits(&width, &height, &bytes)
91
89 =item im_get_image_file_limits(ctx, &width, &height, &bytes)
90 X<im_get_image_file_limits API>X<i_get_image_file_limits>
9291 =category Files
92 =synopsis im_get_image_file_limits(aIMCTX, &width, &height, &bytes)
9393 =synopsis i_get_image_file_limits(&width, &height, &bytes)
9494
9595 Retrieves the file limits set by i_set_image_file_limits().
105105 size_t *bytes - size in memory of the image in bytes.
106106
107107 =back
108
109 Also callable as C<i_get_image_file_limits(&width, &height, &bytes)>.
108110
109111 =cut
110112 */
111113
112114 int
113 i_get_image_file_limits(i_img_dim *width, i_img_dim *height, size_t *bytes) {
114 i_clear_error();
115
116 *width = max_width;
117 *height = max_height;
118 *bytes = max_bytes;
115 im_get_image_file_limits(pIMCTX, i_img_dim *width, i_img_dim *height, size_t *bytes) {
116 im_clear_error(aIMCTX);
117
118 *width = aIMCTX->max_width;
119 *height = aIMCTX->max_height;
120 *bytes = aIMCTX->max_bytes;
119121
120122 return 1;
121123 }
122124
123125 /*
124 =item i_int_check_image_file_limits(width, height, channels, sample_size)
125
126 =item im_int_check_image_file_limits(width, height, channels, sample_size)
127 X<im_int_check_image_file_limits API>X<i_int_check_image_file_limits>
126128 =category Files
127 =synopsis i_i_int_check_image_file_limits(width, height, channels, sizeof(i_sample_t))
129 =synopsis im_int_check_image_file_limits(aIMCTX, width, height, channels, sizeof(i_sample_t))
130 =synopsis i_int_check_image_file_limits(width, height, channels, sizeof(i_sample_t))
128131
129132 Checks the size of a file in memory against the configured image file
130133 limits.
136139
137140 This function is intended to be called by image file read functions.
138141
142 Also callable as C<i_int_check_image_file_limits(width, height, channels, sizeof(i_sample_t)>.
143
139144 =cut
140145 */
141146
142147 int
143 i_int_check_image_file_limits(i_img_dim width, i_img_dim height, int channels, size_t sample_size) {
148 im_int_check_image_file_limits(pIMCTX, i_img_dim width, i_img_dim height, int channels, size_t sample_size) {
144149 size_t bytes;
145 i_clear_error();
150 im_clear_error(aIMCTX);
146151
147152 if (width <= 0) {
148 i_push_errorf(0, "file size limit - image width of %" i_DF " is not positive",
153 im_push_errorf(aIMCTX, 0, "file size limit - image width of %" i_DF " is not positive",
149154 i_DFc(width));
150155 return 0;
151156 }
152 if (max_width && width > max_width) {
153 i_push_errorf(0, "file size limit - image width of %" i_DF " exceeds limit of %" i_DF,
154 i_DFc(width), i_DFc(max_width));
157 if (aIMCTX->max_width && width > aIMCTX->max_width) {
158 im_push_errorf(aIMCTX, 0, "file size limit - image width of %" i_DF " exceeds limit of %" i_DF,
159 i_DFc(width), i_DFc(aIMCTX->max_width));
155160 return 0;
156161 }
157162
158163 if (height <= 0) {
159 i_push_errorf(0, "file size limit - image height of %" i_DF " is not positive",
164 im_push_errorf(aIMCTX, 0, "file size limit - image height of %" i_DF " is not positive",
160165 i_DFc(height));
161166 return 0;
162167 }
163168
164 if (max_height && height > max_height) {
165 i_push_errorf(0, "file size limit - image height of %" i_DF
166 " exceeds limit of %" i_DF, i_DFc(height), i_DFc(max_height));
169 if (aIMCTX->max_height && height > aIMCTX->max_height) {
170 im_push_errorf(aIMCTX, 0, "file size limit - image height of %" i_DF
171 " exceeds limit of %" i_DF, i_DFc(height), i_DFc(aIMCTX->max_height));
167172 return 0;
168173 }
169174
170175 if (channels < 1 || channels > MAXCHANNELS) {
171 i_push_errorf(0, "file size limit - channels %d out of range",
176 im_push_errorf(aIMCTX, 0, "file size limit - channels %d out of range",
172177 channels);
173178 return 0;
174179 }
175180
176181 if (sample_size < 1 || sample_size > sizeof(long double)) {
177 i_push_errorf(0, "file size limit - sample_size %ld out of range",
182 im_push_errorf(aIMCTX, 0, "file size limit - sample_size %ld out of range",
178183 (long)sample_size);
179184 return 0;
180185 }
186191 bytes = width * height * channels * sample_size;
187192 if (bytes / width != height * channels * sample_size
188193 || bytes / height != width * channels * sample_size) {
189 i_push_error(0, "file size limit - integer overflow calculating storage");
190 return 0;
191 }
192 if (max_bytes) {
193 if (bytes > max_bytes) {
194 i_push_errorf(0, "file size limit - storage size of %lu "
194 im_push_error(aIMCTX, 0, "file size limit - integer overflow calculating storage");
195 return 0;
196 }
197 if (aIMCTX->max_bytes) {
198 if (bytes > aIMCTX->max_bytes) {
199 im_push_errorf(aIMCTX, 0, "file size limit - storage size of %lu "
195200 "exceeds limit of %lu", (unsigned long)bytes,
196 (unsigned long)max_bytes);
201 (unsigned long)aIMCTX->max_bytes);
197202 return 0;
198203 }
199204 }
+106
-47
log.c less more
0 #define IMAGER_NO_CONTEXT
1 #include "imageri.h"
02 #include "imconfig.h"
13 #include "log.h"
24 #include <stdlib.h>
810 #define DTBUFF 50
911 #define DATABUFF DTBUFF+3+10+1+5+1+1
1012
11 static int log_level = 0;
12 static FILE *lg_file = NULL;
13 static char *date_format = "%Y/%m/%d %H:%M:%S";
14 static char date_buffer[DTBUFF];
15 static char data_buffer[DATABUFF];
13 #define LOG_DATE_FORMAT "%Y/%m/%d %H:%M:%S"
1614
15 static i_mutex_t log_mutex;
16
17 static void
18 im_vloog(pIMCTX, int level, const char *fmt, va_list ap);
1719
1820 /*
1921 * Logging is active
2022 */
2123
2224 int
23 i_init_log(const char* name,int level) {
25 im_init_log(pIMCTX, const char* name,int level) {
2426 i_clear_error();
25 log_level = level;
27
28 if (!log_mutex) {
29 log_mutex = i_mutex_new();
30 }
31
32 if (aIMCTX->lg_file) {
33 if (aIMCTX->own_log)
34 fclose(aIMCTX->lg_file);
35 aIMCTX->lg_file = NULL;
36 }
37
38 aIMCTX->log_level = level;
2639 if (level < 0) {
27 lg_file = NULL;
40 aIMCTX->lg_file = NULL;
2841 } else {
2942 if (name == NULL) {
30 lg_file = stderr;
43 aIMCTX->lg_file = stderr;
44 aIMCTX->own_log = 0;
3145 } else {
32 if (NULL == (lg_file = fopen(name, "w+")) ) {
33 i_push_errorf(errno, "Cannot open file '%s': (%d)", name, errno);
46 if (NULL == (aIMCTX->lg_file = fopen(name, "w+")) ) {
47 im_push_errorf(aIMCTX, errno, "Cannot open file '%s': (%d)", name, errno);
3448 return 0;
3549 }
50 aIMCTX->own_log = 1;
51 setvbuf(aIMCTX->lg_file, NULL, _IONBF, BUFSIZ);
3652 }
3753 }
38 if (lg_file) {
39 setvbuf(lg_file, NULL, _IONBF, BUFSIZ);
40 mm_log((0,"Imager - log started (level = %d)\n", level));
54 if (aIMCTX->lg_file) {
55 im_log((aIMCTX, 0,"Imager - log started (level = %d)\n", level));
4156 }
4257
43 return lg_file != NULL;
58 return aIMCTX->lg_file != NULL;
4459 }
4560
4661 void
4762 i_fatal(int exitcode,const char *fmt, ... ) {
4863 va_list ap;
49 time_t timi;
50 struct tm *str_tm;
51
52 if (lg_file != NULL) {
53 timi = time(NULL);
54 str_tm = localtime(&timi);
55 if ( strftime(date_buffer, DTBUFF, date_format, str_tm) )
56 fprintf(lg_file,"[%s] ",date_buffer);
64 dIMCTX;
65
66 if (aIMCTX->lg_file != NULL) {
5767 va_start(ap,fmt);
58 vfprintf(lg_file,fmt,ap);
68 im_vloog(aIMCTX, 0, fmt, ap);
5969 va_end(ap);
6070 }
6171 exit(exitcode);
6272 }
6373
74 void
75 im_fatal(pIMCTX, int exitcode,const char *fmt, ... ) {
76 va_list ap;
77
78 if (aIMCTX->lg_file != NULL) {
79 va_start(ap,fmt);
80 im_vloog(aIMCTX, 0, fmt, ap);
81 va_end(ap);
82 }
83 exit(exitcode);
84 }
6485
6586 /*
6687 =item i_loog(level, format, ...)
7192 =cut
7293 */
7394
95 static void
96 im_vloog(pIMCTX, int level, const char *fmt, va_list ap) {
97 time_t timi;
98 struct tm *str_tm;
99 char date_buffer[DTBUFF];
100
101 if (!aIMCTX->lg_file || level > aIMCTX->log_level)
102 return;
103
104 i_mutex_lock(log_mutex);
105
106 timi = time(NULL);
107 str_tm = localtime(&timi);
108 strftime(date_buffer, DTBUFF, LOG_DATE_FORMAT, str_tm);
109 fprintf(aIMCTX->lg_file, "[%s] %10s:%-5d %3d: ", date_buffer,
110 aIMCTX->filename, aIMCTX->line, level);
111 vfprintf(aIMCTX->lg_file, fmt, ap);
112 fflush(aIMCTX->lg_file);
113
114 i_mutex_unlock(log_mutex);
115 }
116
74117 void
75118 i_loog(int level,const char *fmt, ... ) {
119 dIMCTX;
76120 va_list ap;
77 if (level > log_level) return;
78 if (lg_file != NULL) {
79 fputs(data_buffer, lg_file);
80 fprintf(lg_file, "%3d: ",level);
81 va_start(ap,fmt);
82 vfprintf(lg_file, fmt, ap);
83 fflush(lg_file);
84 va_end(ap);
85 }
121
122 if (!aIMCTX->lg_file || level > aIMCTX->log_level)
123 return;
124
125 va_start(ap,fmt);
126 im_vloog(aIMCTX, level, fmt, ap);
127 va_end(ap);
128 }
129
130 void
131 im_loog(pIMCTX, int level,const char *fmt, ... ) {
132 va_list ap;
133
134 if (!aIMCTX->lg_file || level > aIMCTX->log_level)
135 return;
136
137 va_start(ap,fmt);
138 im_vloog(aIMCTX, level, fmt, ap);
139 va_end(ap);
86140 }
87141
88142 /*
95149 */
96150
97151 void
98 i_lhead(const char *file, int line) {
99 time_t timi;
100 struct tm *str_tm;
101
102 if (lg_file != NULL) {
103 timi = time(NULL);
104 str_tm = localtime(&timi);
105 strftime(date_buffer, DTBUFF, date_format, str_tm);
106 #ifdef IMAGER_SNPRINTF
107 snprintf(data_buffer, sizeof(data_buffer), "[%s] %10s:%-5d ", date_buffer, file, line);
108 #else
109 sprintf(data_buffer, "[%s] %10s:%-5d ", date_buffer, file, line);
110 #endif
152 im_lhead(pIMCTX, const char *file, int line) {
153 if (aIMCTX->lg_file != NULL) {
154 aIMCTX->filename = file;
155 aIMCTX->line = line;
111156 }
157 }
158
159 void i_lhead(const char *file, int line) {
160 dIMCTX;
161
162 im_lhead(aIMCTX, file, line);
112163 }
113164
114165 #else
117168 * Logging is inactive - insert dummy functions
118169 */
119170
120 int i_init_log(const char* name,int onoff) {
171 int im_init_log(pIMCTX, const char* name,int onoff) {
121172 i_clear_error();
122173 i_push_error(0, "Logging disabled");
123174 return 0;
124175 }
125176
126177 void i_fatal(int exitcode,const char *fmt, ... ) { exit(exitcode); }
178 void im_fatal(pIMCTX, int exitcode,const char *fmt, ... ) { exit(exitcode); }
127179
128180 void
129181 i_loog(int level,const char *fmt, ... ) {
130182 }
131183
132184 void
185 im_loog(pIMCTX, int level,const char *fmt, ... ) {
186 }
187
188 void
133189 i_lhead(const char *file, int line) { }
134190
191 void
192 im_lhead(pIMCTX, const char *file, int line) { }
193
135194 #endif
1010 global: creates a global variable FILE* lg_file
1111 */
1212
13 int i_init_log( const char *name, int onoff );
13 int im_init_log(pIMCTX, const char *name, int onoff );
14 #define i_init_log(name, onoff) im_init_log(aIMCTX, name, onoff)
15 #ifndef IMAGER_NO_CONTEXT
1416 void i_fatal ( int exitcode,const char *fmt, ... );
17 #endif
18 void im_fatal (pIMCTX, int exitcode,const char *fmt, ... );
19 void im_lhead ( pIMCTX, const char *file, int line );
1520 void i_lhead ( const char *file, int line );
1621 void i_loog(int level,const char *msg, ... ) I_FORMAT_ATTR(2,3);
22 void im_loog(pIMCTX, int level,const char *msg, ... ) I_FORMAT_ATTR(3,4);
1723
1824 /*
19 =item mm_log((level, format, ...))
25 =item im_log((aIMCTX, level, format, ...))
2026 =category Logging
2127
2228 This is the main entry point to logging. Note that the extra set of
2531 This will format a string with the current file and line number to the
2632 log file if logging is enabled.
2733
34 This must be called with a context object defined by one of the
35 C<dIMCTX> macros in scope.
36
37 This can also be called as C<mm_log((level, format, args))> in which
38 case the currently active context is used and any in scope context is
39 ignored.
40
2841 =cut
2942 */
3043
3144 #ifdef IMAGER_LOG
45 #ifndef IMAGER_NO_CONTEXT
3246 #define mm_log(x) { i_lhead(__FILE__,__LINE__); i_loog x; }
47 #endif
48 #define im_log(x) { im_lhead(aIMCTX, __FILE__,__LINE__); im_loog x; }
3349 #else
3450 #define mm_log(x)
51 #define im_log(x)
3552 #endif
3653
3754
99 =over
1010 =cut
1111 */
12
13 #define IMAGER_NO_CONTEXT
1214
1315 #include "imager.h"
1416 #include "imageri.h"
123125 =cut
124126 */
125127
126 i_img *i_img_masked_new(i_img *targ, i_img *mask, i_img_dim x, i_img_dim y, i_img_dim w, i_img_dim h) {
128 i_img *
129 i_img_masked_new(i_img *targ, i_img *mask, i_img_dim x, i_img_dim y, i_img_dim w, i_img_dim h) {
127130 i_img *im;
128131 i_img_mask_ext *ext;
129
130 i_clear_error();
132 dIMCTXim(targ);
133
134 im_clear_error(aIMCTX);
131135 if (x >= targ->xsize || y >= targ->ysize) {
132 i_push_error(0, "subset outside of target image");
136 im_push_error(aIMCTX, 0, "subset outside of target image");
133137 return NULL;
134138 }
135139 if (mask) {
143147 if (y+h > targ->ysize)
144148 h = targ->ysize - y;
145149
146 im = mymalloc(sizeof(i_img));
150 im = im_img_alloc(aIMCTX);
151
147152 memcpy(im, &IIM_base_masked, sizeof(i_img));
153 i_tags_new(&im->tags);
148154 im->xsize = w;
149155 im->ysize = h;
150156 im->channels = targ->channels;
157163 ext->ybase = y;
158164 ext->samps = mymalloc(sizeof(i_sample_t) * im->xsize);
159165 im->ext_data = ext;
166
167 im_img_init(aIMCTX, im);
160168
161169 return im;
162170 }
584592 return result;
585593 }
586594 else {
595 dIMCTXim(im);
587596 i_push_error(0, "Image position outside of image");
588597 return -1;
589598 }
651660 return result;
652661 }
653662 else {
663 dIMCTXim(im);
654664 i_push_error(0, "Image position outside of image");
655665 return -1;
656666 }
0 /*
1 dummy mutexes, for non-threaded builds
2 */
3
4 #include "imageri.h"
5
6 #include <pthread.h>
7
8 /* documented in mutexwin.c */
9
10 struct i_mutex_tag {
11 int dummy;
12 };
13
14 i_mutex_t
15 i_mutex_new(void) {
16 i_mutex_t m;
17
18 m = malloc(sizeof(*m));
19 if (!m)
20 i_fatal(3, "Cannot allocate mutex object");
21
22 return m;
23 }
24
25 void
26 i_mutex_destroy(i_mutex_t m) {
27 free(m);
28 }
29
30 void
31 i_mutex_lock(i_mutex_t m) {
32 (void)m;
33 }
34
35 void
36 i_mutex_unlock(i_mutex_t m) {
37 (void)m;
38 }
0 /*
1 pthreads mutexes
2 */
3
4 #include "imageri.h"
5
6 #include <pthread.h>
7 #include <errno.h>
8
9 /* documented in mutexwin.c */
10
11 struct i_mutex_tag {
12 pthread_mutex_t mutex;
13 };
14
15 i_mutex_t
16 i_mutex_new(void) {
17 i_mutex_t m;
18
19 m = malloc(sizeof(*m));
20 if (!m)
21 i_fatal(3, "Cannot allocate mutex object");
22 if (pthread_mutex_init(&m->mutex, NULL) != 0) {
23 i_fatal(3, "Error initializing mutex %d", errno);
24 }
25
26 return m;
27 }
28
29 void
30 i_mutex_destroy(i_mutex_t m) {
31 pthread_mutex_destroy(&(m->mutex));
32 free(m);
33 }
34
35 void
36 i_mutex_lock(i_mutex_t m) {
37 pthread_mutex_lock(&(m->mutex));
38 }
39
40 void
41 i_mutex_unlock(i_mutex_t m) {
42 pthread_mutex_unlock(&m->mutex);
43 }
0 /*
1 =head1 NAME
2
3 mutex.c - Imager's mutex API.
4
5 =head1 FUNCTIONS
6
7 =over
8
9 =cut
10 */
11
12 #include "imageri.h"
13
14 #include <windows.h>
15
16 struct i_mutex_tag {
17 CRITICAL_SECTION section;
18 };
19
20 /*
21 =item i_mutex_new()
22 =category Mutex functions
23 =synopsis i_mutex_t m = i_mutex_new();
24 =order 10
25
26 Create a mutex.
27
28 If a critical section cannot be created for whatever reason, Imager
29 will abort.
30
31 =cut
32 */
33
34 i_mutex_t
35 i_mutex_new(void) {
36 i_mutex_t m;
37
38 m = malloc(sizeof(*m));
39 if (!m)
40 i_fatal(3, "Cannot allocate mutex object");
41 InitializeCriticalSection(&(m->section));
42
43 return m;
44 }
45
46 /*
47 =item i_mutex_destroy(m)
48 =category Mutex functions
49 =synopsis i_mutex_destroy(m);
50
51 Destroy a mutex.
52
53 =cut
54 */
55
56 void
57 i_mutex_destroy(i_mutex_t m) {
58 DeleteCriticalSection(&(m->section));
59 free(m);
60 }
61
62 /*
63 =item i_mutex_lock(m)
64 =category Mutex functions
65 =synopsis i_mutex_lock(m);
66
67 Lock the mutex, waiting if another thread has the mutex locked.
68
69 =cut
70 */
71
72 void
73 i_mutex_lock(i_mutex_t m) {
74 EnterCriticalSection(&(m->section));
75 }
76
77 /*
78 =item i_mutex_unlock(m)
79 =category Mutex functions
80 =synopsis i_mutex_unlock(m);
81
82 Release the mutex.
83
84 The behavior of releasing a mutex you don't hold is unspecified.
85
86 =cut
87 */
88
89 void
90 i_mutex_unlock(i_mutex_t m) {
91 LeaveCriticalSection(&(m->section));
92 }
93
1616
1717 =cut
1818 */
19
20 #define IMAGER_NO_CONTEXT
1921
2022 #include "imager.h"
2123 #include "imageri.h"
8385 };
8486
8587 /*
86 =item i_img_pal_new(C<x>, C<y>, C<channels>, C<maxpal>)
87
88 =item im_img_pal_new(ctx, C<x>, C<y>, C<channels>, C<maxpal>)
89 X<im_img_pal_new API>X<i_img_pal_new API>
8890 =category Image creation/destruction
91 =synopsis i_img *img = im_img_pal_new(aIMCTX, width, height, channels, max_palette_size)
8992 =synopsis i_img *img = i_img_pal_new(width, height, channels, max_palette_size)
9093
9194 Creates a new paletted image of the supplied dimensions.
9497
9598 Returns a new image or NULL on failure.
9699
100 Also callable as C<i_img_pal_new(width, height, channels, max_palette_size)>.
101
97102 =cut
98103 */
99104 i_img *
100 i_img_pal_new(i_img_dim x, i_img_dim y, int channels, int maxpal) {
105 im_img_pal_new(pIMCTX, i_img_dim x, i_img_dim y, int channels, int maxpal) {
101106 i_img *im;
102107 i_img_pal_ext *palext;
103108 size_t bytes, line_bytes;
112117 return NULL;
113118 }
114119 if (channels < 1 || channels > MAXCHANNELS) {
115 i_push_errorf(0, "Channels must be positive and <= %d", MAXCHANNELS);
120 im_push_errorf(aIMCTX, 0, "Channels must be positive and <= %d", MAXCHANNELS);
116121 return NULL;
117122 }
118123 bytes = sizeof(i_palidx) * x * y;
184189
185190 =cut
186191 */
187 int i_img_to_rgb_inplace(i_img *im) {
192 int
193 i_img_to_rgb_inplace(i_img *im) {
188194 i_img temp;
195 dIMCTXim(im);
189196
190197 if (im->virtual)
191198 return 0;
214221 i_img *i_img_to_pal(i_img *src, i_quantize *quant) {
215222 i_palidx *result;
216223 i_img *im;
224 dIMCTXim(src);
217225
218226 i_clear_error();
219227
243251
244252 =cut
245253 */
246 i_img *i_img_to_rgb(i_img *src) {
254 i_img *
255 i_img_to_rgb(i_img *src) {
256 dIMCTXim(src);
247257 i_img *im = i_img_empty_ch(NULL, src->xsize, src->ysize, src->channels);
248258 i_img_rgb_convert(im, src);
249259
305315 return 0;
306316 }
307317 else {
308 mm_log((1, "i_ppix: color(%d,%d,%d) not found, converting to rgb\n",
318 dIMCTXim(im);
319 im_log((aIMCTX, 1, "i_ppix: color(%d,%d,%d) not found, converting to rgb\n",
309320 val->channel[0], val->channel[1], val->channel[2]));
310321 if (i_img_to_rgb_inplace(im)) {
311322 return i_ppix(im, x, y, val);
422433 if (chans) {
423434 for (ch = 0; ch < chan_count; ++ch) {
424435 if (chans[ch] < 0 || chans[ch] >= im->channels) {
425 i_push_errorf(0, "No channel %d in this image", chans[ch]);
436 dIMCTXim(im);
437 im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
426438 }
427439 }
428440
438450 }
439451 else {
440452 if (chan_count <= 0 || chan_count > im->channels) {
441 i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels",
453 dIMCTXim(im);
454 im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels",
442455 chan_count);
443456 return 0;
444457 }
644657 /* make sure we have good channel numbers */
645658 for (ch = 0; ch < chan_count; ++ch) {
646659 if (chans[ch] < 0 || chans[ch] >= im->channels) {
647 i_push_errorf(0, "No channel %d in this image", chans[ch]);
660 dIMCTXim(im);
661 im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
648662 return -1;
649663 }
650664 }
661675 }
662676 else {
663677 if (chan_count <= 0 || chan_count > im->channels) {
664 i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels",
678 dIMCTXim(im);
679 im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels",
665680 chan_count);
666681 return -1;
667682 }
681696 return count;
682697 }
683698 else {
699 dIMCTXim(im);
684700 i_push_error(0, "Image position outside of image");
685701 return -1;
686702 }
715731 /* make sure we have good channel numbers */
716732 for (ch = 0; ch < chan_count; ++ch) {
717733 if (chans[ch] < 0 || chans[ch] >= im->channels) {
718 i_push_errorf(0, "No channel %d in this image", chans[ch]);
734 dIMCTXim(im);
735 im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]);
719736 return -1;
720737 }
721738 }
732749 }
733750 else {
734751 if (chan_count <= 0 || chan_count > im->channels) {
735 i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels",
752 dIMCTXim(im);
753 im_push_errorf(aIMCTX, 0, "chan_count %d out of range, must be >0, <= channels",
736754 chan_count);
737755 return -1;
738756 }
752770 return count;
753771 }
754772 else {
773 dIMCTXim(im);
755774 i_push_error(0, "Image position outside of image");
756775 return -1;
757776 }
0 /* perlio.c - Imager's interface to PerlIO
1
2 */
3 #define IMAGER_NO_CONTEXT
4 #include "imager.h"
5 #include "EXTERN.h"
6 #include "perl.h"
7 #include "imperlio.h"
8
9
10 static ssize_t
11 perlio_reader(void *handle, void *buf, size_t count);
12 static ssize_t
13 perlio_writer(void *handle, const void *buf, size_t count);
14 static off_t
15 perlio_seeker(void *handle, off_t offset, int whence);
16 static int
17 perlio_closer(void *handle);
18 static void
19 perlio_destroy(void *handle);
20 static const char *my_strerror(pTHX_ int err);
21
22 #ifndef tTHX
23 #define tTHX PerlInterpreter *
24 #endif
25
26 typedef struct {
27 PerlIO *handle;
28 pIMCTX;
29 #ifdef MULTIPLICITY
30 tTHX my_perl;
31 #endif
32 } im_perlio;
33
34 #define dIMCTXperlio(state) dIMCTXctx(state->aIMCTX)
35
36 /*
37 =item im_io_new_perlio(PerlIO *)
38
39 Create a new perl I/O object that reads/writes/seeks on a PerlIO
40 handle.
41
42 The close() handle flushes output but does not close the handle.
43
44 =cut
45 */
46
47 i_io_glue_t *
48 im_io_new_perlio(pTHX_ PerlIO *handle) {
49 im_perlio *state = mymalloc(sizeof(im_perlio));
50 dIMCTX;
51
52 state->handle = handle;
53 #ifdef MULTIPLICITY
54 state->aTHX = aTHX;
55 #endif
56 state->aIMCTX = aIMCTX;
57
58 return io_new_cb(state, perlio_reader, perlio_writer,
59 perlio_seeker, perlio_closer, perlio_destroy);
60 }
61
62 static ssize_t
63 perlio_reader(void *ctx, void *buf, size_t count) {
64 im_perlio *state = ctx;
65 dTHXa(state->my_perl);
66 dIMCTXperlio(state);
67
68 ssize_t result = PerlIO_read(state->handle, buf, count);
69 if (result == 0 && PerlIO_error(state->handle)) {
70 im_push_errorf(aIMCTX, errno, "read() failure (%s)", my_strerror(aTHX_ errno));
71 return -1;
72 }
73
74 return result;
75 }
76
77 static ssize_t
78 perlio_writer(void *ctx, const void *buf, size_t count) {
79 im_perlio *state = ctx;
80 dTHXa(state->my_perl);
81 dIMCTXperlio(state);
82 ssize_t result;
83
84 result = PerlIO_write(state->handle, buf, count);
85
86 if (result == 0) {
87 im_push_errorf(aIMCTX, errno, "write() failure (%s)", my_strerror(aTHX_ errno));
88 }
89
90 return result;
91 }
92
93 static off_t
94 perlio_seeker(void *ctx, off_t offset, int whence) {
95 im_perlio *state = ctx;
96 dTHXa(state->my_perl);
97 dIMCTXperlio(state);
98
99 if (whence != SEEK_CUR || offset != 0) {
100 if (PerlIO_seek(state->handle, offset, whence) < 0) {
101 im_push_errorf(aIMCTX, errno, "seek() failure (%s)", my_strerror(aTHX_ errno));
102 return -1;
103 }
104 }
105
106 return PerlIO_tell(state->handle);
107 }
108
109 static int
110 perlio_closer(void *ctx) {
111 im_perlio *state = ctx;
112 dTHXa(state->my_perl);
113 dIMCTXperlio(state);
114
115 if (PerlIO_flush(state->handle) < 0) {
116 im_push_errorf(aIMCTX, errno, "flush() failure (%s)", my_strerror(aTHX_ errno));
117 return -1;
118 }
119 return 0;
120 }
121
122 static void
123 perlio_destroy(void *ctx) {
124 myfree(ctx);
125 }
126
127 static
128 const char *my_strerror(pTHX_ int err) {
129 const char *result = strerror(err);
130
131 if (!result)
132 result = "Unknown error";
133
134 return result;
135 }
136
0 #include "imager.h"
0 #include "imdatatypes.h"
1 #include "immacros.h"
12
23 /* structures for passing data between Imager-plugin and the Imager-module */
34
1314 #define i_color_set(cl,r,g,b,a) (symbol_table->i_color_set(cl,r,g,b,a))
1415 #define i_color_info(cl) (symbol_table->i_color_info(cl))
1516
16 #define i_img_new() (symbol_table->i_img_new())
17 #define i_img_empty(im,x,y) ((symbol_table->i_img_empty(im,x,y))
18 #define i_img_empty_ch(im,x,y,ch) ((symbol_table->i_img_empty_ch(im,x,y,ch))
19 #define i_img_exorcise(im) (symbol_table->i_img_exorcise(im))
20 #define i_img_info(im,info) (symbol_table->i_img_info(im,info))
17 #define im_get_context() (symbol_table->im_get_context_f())
18 #define i_img_empty_ch(im,x,y,ch) ((symbol_table->i_img_empty_ch_f(im_get_context(), im,x,y,ch))
19 #define i_img_exorcise(im) (symbol_table->i_img_exorcise_f(im))
20 #define i_img_info(im,info) (symbol_table->i_img_info_f(im,info))
2121
22 #define i_img_setmask(im,ch_mask) (symbol_table->i_img_setmask(im,ch_mask))
23 #define i_img_getmask(im) (symbol_table->i_img_getmask(im))
22 #define i_img_setmask(im,ch_mask) (symbol_table->i_img_setmask_f(im,ch_mask))
23 #define i_img_getmask(im) (symbol_table->i_img_getmask_f(im))
2424
2525 /*
2626 Not needed? The i_gpix() macro in image.h will call the right function
251251 if (fabs(sz) > 0.0000001
252252 && sx >= -1 && sx < src->xsize
253253 && sy >= -1 && sy < src->ysize) {
254 i_img_dim bx = floor(sx);
255 i_img_dim by = floor(sy);
254256
255257 ROT_DEBUG(fprintf(stderr, "map " i_DFp " to %g,%g\n", i_DFcp(x, y), sx, sy));
256 if (sx != (i_img_dim)sx) {
257 if (sy != (i_img_dim)sy) {
258 if (sx != bx) {
259 if (sy != by) {
258260 IM_COLOR c[2][2];
259261 IM_COLOR ci2[2];
260262 ROT_DEBUG(fprintf(stderr, " both non-int\n"));
261263 for (i = 0; i < 2; ++i)
262264 for (j = 0; j < 2; ++j)
263 if (IM_GPIX(src, floor(sx)+i, floor(sy)+j, &c[j][i]))
265 if (IM_GPIX(src, bx+i, by+j, &c[j][i]))
264266 c[j][i] = back;
265267 for (j = 0; j < 2; ++j)
266268 ci2[j] = interp_i_color(c[j][0], c[j][1], sx, src->channels);
270272 IM_COLOR ci2[2];
271273 ROT_DEBUG(fprintf(stderr, " y int, x non-int\n"));
272274 for (i = 0; i < 2; ++i)
273 if (IM_GPIX(src, floor(sx)+i, sy, ci2+i))
275 if (IM_GPIX(src, bx+i, sy, ci2+i))
274276 ci2[i] = back;
275277 vals[x] = interp_i_color(ci2[0], ci2[1], sx, src->channels);
276278 }
280282 IM_COLOR ci2[2];
281283 ROT_DEBUG(fprintf(stderr, " x int, y non-int\n"));
282284 for (i = 0; i < 2; ++i)
283 if (IM_GPIX(src, sx, floor(sy)+i, ci2+i))
285 if (IM_GPIX(src, bx, by+i, ci2+i))
284286 ci2[i] = back;
285287 vals[x] = interp_i_color(ci2[0], ci2[1], sy, src->channels);
286288 }
401403
402404 #define numfmt "%23g"
403405
404 ROT_DEBUG(static dump_mat(const char *name, double *f) {
406 ROT_DEBUG(static void dump_mat(const char *name, double *f) {
405407 fprintf(stderr, "%s:\n " numfmt " " numfmt " " numfmt "\n"
406408 " " numfmt " " numfmt " " numfmt "\n"
407409 " " numfmt " " numfmt " " numfmt "\n",
415417 double xlate2[9] = { 0 };
416418 double temp[9], matrix[9];
417419 i_img_dim x1, x2, y1, y2, newxsize, newysize;
420
421 ROT_DEBUG(fprintf(stderr, "rotate angle %.20g\n", amount));
418422
419423 /* first translate the centre of the image to (0,0) */
420424 xlate1[0] = 1;
22 # to make sure we get expected values
33
44 use strict;
5 use Test::More tests => 433;
5 use Test::More tests => 466;
66
77 BEGIN { use_ok(Imager => qw(:handy :all)) }
88
124124 is_color3($colors[1], 0, 255, 0, "still green");
125125 is_color3($colors[2], 0, 0, 255, "still blue");
126126 is_color3($colors[3], 0, 0, 0, "still black");
127 is_deeply([ unpack("C", Imager::i_gsamp($im_pal2, 0, 100, 0, [ 0, 1, 2 ])) ],
128 [ unpack("C", "\0\xFF\0\0\0\0"."\xFF\0\0" x 48 . "\0\0\xFF" x 50) ],
129 "colors are still correct");
127 my @samples = Imager::i_gsamp($im_pal2, 0, 100, 0, [ 0, 1, 2 ]);
128 my @expect = unpack("C*", "\0\xFF\0\0\0\0"."\xFF\0\0" x 48 . "\0\0\xFF" x 50);
129 my $match_list = is_deeply(\@samples, \@expect, "colors are still correct");
130 my $samples = Imager::i_gsamp($im_pal2, 0, 100, 0, [ 0, 1, 2 ]);
131 my $match_scalar = is_deeply([ unpack("C*", $samples) ],
132 \@expect, "colors are still correct (scalar)");
133 unless ($match_list && $match_scalar) {
134 # this has been failing on a particular smoker, provide more
135 # diagnostic information
136 print STDERR "Pallete:\n";
137 print STDERR " $_: ", join(",", $colors[$_]->rgba), "\n" for 0..$#colors;
138 print STDERR "Samples (list): ", join(",", @samples), "\n";
139 print STDERR "Samples (scalar): ", join(",", unpack("C*", $samples)), "\n";
140 print STDERR "Indexes: ", join(",", Imager::i_gpal($im_pal2, 0, 100, 0)), "\n";
141 }
130142 }
131143
132144 # test the OO interfaces
184196 is($impal3->type, 'paletted', "and is paletted");
185197 }
186198
187 { # to_rgb on incomplete image
199 {
188200 my $im = Imager->new;
189201 ok($im, "make empty image");
190202 ok(!$im->to_rgb8, "convert to rgb8");
191 is($im->errstr, "empty input image", "check message");
203 is($im->errstr, "to_rgb8: empty input image", "check message");
204 is($im->bits, undef, "can't call bits on an empty image");
205 is($im->errstr, "bits: empty input image", "check message");
206 is($im->type, undef, "can't call type on an empty image");
207 is($im->errstr, "type: empty input image", "check message");
208 is($im->virtual, undef, "can't call virtual on an empty image");
209 is($im->errstr, "virtual: empty input image", "check message");
210 is($im->is_bilevel, undef, "can't call virtual on an empty image");
211 is($im->errstr, "is_bilevel: empty input image", "check message");
212 ok(!$im->getscanline(y => 0), "can't call getscanline on an empty image");
213 is($im->errstr, "getscanline: empty input image", "check message");
214 ok(!$im->setscanline(y => 0, pixels => [ $red, $blue ]),
215 "can't call setscanline on an empty image");
216 is($im->errstr, "setscanline: empty input image", "check message");
217 ok(!$im->getsamples(y => 0), "can't call getsamples on an empty image");
218 is($im->errstr, "getsamples: empty input image", "check message");
219 is($im->getwidth, undef, "can't get width of empty image");
220 is($im->errstr, "getwidth: empty input image", "check message");
221 is($im->getheight, undef, "can't get height of empty image");
222 is($im->errstr, "getheight: empty input image", "check message");
223 is($im->getchannels, undef, "can't get channels of empty image");
224 is($im->errstr, "getchannels: empty input image", "check message");
225 is($im->getmask, undef, "can't get mask of empty image");
226 is($im->errstr, "getmask: empty input image", "check message");
227 is($im->setmask, undef, "can't set mask of empty image");
228 is($im->errstr, "setmask: empty input image", "check message");
192229 }
193230
194231 { # basic checks, 8-bit direct images
10631100 }
10641101 }
10651102
1103 {
1104 my $empty = Imager->new;
1105 ok(!$empty->addtag(name => "foo", value => 1),
1106 "can't addtag on an empty image");
1107 is($empty->errstr, "addtag: empty input image",
1108 "check error message");
1109 ok(!$empty->settag(name => "foo", value => 1),
1110 "can't settag on an empty image");
1111 is($empty->errstr, "settag: empty input image",
1112 "check error message");
1113 ok(!$empty->deltag(name => "foo"), "can't deltag on an empty image");
1114 is($empty->errstr, "deltag: empty input image",
1115 "check error message");
1116 ok(!$empty->tags(name => "foo"), "can't tags on an empty image");
1117 is($empty->errstr, "tags: empty input image",
1118 "check error message");
1119 }
1120
10661121 Imager->close_log();
10671122
10681123 unless ($ENV{IMAGER_KEEP_FILES}) {
00 #!perl -w
11 use strict;
2 use Test::More tests => 242;
2 use Test::More tests => 244;
33 use Imager qw(:all :handy);
44 use Imager::Test qw(is_color3 is_fcolor3);
55
686686 "check values written");
687687 }
688688
689 {
690 my $empty = Imager->new;
691 ok(!$empty->masked, "fail to make a masked image from an empty");
692 is($empty->errstr, "masked: empty input image",
693 "check error message");
694 }
695
689696 Imager->close_log();
690697
691698 unless ($ENV{IMAGER_KEEP_FILES}) {
209209 my $im = Imager->new;
210210 ok($im, "make empty image");
211211 ok(!$im->to_rgb16, "convert empty image to 16-bit");
212 is($im->errstr, "empty input image", "check message");
212 is($im->errstr, "to_rgb16: empty input image", "check message");
213213 }
214214
215215 { # bounds checks
165165 my $im = Imager->new;
166166 ok($im, "make empty image");
167167 ok(!$im->to_rgb_double, "convert empty image to double");
168 is($im->errstr, "empty input image", "check message");
168 is($im->errstr, "to_rgb_double: empty input image", "check message");
169169 }
170170
171171 my $psamp_outside_error = "Image position outside of image";
00 #!perl -w
11 # some of this is tested in t01introvert.t too
22 use strict;
3 use Test::More tests => 211;
3 use Test::More tests => 226;
44 BEGIN { use_ok("Imager", ':handy'); }
55
66 use Imager::Test qw(image_bounds_checks test_image is_color3 isnt_image is_color4 is_fcolor3);
2828 print "# blacki $blacki\n";
2929 ok(defined $blacki && $blacki == 0, "we got the first color");
3030
31 ok($img->colorcount() == 4, "should have 4 colors");
31 is($img->colorcount(), 4, "should have 4 colors");
32 is($img->maxcolors, 256, "maxcolors always 256");
33
3234 my ($redi, $greeni, $bluei) = 1..3;
3335
3436 my @all = $img->getcolors;
589591 0, 0, 1.0, "get a pixel in float form, make sure it's blue");
590592 }
591593
594 {
595 my $empty = Imager->new;
596 ok(!$empty->to_paletted, "can't convert an empty image");
597 is($empty->errstr, "to_paletted: empty input image",
598 "check error message");
599
600 is($empty->addcolors(colors => [ $black ]), -1,
601 "can't addcolors() to an empty image");
602 is($empty->errstr, "addcolors: empty input image",
603 "check error message");
604
605 ok(!$empty->setcolors(colors => [ $black ]),
606 "can't setcolors() to an empty image");
607 is($empty->errstr, "setcolors: empty input image",
608 "check error message");
609
610 ok(!$empty->getcolors(),
611 "can't getcolors() from an empty image");
612 is($empty->errstr, "getcolors: empty input image",
613 "check error message");
614
615 is($empty->colorcount, -1, "can't colorcount() an empty image");
616 is($empty->errstr, "colorcount: empty input image",
617 "check error message");
618
619 is($empty->maxcolors, -1, "can't maxcolors() an empty image");
620 is($empty->errstr, "maxcolors: empty input image",
621 "check error message");
622
623 is($empty->findcolor(color => $blue), undef,
624 "can't findcolor an empty image");
625 is($empty->errstr, "findcolor: empty input image",
626 "check error message");
627 }
628
592629 Imager->close_log;
593630
594631 unless ($ENV{IMAGER_KEEP_FILES}) {
00 #!perl -w
11 use strict;
2 use Test::More tests => 252;
2 use Test::More tests => 274;
3 use Imager::Test qw(is_image);
34 # for SEEK_SET etc, Fcntl doesn't provide these in 5.005_03
45 use IO::Seekable;
6 use Config;
57
68 BEGIN { use_ok(Imager => ':all') };
79
226228 my $result =
227229 eval {
228230 $io->raw_write($data);
231 1;
229232 };
230 ok($@, "should have croaked")
233 ok(!$result, "should have croaked")
231234 and print "# $@\n";
232235 }
233236
833836 }
834837 }
835838
839 SKIP:
840 {
841 $Config{useperlio}
842 or skip "PerlIO::scalar requires perlio", 13;
843
844 my $foo;
845 open my $fh, "+<", \$foo;
846 my $io = Imager::IO->_new_perlio($fh);
847 ok($io, "perlio: make a I/O object for a perl scalar fh");
848 is($io->write("test"), 4, "perlio: check we can write");
849 is($io->seek(2, SEEK_SET), 2, "perlio: check we can seek");
850 is($io->write("more"), 4, "perlio: write some more");
851 is($io->seek(0, SEEK_SET), 0, "perlio: seek back to start");
852 my $data;
853 is($io->read($data, 10), 6, "perlio: read everything back");
854 is($data, "temore", "perlio: check we read back what we wrote");
855 is($io->close, 0, "perlio: close it");
856 is($foo, "temore", "perlio: check it got to the scalar properly");
857
858 my $io2 = Imager::IO->new_fh($fh);
859 ok($io2, "new_fh() can make an I/O layer object from a scalar fh");
860 close $fh;
861
862 my $im = Imager->new(xsize => 10, ysize => 10);
863 $foo = "";
864 open my $fh2, ">", \$foo;
865 ok($im->write(fh => $fh2, type => "pnm"), "can write image to scalar fh")
866 or print "# ", $im->errstr, "\n";
867
868 close $fh2;
869 open my $fh3, "<", \$foo;
870 my $im2 = Imager->new(fh => $fh3);
871 ok($im2, "read image from a scalar fh");
872 is_image($im, $im2, "check they match");
873 }
874
875 {
876 tie *FOO, "IO::Tied";
877 my $io = Imager::IO->new_fh(\*FOO);
878 ok($io, "tied: make a I/O object for a tied fh");
879 is($io->write("test"), 4, "tied: check we can write");
880 is($io->seek(2, SEEK_SET), 2, "tied: check we can seek");
881 is($io->write("more"), 4, "tied: write some more");
882 is($io->seek(0, SEEK_SET), 0, "tied: seek back to start");
883 my $data;
884 is($io->read($data, 10), 6, "tied: read everything back");
885 is($data, "temore", "tied: check we read back what we wrote");
886 is($io->close, 0, "tied: close it");
887 is(tied(*FOO)->[0], "temore", "tied: check it got to the output properly");
888 }
889
836890 Imager->close_log;
837891
838892 unless ($ENV{IMAGER_KEEP_FILES}) {
867921 sub fail_seek {
868922 return -1;
869923 }
924
925 package IO::Tied;
926 use base 'Tie::Handle';
927 use IO::Seekable;
928
929 sub TIEHANDLE {
930 return bless [ "", 0 ];
931 }
932
933 sub PRINT {
934 for my $entry (@_[1 .. $#_]) {
935 substr($_[0][0], $_[0][1], length $entry, $entry);
936 $_[0][1] += length $entry;
937 }
938
939 return 1;
940 }
941
942 sub SEEK {
943 my ($self, $offset, $whence) = @_;
944
945 my $newpos;
946 if ($whence == SEEK_SET) {
947 $newpos = $offset;
948 }
949 elsif ($whence == SEEK_CUR) {
950 $newpos = $self->[1] + $offset;
951 }
952 elsif ($whence == SEEK_END) {
953 $newpos = length($self->[0]) + $newpos;
954 }
955 else {
956 return -1;
957 }
958
959 if ($newpos < 0) {
960 return 0;
961 }
962
963 $self->[1] = $newpos;
964
965 return 1;
966 }
967
968 sub TELL {
969 return $_[0][1];
970 }
971
972 sub READ {
973 my $self = shift;
974 my $outlen = $_[1];
975 my $offset = @_ > 2 ? $_[2] : 0;
976 if ($self->[1] + $outlen > length $self->[0]) {
977 $outlen = length($self->[0]) - $self->[1];
978 $outlen <= 0
979 and return "";
980 }
981 defined $_[0] or $_[0] = "";
982 substr($_[0], $offset, $outlen) = substr($self->[0], $self->[1], $outlen);
983 $self->[1] += $outlen;
984
985 return $outlen;
986 }
0 #!perl -w
1 use strict;
2
3 # avoiding this prologue would be nice, but it seems to be unavoidable,
4 # see "It is also important to note ..." in perldoc threads
5 use Config;
6 my $loaded_threads;
7 BEGIN {
8 if ($Config{useithreads} && $] > 5.008007) {
9 $loaded_threads =
10 eval {
11 require threads;
12 threads->import;
13 1;
14 };
15 }
16 }
17 use Test::More;
18
19 $Config{useithreads}
20 or plan skip_all => "can't test Imager's threads support with no threads";
21 $] > 5.008007
22 or plan skip_all => "require a perl with CLONE_SKIP to test Imager's threads support";
23 $loaded_threads
24 or plan skip_all => "couldn't load threads";
25
26 $INC{"Devel/Cover.pm"}
27 and plan skip_all => "threads and Devel::Cover don't get along";
28
29 use Imager;
30
31 -d "testout" or mkdir "testout";
32
33 Imager->open_log(log => "testout/t080log1.log")
34 or plan skip_all => "Cannot open log file: " . Imager->errstr;
35
36 plan tests => 3;
37
38 Imager->log("main thread a\n");
39
40 my $t1 = threads->create
41 (
42 sub {
43 Imager->log("child thread a\n");
44 Imager->open_log(log => "testout/t080log2.log")
45 or die "Cannot open second log file: ", Imager->errstr;
46 Imager->log("child thread b\n");
47 sleep(1);
48 Imager->log("child thread c\n");
49 sleep(1);
50 1;
51 }
52 );
53
54 Imager->log("main thread b\n");
55 sleep(1);
56 Imager->log("main thread c\n");
57 ok($t1->join, "join child thread");
58 Imager->log("main thread d\n");
59 Imager->close_log();
60
61 my %log1 = parse_log("testout/t080log1.log");
62 my %log2 = parse_log("testout/t080log2.log");
63
64 my @log1 =
65 (
66 "main thread a",
67 "main thread b",
68 "child thread a",
69 "main thread c",
70 "main thread d",
71 );
72
73 my @log2 =
74 (
75 "child thread b",
76 "child thread c",
77 );
78
79 is_deeply(\%log1, { map {; $_ => 1 } @log1 },
80 "check messages in main thread log");
81 is_deeply(\%log2, { map {; $_ => 1 } @log2 },
82 "check messages in child thread log");
83
84 # grab the messages from the given log
85 sub parse_log {
86 my ($filename) = @_;
87
88 open my $fh, "<", $filename
89 or die "Cannot open log file $filename: $!";
90
91 my %lines;
92 while (<$fh>) {
93 chomp;
94 my ($date, $time, $file_line, $level, $message) = split ' ', $_, 5;
95 $lines{$message} = 1;
96 }
97
98 delete $lines{"Imager - log started (level = 1)"};
99 delete $lines{"Imager $Imager::VERSION starting"};
100
101 return %lines;
102 }
103
104 END {
105 unlink "testout/t080log1.log", "testout/t080log2.log"
106 unless $ENV{IMAGER_KEEP_FILES};
107 }
0 #!perl -w
1 use strict;
2
3 # avoiding this prologue would be nice, but it seems to be unavoidable,
4 # see "It is also important to note ..." in perldoc threads
5 use Config;
6 my $loaded_threads;
7 BEGIN {
8 if ($Config{useithreads} && $] > 5.008007) {
9 $loaded_threads =
10 eval {
11 require threads;
12 threads->import;
13 1;
14 };
15 }
16 }
17 use Test::More;
18
19 $Config{useithreads}
20 or plan skip_all => "can't test Imager's threads support with no threads";
21 $] > 5.008007
22 or plan skip_all => "require a perl with CLONE_SKIP to test Imager's threads support";
23 $loaded_threads
24 or plan skip_all => "couldn't load threads";
25
26 $INC{"Devel/Cover.pm"}
27 and plan skip_all => "threads and Devel::Cover don't get along";
28
29 use Imager;
30
31 # test that the error contexts are separate under threads
32
33 plan tests => 11;
34
35 Imager->open_log(log => "testout/t081error.log");
36
37 Imager::i_clear_error();
38 Imager::i_push_error(0, "main thread a");
39
40 my @threads;
41 for my $tid (1..5) {
42 my $t1 = threads->create
43 (
44 sub {
45 my $id = shift;
46 Imager::i_push_error(0, "$id: child thread a");
47 sleep(1+rand(4));
48 Imager::i_push_error(1, "$id: child thread b");
49
50 is_deeply([ Imager::i_errors() ],
51 [
52 [ "$id: child thread b", 1 ],
53 [ "$id: child thread a", 0 ],
54 ], "$id: check errors in child");
55 1;
56 },
57 $tid
58 );
59 push @threads, [ $tid, $t1 ];
60 }
61
62 Imager::i_push_error(1, "main thread b");
63
64 for my $thread (@threads) {
65 my ($id, $t1) = @$thread;
66 ok($t1->join, "join child $id");
67 }
68
69 Imager::i_push_error(2, "main thread c");
70
71 is_deeply([ Imager::i_errors() ],
72 [
73 [ "main thread c", 2 ],
74 [ "main thread b", 1 ],
75 [ "main thread a", 0 ],
76 ], "check errors in parent");
77
0 #!perl -w
1 use strict;
2
3 # avoiding this prologue would be nice, but it seems to be unavoidable,
4 # see "It is also important to note ..." in perldoc threads
5 use Config;
6 my $loaded_threads;
7 BEGIN {
8 if ($Config{useithreads} && $] > 5.008007) {
9 $loaded_threads =
10 eval {
11 require threads;
12 threads->import;
13 1;
14 };
15 }
16 }
17 use Test::More;
18
19 $Config{useithreads}
20 or plan skip_all => "can't test Imager's threads support with no threads";
21 $] > 5.008007
22 or plan skip_all => "require a perl with CLONE_SKIP to test Imager's threads support";
23 $loaded_threads
24 or plan skip_all => "couldn't load threads";
25
26 $INC{"Devel/Cover.pm"}
27 and plan skip_all => "threads and Devel::Cover don't get along";
28
29 use Imager;
30
31 # test that image file limits are localized to a thread
32
33 plan tests => 31;
34
35 Imager->open_log(log => "testout/t082limit.log");
36
37 ok(Imager->set_file_limits(width => 10, height => 10, bytes => 300),
38 "set limits to 10, 10, 300");
39
40 ok(Imager->check_file_limits(width => 10, height => 10),
41 "successful check limits in parent");
42
43 ok(!Imager->check_file_limits(width => 10, height => 10, sample_size => 2),
44 "failed check limits in parent");
45
46 my @threads;
47 for my $tid (1..5) {
48 my $t1 = threads->create
49 (
50 sub {
51 my $id = shift;
52 my $dlimit = $tid * 5;
53 my $blimit = $dlimit * $dlimit * 3;
54 ok(Imager->set_file_limits(width => $dlimit, height => $dlimit,
55 bytes => $blimit),
56 "$tid: set limits to $dlimit x $dlimit, $blimit bytes");
57 ok(Imager->check_file_limits(width => $dlimit, height => $dlimit),
58 "$tid: successful check $dlimit x $dlimit");
59 ok(!Imager->check_file_limits(width => $dlimit, height => $dlimit, sample_size => 2),
60 "$tid: failed check $dlimit x $dlimit, ssize 2");
61 is_deeply([ Imager->get_file_limits ], [ $dlimit, $dlimit, $blimit ],
62 "check limits are still $dlimit x $dlimit , $blimit bytes");
63 },
64 $tid
65 );
66 push @threads, [ $tid, $t1 ];
67 }
68
69 for my $thread (@threads) {
70 my ($id, $t1) = @$thread;
71 ok($t1->join, "join child $id");
72 }
73
74 ok(Imager->check_file_limits(width => 10, height => 10),
75 "test we still pass");
76 ok(!Imager->check_file_limits(width => 10, height => 10, sample_size => 2),
77 "test we still fail");
78 is_deeply([ Imager->get_file_limits ], [ 10, 10, 300 ],
79 "check original main thread limits still set");
33 # the file format
44
55 use strict;
6 use Test::More tests => 85;
6 use Test::More tests => 89;
77 use Imager;
88
99 -d "testout" or mkdir "testout";
145145 }
146146 }
147147
148 { # test empty image handling for write()/write_multi()
149 my $empty = Imager->new;
150 my $data;
151 ok(!$empty->write(data => \$data, type => "pnm"),
152 "fail to write an empty image");
153 is($empty->errstr, "write: empty input image", "check error message");
154 my $good = Imager->new(xsize => 1, ysize => 1);
155 ok(!Imager->write_multi({ data => \$data, type => "pnm" }, $good, $empty),
156 "fail to write_multi an empty image");
157 is(Imager->errstr, "write_multi: empty input image (image 2)");
158 }
159
148160 # check file type probe
149161 probe_ok("49492A41", undef, "not quite tiff");
150162 probe_ok("4D4D0041", undef, "not quite tiff");
175175 ok(!$im->read(file => 'testout/t103_empty.raw', xsize => 50, ysize=>50, type=>'raw', interleave => 1),
176176 'read an empty file');
177177 is($im->errstr, 'premature end of file', "check message");
178 open RAW, "> testout/t103_empty.raw"
179 or die "Cannot create testout/t103_empty.raw: $!";
180 ok(!$im->read(fh => \*RAW, , xsize => 50, ysize=>50, type=>'raw', interleave => 1),
181 'read a file open for write');
182 cmp_ok($im->errstr, '=~', '^error reading file: read\(\) failure', "check message");
183
178 SKIP:
179 {
180 # see 862083f7e40bc2a9e3b94aedce56c1336e7bdb25 in perl5 git
181 $] >= 5.010
182 or skip "5.8.x and earlier don't treat a read on a WRONLY file as an error", 2;
183 open RAW, "> testout/t103_empty.raw"
184 or die "Cannot create testout/t103_empty.raw: $!";
185 ok(!$im->read(fh => \*RAW, , xsize => 50, ysize=>50, type=>'raw', interleave => 1),
186 'read a file open for write');
187 cmp_ok($im->errstr, '=~', '^error reading file: read\(\) failure', "check message");
188 }
184189 }
185190
186191
00 #!perl -w
11 use strict;
2 use Test::More tests => 157;
2 use Test::More tests => 165;
33
44 use Imager ':handy';
55 use Imager::Fill;
665665 is($im->getcolorcount, 2, "only original and fill color");
666666 }
667667
668 SKIP:
669 {
670 # the wrong image dimension was used for adjusting vs yoff,
671 # producing uncovered parts of the output image
672 my $tx = Imager->new(xsize => 30, ysize => 20);
673 ok($tx, "create texture image")
674 or diag "create texture image", Imager->errstr;
675 $tx or skip "no texture image", 7;
676 ok($tx->box(filled => 1, color => "ff0000"), "fill texture image")
677 or diag "fill texture image", $tx->errstr;
678 my $cmp = Imager->new(xsize => 100, ysize => 100);
679 ok($cmp, "create comparison image")
680 or diag "create comparison image: ", Imager->errstr;
681 $cmp or skip "no comparison image", 5;
682 ok($cmp->box(filled => 1, color => "FF0000"), "fill compare image")
683 or diag "fill compare image: ", $cmp->errstr;
684 my $im = Imager->new(xsize => 100, ysize => 100);
685 ok($im, "make test image")
686 or diag "make test image: ", Imager->errstr;
687 $im or skip "no test image", 3;
688 my $fill = Imager::Fill->new(image => $tx, yoff => 10);
689 ok($fill, "make xoff=10 image fill")
690 or diag "make fill: ", Imager->errstr;
691 $fill or skip "no fill", 2;
692 ok($im->box(fill => $fill), "fill test image")
693 or diag "fill test image: ", $im->errstr;
694 is_image($im, $cmp, "check test image");
695 }
696
668697 sub color_close {
669698 my ($c1, $c2) = @_;
670699
00 #!perl -w
11 use strict;
2 use Test::More tests => 244;
2 use Test::More tests => 256;
33 use Imager ':all';
44 use Imager::Test qw(is_color3 is_image);
55 use constant PI => 3.14159265358979;
296296 }
297297 }
298298
299 {
300 my $empty = Imager->new;
301 ok(!$empty->box(), "can't draw box to empty image");
302 is($empty->errstr, "box: empty input image", "check error message");
303 ok(!$empty->arc(), "can't draw arc to empty image");
304 is($empty->errstr, "arc: empty input image", "check error message");
305 ok(!$empty->line(x1 => 0, y1 => 0, x2 => 10, y2 => 0),
306 "can't draw line to empty image");
307 is($empty->errstr, "line: empty input image", "check error message");
308 ok(!$empty->polyline(points => [ [ 0, 0 ], [ 10, 0 ] ]),
309 "can't draw polyline to empty image");
310 is($empty->errstr, "polyline: empty input image", "check error message");
311 ok(!$empty->polygon(points => [ [ 0, 0 ], [ 10, 0 ], [ 0, 10 ] ]),
312 "can't draw polygon to empty image");
313 is($empty->errstr, "polygon: empty input image", "check error message");
314 ok(!$empty->flood_fill(x => 0, y => 0), "can't flood fill to empty image");
315 is($empty->errstr, "flood_fill: empty input image", "check error message");
316 }
317
299318
300319 malloc_state();
301320
00 #!perl -w
11 use strict;
22 use Imager;
3 use Test::More tests => 10;
3 use Test::More tests => 14;
44
55 unshift @INC, "t";
66
3939 or skip("Failed to load", 1);
4040 ok($good->isa("GoodTestFont"), "and it's the right type");
4141 }
42
43
44 use Imager::Font::Test;
45
46 # check string() and align_string() handle an empty image
47 {
48 my $font = Imager::Font::Test->new;
49 my $empty = Imager->new;
50 ok(!$empty->string(text => "foo", x => 0, y => 10, size => 10, font => $font),
51 "can't draw text on an empty image");
52 is($empty->errstr, "string: empty input image",
53 "check error message");
54 ok(!$empty->align_string(text => "foo", x => 0, y => 10, size => 10, font => $font),
55 "can't draw text on an empty image");
56 is($empty->errstr, "align_string: empty input image",
57 "check error message");
58 }
3434 my $ttraw = Imager::i_tt_new($fontname);
3535 ok($ttraw, "create font");
3636
37 my @bbox = i_tt_bbox($ttraw,50.0,'XMCLH',6,0);
37 my @bbox = i_tt_bbox($ttraw,50.0,'XMCLH',0);
3838 is(@bbox, 8, "bounding box");
3939 print "#bbox: ($bbox[0], $bbox[1]) - ($bbox[2], $bbox[3])\n";
4040
7676 my $text = pack("C*", 0x41, 0xE2, 0x80, 0x90, 0x41);
7777 my $alttext = "A-A";
7878
79 my @utf8box = i_tt_bbox($ttraw, 50.0, $text, length($text), 1);
79 my @utf8box = i_tt_bbox($ttraw, 50.0, $text, 1);
8080 is(@utf8box, 8, "utf8 bbox element count");
81 my @base = i_tt_bbox($ttraw, 50.0, $alttext, length($alttext), 0);
81 my @base = i_tt_bbox($ttraw, 50.0, $alttext, 0);
8282 is(@base, 8, "alt bbox element count");
8383 my $maxdiff = $fontname eq $deffont ? 0 : $base[2] / 3;
8484 print "# (@utf8box vs @base)\n";
105105 "draw UTF8");
106106 ok(i_tt_cp($ttraw, $backgr, 350, 80, 0, 14, $text, 0, 1, 0),
107107 "cp UTF8");
108 @utf8box = i_tt_bbox($ttraw, 50.0, $text, length($text), 0);
108 @utf8box = i_tt_bbox($ttraw, 50.0, $text, 0);
109109 is(@utf8box, 8, "native utf8 bbox element count");
110110 ok(abs($utf8box[2] - $base[2]) <= $maxdiff,
111111 "compare box sizes native $utf8box[2] vs $base[2] (maxerror $maxdiff)");
0 #!perl -w
1 use strict;
2 use Imager::Test qw(std_font_tests std_font_test_count);
3 use Imager::Font;
4 use Test::More;
5
6 $Imager::formats{tt}
7 or plan skip_all => "No tt available";
8
9 Imager->open_log(log => "testout/t37std.log");
10
11 plan tests => std_font_test_count();
12
13 my $font = Imager::Font->new(file => "fontfiles/dodge.ttf",
14 type => "tt");
15 my $name_font =
16 Imager::Font->new(file => "fontfiles/ImUgly.ttf",
17 type => "tt");
18
19 SKIP:
20 {
21 $font
22 or skip "Cannot load font", std_font_test_count();
23 std_font_tests
24 ({
25 font => $font,
26 has_chars => [ 1, 1, 1 ],
27 glyph_name_font => $name_font,
28 glyph_names => [ qw(A uni2010 A) ],
29 });
30 }
31
32 Imager->close_log;
102102 { # error handling - NULL image
103103 my $im = Imager->new;
104104 ok(!$im->scale(scalefactor => 0.5), "try to scale empty image");
105 is($im->errstr, "empty input image", "check error message");
105 is($im->errstr, "scale: empty input image", "check error message");
106106
107107 # scaleX/scaleY
108108 ok(!$im->scaleX(scalefactor => 0.5), "try to scaleX empty image");
109 is($im->errstr, "empty input image", "check error message");
109 is($im->errstr, "scaleX: empty input image", "check error message");
110110 ok(!$im->scaleY(scalefactor => 0.5), "try to scaleY empty image");
111 is($im->errstr, "empty input image", "check error message");
111 is($im->errstr, "scaleY: empty input image", "check error message");
112112 }
113113
114114 { # invalid qtype value
55 eval "use Affix::Infix2Postfix; 1;"
66 or plan skip_all => "No Affix::Infix2Postfix";
77
8 plan tests => 6;
8 plan tests => 8;
99
1010 #$Imager::DEBUG=1;
1111
4646 }
4747 }
4848
49
49 {
50 my $empty = Imager->new;
51 ok(!$empty->transform(xexpr => "x", yexpr => "y"),
52 "fail to transform an empty image");
53 is($empty->errstr, "transform: empty input image",
54 "check error message");
55 }
00 #!perl -w
11 use strict;
2 use Test::More tests => 38;
2 use Test::More tests => 40;
33 BEGIN { use_ok('Imager'); }
44 use Imager::Test qw(is_color3);
55
142142 0 0 getp1 sat 255 * 0.01 + 0 0 rgb
143143 EOS
144144
145
146 {
147 my $empty = Imager->new;
148 my $good = Imager->new(xsize => 1, ysize => 1);
149 ok(!Imager::transform2({ rpnexpr => "x y getp1" }, $good, $empty),
150 "can't transform an empty image");
151 is(Imager->errstr, "transform2: empty input image (input image 2)",
152 "check error message");
153 }
154
145155 use Imager::Transform;
146156
147157 # some simple tests
00 #!perl -w
11 use strict;
22 use Imager qw(:handy);
3 use Test::More tests => 116;
3 use Test::More tests => 122;
44
55 -d "testout" or mkdir "testout";
66
423423 is_image($diff2, $cmp2, "difference() - check image with mindist 1.1 - large samples");
424424 }
425425
426 {
427 my $empty = Imager->new;
428 ok(!$empty->filter(type => "hardinvert"), "can't filter an empty image");
429 is($empty->errstr, "filter: empty input image",
430 "check error message");
431 ok(!$empty->difference(other => $imbase), "can't difference empty image");
432 is($empty->errstr, "difference: empty input image",
433 "check error message");
434 ok(!$imbase->difference(other => $empty),
435 "can't difference against empty image");
436 is($imbase->errstr, "difference: empty input image (other image)",
437 "check error message");
438 }
439
426440 sub test {
427441 my ($in, $params, $out) = @_;
428442
00 #!perl -w
11 use strict;
22 use Imager qw(:handy);
3 use Test::More tests => 114;
3 use Test::More tests => 120;
44 use Imager::Test qw(is_image is_imaged);
55
66 -d "testout" or mkdir "testout";
238238 }
239239 }
240240
241 {
242 my $empty = Imager->new;
243 my $good = Imager->new(xsize => 1, ysize => 1);
244 ok(!$empty->compose(src => $good), "can't compose to empty image");
245 is($empty->errstr, "compose: empty input image",
246 "check error message");
247 ok(!$good->compose(src => $empty), "can't compose from empty image");
248 is($good->errstr, "compose: empty input image (for src)",
249 "check error message");
250 ok(!$good->compose(src => $good, mask => $empty),
251 "can't compose with empty mask");
252 is($good->errstr, "compose: empty input image (for mask)",
253 "check error message");
254 }
255
241256 unless ($ENV{IMAGER_KEEP_FILES}) {
242257 unlink @files;
243258 }
3333 # bad image error
3434 my $im = Imager->new;
3535 ok(!Imager->combine(src => [ $im ]), "empty image");
36 is(Imager->errstr, "empty input image", "check message");
36 is(Imager->errstr, "combine: empty input image (src->[0])",
37 "check message");
3738 }
3839
3940 {
00 #!perl -w
11 use strict;
2 use Test::More tests => 87;
2 use Test::More tests => 95;
33 use Imager;
44 use Imager::Test qw(is_color3 is_image is_imaged test_image_double test_image isnt_image is_image_similar);
55
2020 my $diff = Imager::i_img_diff($img->{IMG}, $nimg->{IMG});
2121 is_image($img, $nimg, "copy matches source");
2222
23 {
24 my $empty = Imager->new;
25 ok(!$empty->copy, "fail to copy an empty image");
26 is($empty->errstr, "copy: empty input image", "check error message");
27 }
28
2329 # test if ->flip(dir=>'h')->flip(dir=>'h') doesn't alter the image
2430 $nimg->flip(dir=>"h")->flip(dir=>"h");
2531 is_image($nimg, $img, "double horiz flipped matches original");
3238 # test if ->flip(dir=>'h')->flip(dir=>'v') is same as ->flip(dir=>'hv')
3339 $nimg->flip(dir=>"v")->flip(dir=>"h")->flip(dir=>"hv");;
3440 is_image($img, $nimg, "check flip with hv matches flip v then flip h");
41
42 {
43 my $empty = Imager->new;
44 ok(!$empty->flip(dir => "v"), "fail to flip an empty image");
45 is($empty->errstr, "flip: empty input image", "check error message");
46 }
3547
3648 {
3749 my $imsrc = test_image_double;
146158
147159 $trimg->write(file=>"testout/t64_trans_back.ppm")
148160 or print "# Cannot save: ",$trimg->errstr,"\n";
161
162 {
163 my $empty = Imager->new;
164 ok(!$empty->matrix_transform(matrix => [ 1, 0, 0,
165 0, 1, 0,
166 0, 0, 1 ]),
167 "can't transform an empty image");
168 is($empty->errstr, "matrix_transform: empty input image",
169 "check error message");
170 }
149171
150172 sub rot_test {
151173 my ($src, $degrees, $count) = @_;
246268 is($deg->getwidth, 150, "check degrees => 270 width");
247269 is($deg->getheight, 150, "check degrees => 270 height");
248270 ok($deg->write(file => "testout/t64rotdeg270.ppm"), "save it");
249 # deg->write(file => "testout/t64rotright270.ppm");
271 $right->write(file => "testout/t64rotright270.ppm");
250272 is_image($deg, $right, "check right and degrees result the same");
251273 #$deg = $deg->convert(preset => "addalpha");
252274 # $right = $right->convert(preset => "addalpha");
253275 # my $diff = $right->difference(other => $deg, mindist => 1);
254276 # $diff->write(file => "testout/t64rotdiff.png");
255277 }
278
279 {
280 my $empty = Imager->new;
281 ok(!$empty->rotate(degrees => 90), "can't rotate an empty image");
282 is($empty->errstr, "rotate: empty input image",
283 "check error message");
284 }
00 #!perl -w
11 use strict;
2 use Test::More tests => 64;
2 use Test::More tests => 66;
33 use Imager;
44 use Imager::Test qw(test_image);
55
181181 "outside of image" );
182182 cmp_ok($src->errstr, '=~', qr/outside of the image/, "and message");
183183 }
184
185 {
186 my $empty = Imager->new;
187 ok(!$empty->crop(left => 10), "can't crop an empty image");
188 is($empty->errstr, "crop: empty input image", "check message");
189 }
00 #!perl -w
11 use strict;
2 use Test::More tests => 54;
2 use Test::More tests => 60;
33
44 use Imager;
55 use Imager::Test qw(is_image);
2323
2424 ok($img->write(type=>'pnm',file=>'testout/t66.ppm'), "save it")
2525 or print "# ", $img->errstr, "\n";
26
27 {
28 my $empty = Imager->new;
29 ok(!$empty->paste(src => $nimg), "paste into empty image");
30 is($empty->errstr, "paste: empty input image",
31 "check error message");
32
33 ok(!$img->paste(src => $empty), "paste from empty image");
34 is($img->errstr, "paste: empty input image (for src)",
35 "check error message");
36
37 ok(!$img->paste(), "no source image");
38 is($img->errstr, "no source image");
39 }
2640
2741 # more stringent tests
2842 {
00 #!perl -w
11 use strict;
22 use Imager qw(:all :handy);
3 use Test::More tests => 29;
3 use Test::More tests => 31;
44 use Imager::Test qw(test_colorf_gpix is_fcolor1 is_fcolor3);
55
66 -d "testout" or mkdir "testout";
148148 is($im->errstr, "convert: invalid matrix: element 0 is not an array ref",
149149 "check the error message");
150150 }
151
152 {
153 my $empty = Imager->new;
154 ok(!$empty->convert(preset => "addalpha"), "can't convert an empty image");
155 is($empty->errstr, "convert: empty input image", "check error message");
156 }
0 #!perl -w
1 use strict;
2 use Test::More tests => 8;
3
04 -d "testout" or mkdir "testout";
15
26 Imager::init("log"=>'testout/t68map.log');
37
48 use Imager qw(:all :handy);
59
6 print "1..5\n";
7
810 my $imbase = Imager::ImgRaw::new(200,300,3);
911
1012
11 @map1 = map { int($_/2) } 0..255;
12 @map2 = map { 255-int($_/2) } 0..255;
13 @map3 = 0..255;
14 @maps = 0..24;
15 @mapl = 0..400;
13 my @map1 = map { int($_/2) } 0..255;
14 my @map2 = map { 255-int($_/2) } 0..255;
15 my @map3 = 0..255;
16 my @maps = 0..24;
17 my @mapl = 0..400;
1618
17 $tst = 1;
19 my $tst = 1;
1820
19 i_map($imbase, [ [], [], \@map1 ]);
20 print "ok ".$tst++."\n";
21 i_map($imbase, [ \@map1, \@map1, \@map1 ]);
21 ok(i_map($imbase, [ [], [], \@map1 ]), "map1 in ch 3");
22 ok(i_map($imbase, [ \@map1, \@map1, \@map1 ]), "map1 in ch1-3");
2223
23 print "ok ".$tst++."\n";
24 i_map($imbase, [ \@map1, \@map2, \@map3 ]);
24 ok(i_map($imbase, [ \@map1, \@map2, \@map3 ]), "map1-3 in ch 1-3");
2525
26 print "ok ".$tst++."\n";
27 i_map($imbase, [ \@maps, \@mapl, \@map3 ]);
26 ok(i_map($imbase, [ \@maps, \@mapl, \@map3 ]), "incomplete maps");
2827
2928 # test the highlevel interface
3029 # currently this requires visual inspection of the output files
3130
31 SKIP: {
32 my $im = Imager->new;
33 $im->read(file=>'testimg/scale.ppm')
34 or skip "Cannot load test image testimg/scale.ppm", 2;
3235
33 my $im = Imager->new;
34 if ($im->read(file=>'testimg/scale.ppm')) {
35 print( ( $im->map(red=>\@map1, green=>\@map2, blue=>\@map3) ? "ok " : "not ok ").$tst++."\n" );
36 print( ( $im->map(maps=>[\@map1, [], \@map2]) ? "ok " : "not ok "). $tst++."\n");
36 ok( $im->map(red=>\@map1, green=>\@map2, blue=>\@map3),
37 "test OO interface (maps by color)");
38 ok( $im->map(maps=>[\@map1, [], \@map2]),
39 "test OO interface (maps by maps)");
3740 }
38 else {
39 die "could not load testout/scale.ppm\n";
41
42 {
43 my $empty = Imager->new;
44 ok(!$empty->map(maps => [ \@map1, \@map2, \@map3 ]),
45 "can't map an empty image");
46 is($empty->errstr, "map: empty input image", "check error message");
4047 }
7474 { # check empty image errors
7575 my $empty = Imager->new;
7676 ok(!$empty->rubthrough(src => $oosrc), "check empty target");
77 is($empty->errstr, 'empty input image', "check error message");
77 is($empty->errstr, 'rubthrough: empty input image', "check error message");
7878 ok(!$oogtarg->rubthrough(src=>$empty), "check empty source");
79 is($oogtarg->errstr, 'empty input image for src',
79 is($oogtarg->errstr, 'rubthrough: empty input image (for src)',
8080 "check error message");
8181 }
8282
1818
1919 -d "testout" or mkdir "testout";
2020
21 plan tests => 115;
21 print STDERR "Inline version $Inline::VERSION\n";
22
23 plan tests => 117;
2224 require Inline;
2325 Inline->import(with => 'Imager');
2426 Inline->import("FORCE"); # force rebuild
409411 return i_psampf(im, 0, 1, 0, samps, NULL, chan_count);
410412 }
411413
414 int
415 test_mutex() {
416 i_mutex_t m;
417
418 m = i_mutex_new();
419 i_mutex_lock(m);
420 i_mutex_unlock(m);
421 i_mutex_destroy(m);
422
423 return 1;
424 }
425
426 int
427 test_slots() {
428 im_slot_t slot = im_context_slot_new(NULL);
429
430 if (im_context_slot_get(aIMCTX, slot)) {
431 fprintf(stderr, "slots should default to NULL\n");
432 return 0;
433 }
434 if (!im_context_slot_set(aIMCTX, slot, &slot)) {
435 fprintf(stderr, "set slot failed\n");
436 return 0;
437 }
438
439 if (im_context_slot_get(aIMCTX, slot) != &slot) {
440 fprintf(stderr, "get slot didn't match\n");
441 return 0;
442 }
443
444 return 1;
445 }
446
412447 EOS
413448
414449 my $im = Imager->new(xsize=>50, ysize=>50);
625660 is($im->type, "paletted", "make sure we kept the image type");
626661 }
627662
663 ok(test_mutex(), "call mutex APIs");
664
665 ok(test_slots(), "call slot APIs");
666
628667 sub _get_error {
629668 my @errors = Imager::i_errors();
630669 return join(": ", map $_->[0], @errors);
0 #!perl -w
1 #
2 # this tests both the Inline interface and the API with IMAGER_NO_CONTEXT
3 use strict;
4 use Test::More;
5 use Imager::Test qw(is_color3 is_color4);
6 eval "require Inline::C;";
7 plan skip_all => "Inline required for testing API" if $@;
8
9 eval "require Parse::RecDescent;";
10 plan skip_all => "Could not load Parse::RecDescent" if $@;
11
12 use Cwd 'getcwd';
13 plan skip_all => "Inline won't work in directories with spaces"
14 if getcwd() =~ / /;
15
16 plan skip_all => "perl 5.005_04, 5.005_05 too buggy"
17 if $] =~ /^5\.005_0[45]$/;
18
19 -d "testout" or mkdir "testout";
20
21 plan tests => 5;
22 require Inline;
23 Inline->import(C => Config => AUTO_INCLUDE => "#define IMAGER_NO_CONTEXT\n");
24 Inline->import(with => 'Imager');
25 Inline->import("FORCE"); # force rebuild
26 #Inline->import(C => Config => OPTIMIZE => "-g");
27
28 Inline->bind(C => <<'EOS');
29 #include <math.h>
30
31 Imager make_10x10() {
32 dIMCTX;
33 i_img *im = i_img_8_new(10, 10, 3);
34 i_color c;
35 c.channel[0] = c.channel[1] = c.channel[2] = 255;
36 i_box_filled(im, 0, 0, im->xsize-1, im->ysize-1, &c);
37
38 return im;
39 }
40
41 void error_dIMCTX() {
42 dIMCTX;
43 im_clear_error(aIMCTX);
44 im_push_error(aIMCTX, 0, "test1");
45 im_push_errorf(aIMCTX, 0, "test%d", 2);
46
47 im_log((aIMCTX, 0, "test logging\n"));
48 }
49
50 void error_dIMCTXim(Imager im) {
51 dIMCTXim(im);
52 im_clear_error(aIMCTX);
53 im_push_error(aIMCTX, 0, "test1");
54 }
55
56 int context_refs() {
57 dIMCTX;
58
59 im_context_refinc(aIMCTX, "context_refs");
60 im_context_refdec(aIMCTX, "context_refs");
61
62 return 1;
63 }
64
65 EOS
66
67 Imager->open_log(log => "testout/t84inlinectx.log");
68
69 my $im2 = make_10x10();
70 ok($im2, "make an image");
71 is_color3($im2->getpixel(x => 0, y => 0), 255, 255, 255,
72 "check the colors");
73 error_dIMCTX();
74 is(_get_error(), "test2: test1", "check dIMCTX");
75
76 my $im = Imager->new(xsize => 1, ysize => 1);
77 error_dIMCTXim($im);
78 is(_get_error(), "test1", "check dIMCTXim");
79
80 ok(context_refs(), "check refcount functions");
81
82 Imager->close_log();
83
84 unless ($ENV{IMAGER_KEEP_FILES}) {
85 unlink "testout/t84inlinectx.log";
86 }
87
88 sub _get_error {
89 my @errors = Imager::i_errors();
90 return join(": ", map $_->[0], @errors);
91 }
00 #!perl -w
11 use strict;
2 use Test::More tests => 16;
2 use Test::More tests => 22;
33
44 use Imager;
55
6868 $im_g->getcolorusagehash,
6969 'color usage hash (grey)');
7070 }
71
72 {
73 my $empty = Imager->new;
74 is($empty->getcolorcount, undef, "can't getcolorcount an empty image");
75 is($empty->errstr, "getcolorcount: empty input image",
76 "check error message");
77 is($empty->getcolorusagehash, undef, "can't getcolorusagehash an empty image");
78 is($empty->errstr, "getcolorusagehash: empty input image",
79 "check error message");
80 is($empty->getcolorusage, undef, "can't getcolorusage an empty image");
81 is($empty->errstr, "getcolorusage: empty input image",
82 "check error message");
83 }
1717 use Test::More;
1818
1919 $Config{useithreads}
20 or plan skip_all => "can't test Imager's lack of threads support with no threads";
20 or plan skip_all => "can't test Imager's threads support with no threads";
2121 $] > 5.008007
22 or plan skip_all => "require a perl with CLONE_SKIP to test Imager's lack of threads support";
22 or plan skip_all => "require a perl with CLONE_SKIP to test Imager's threads support";
2323 $loaded_threads
2424 or plan skip_all => "couldn't load threads";
2525
3131 $Test::More::VERSION =~ /^2\.00_/
3232 and plan skip_all => "threads are hosed in 2.00_06 and presumably all 2.00_*";
3333
34 plan tests => 11;
34 plan tests => 13;
3535
3636 my $thread = threads->create(sub { 1; });
3737 ok($thread->join, "join first thread");
3838
39 # these are all, or contain, XS allocated objects, if we don't
40 # probably handle CLONE requests, or provide a CLONE_SKIP, we'll
41 # probably see a double-free, one from the thread, and the other from
42 # the main line of control.
39 # these are all, or contain, XS allocated objects, if we don't handle
40 # CLONE requests, or provide a CLONE_SKIP, we'll probably see a
41 # double-free, one from the thread, and the other from the main line
42 # of control.
43 #
4344 # So make one of each
4445
4546 my $im = Imager->new(xsize => 10, ysize => 10);
8081 (
8182 sub {
8283 ok(!UNIVERSAL::isa($im->{IMG}, "Imager::ImgRaw"),
83 "the low level image object should be undef");
84 "the low level image object should become unblessed");
85 ok(!$im->_valid_image, "image no longer considered valid");
86 is($im->errstr, "images do not cross threads",
87 "check error message");
8488 1;
8589 }
8690 );
88 off_t T_OFF_T
99
1010 Imager::Internal::Hlines T_PTROBJ
11
12 Imager::Context T_PTROBJ
1113
1214 #############################################################################
1315 INPUT
00 # typemaps for perl before 5.8
11 # STRLEN isn't in the default typemap in older perls
22 STRLEN T_UV
3 PerlIO * T_INOUT
34
45 #############################################################################
56 INPUT