blob: 87fc6c142bf4147df24ebcd6f1589bef0914781d [file] [log] [blame]
cristybd4fb6e2011-10-26 13:10:01 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% PPPP AAA N N GGGG OOO %
7% P P A A NN N G O O %
8% PPPP AAAAA N N N G GGG O O %
9% P M A A N NN G G O O %
10% P A A N N GGGG OOO %
11% %
12% %
13% Read Pango Markup Language Format %
14% %
15% Software Design %
16% John Cristy %
17% March 2012 %
18% %
19% %
20% Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization %
21% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% http://www.imagemagick.org/script/license.php %
27% %
28% Unless required by applicable law or agreed to in writing, software %
29% distributed under the License is distributed on an "AS IS" BASIS, %
30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31% See the License for the specific language governing permissions and %
32% limitations under the License. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37*/
38
39/*
40 Include declarations.
41*/
42#include "MagickCore/studio.h"
cristy884cbde2011-10-28 14:42:14 +000043#include "MagickCore/annotate.h"
cristybd4fb6e2011-10-26 13:10:01 +000044#include "MagickCore/blob.h"
45#include "MagickCore/blob-private.h"
cristy884cbde2011-10-28 14:42:14 +000046#include "MagickCore/composite-private.h"
47#include "MagickCore/draw.h"
48#include "MagickCore/draw-private.h"
cristybd4fb6e2011-10-26 13:10:01 +000049#include "MagickCore/exception.h"
50#include "MagickCore/exception-private.h"
51#include "MagickCore/image.h"
52#include "MagickCore/image-private.h"
53#include "MagickCore/list.h"
54#include "MagickCore/magick.h"
cristy884cbde2011-10-28 14:42:14 +000055#include "MagickCore/module.h"
cristybd4fb6e2011-10-26 13:10:01 +000056#include "MagickCore/memory_.h"
57#include "MagickCore/option.h"
58#include "MagickCore/pixel-accessor.h"
cristy884cbde2011-10-28 14:42:14 +000059#include "MagickCore/property.h"
cristybd4fb6e2011-10-26 13:10:01 +000060#include "MagickCore/quantum-private.h"
61#include "MagickCore/static.h"
62#include "MagickCore/string_.h"
cristy884cbde2011-10-28 14:42:14 +000063#if defined(MAGICKCORE_PANGOFT2_DELEGATE)
cristybd4fb6e2011-10-26 13:10:01 +000064#include <pango/pango.h>
cristy884cbde2011-10-28 14:42:14 +000065#include <pango/pangoft2.h>
cristybd4fb6e2011-10-26 13:10:01 +000066#endif
67
cristy884cbde2011-10-28 14:42:14 +000068#if defined(MAGICKCORE_PANGOFT2_DELEGATE)
cristybd4fb6e2011-10-26 13:10:01 +000069/*
70%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
71% %
72% %
73% %
cristy6c28ec02011-10-28 11:37:57 +000074% R e a d P A N G O I m a g e %
cristybd4fb6e2011-10-26 13:10:01 +000075% %
76% %
77% %
78%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
79%
80% ReadPANGOImage() reads an image in the Pango Markup Language Format.
81%
82% The format of the ReadPANGOImage method is:
83%
84% Image *ReadPANGOImage(const ImageInfo *image_info,
85% ExceptionInfo *exception)
86%
87% A description of each parameter follows:
88%
89% o image_info: the image info.
90%
91% o exception: return any errors or warnings in this structure.
92%
93*/
94static Image *ReadPANGOImage(const ImageInfo *image_info,
95 ExceptionInfo *exception)
96{
cristy884cbde2011-10-28 14:42:14 +000097 char
98 *caption,
99 *property;
100
101 DrawInfo
102 *draw_info;
103
104 FT_Bitmap
105 *canvas;
106
107 Image
108 *image;
109
cristy884cbde2011-10-28 14:42:14 +0000110 PangoContext
111 *context;
112
113 PangoFontDescription
114 *description;
115
116 PangoFontMap
117 *fontmap;
118
119 PangoLayout
120 *layout;
121
cristy6a851052011-10-28 17:21:10 +0000122 PangoRectangle
123 extent;
124
cristy884cbde2011-10-28 14:42:14 +0000125 PixelInfo
126 fill_color;
127
128 register Quantum
129 *q;
130
131 register unsigned char
132 *p;
133
134 ssize_t
135 y;
136
137 /*
138 Initialize Image structure.
139 */
140 assert(image_info != (const ImageInfo *) NULL);
141 assert(image_info->signature == MagickSignature);
142 if (image_info->debug != MagickFalse)
143 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
144 image_info->filename);
145 assert(exception != (ExceptionInfo *) NULL);
146 assert(exception->signature == MagickSignature);
147 image=AcquireImage(image_info,exception);
cristy884cbde2011-10-28 14:42:14 +0000148 (void) ResetImagePage(image,"0x0+0+0");
cristy884cbde2011-10-28 14:42:14 +0000149 /*
150 Get context.
151 */
152 fontmap=(PangoFontMap *) pango_ft2_font_map_new();
153 pango_ft2_font_map_set_resolution((PangoFT2FontMap *) fontmap,
cristy2a11bef2011-10-28 18:33:11 +0000154 image->resolution.x,image->resolution.y);
cristy884cbde2011-10-28 14:42:14 +0000155 pango_ft2_font_map_set_default_substitute((PangoFT2FontMap *) fontmap,NULL,
156 NULL,NULL);
157 context=pango_font_map_create_context(fontmap);
158 /*
cristy6a851052011-10-28 17:21:10 +0000159 Render caption.
160 */
161 layout=pango_layout_new(context);
cristy2a11bef2011-10-28 18:33:11 +0000162 draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL);
163 description=pango_font_description_from_string(draw_info->font ==
164 (char *) NULL ? "helvetica" : draw_info->font);
165 pango_font_description_set_size(description,PANGO_SCALE*
166 draw_info->pointsize);
cristy6a851052011-10-28 17:21:10 +0000167 pango_layout_set_font_description(layout,description);
168 pango_font_description_free(description);
169 property=InterpretImageProperties(image_info,image,image_info->filename,
170 exception);
171 (void) SetImageProperty(image,"caption",property,exception);
172 property=DestroyString(property);
173 caption=ConstantString(GetImageProperty(image,"caption",exception));
174 pango_layout_set_text(layout,caption,-1);
175 pango_layout_context_changed(layout);
cristy2a11bef2011-10-28 18:33:11 +0000176 if (image->columns != 0)
177 pango_layout_set_width(layout,(PANGO_SCALE*image->columns*
178 image->resolution.x+36.0)/72.0);
179 else
cristy6a851052011-10-28 17:21:10 +0000180 {
181 pango_layout_get_pixel_extents(layout,NULL,&extent);
182 image->columns=extent.x+extent.width;
183 }
cristy2a11bef2011-10-28 18:33:11 +0000184 if (image->rows != 0)
185 pango_layout_set_height(layout,(PANGO_SCALE*image->columns*
186 image->resolution.x+36.0)/72.0);
187 else
cristy6a851052011-10-28 17:21:10 +0000188 {
189 pango_layout_get_pixel_extents(layout,NULL,&extent);
190 image->rows=extent.y+extent.height;
191 }
192 /*
cristy884cbde2011-10-28 14:42:14 +0000193 Create canvas.
194 */
195 canvas=(FT_Bitmap *) AcquireMagickMemory(sizeof(*canvas));
196 if (canvas == (FT_Bitmap *) NULL)
cristy2a11bef2011-10-28 18:33:11 +0000197 {
198 draw_info=DestroyDrawInfo(draw_info);
199 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
200 }
cristy884cbde2011-10-28 14:42:14 +0000201 canvas->width=image->columns;
202 canvas->pitch=(canvas->width+3) & ~3;
203 canvas->rows=image->rows;
204 canvas->buffer=(unsigned char *) AcquireQuantumMemory(canvas->pitch,
205 canvas->rows*sizeof(*canvas->buffer));
206 if (canvas->buffer == (unsigned char *) NULL)
207 {
cristy2a11bef2011-10-28 18:33:11 +0000208 draw_info=DestroyDrawInfo(draw_info);
cristy884cbde2011-10-28 14:42:14 +0000209 canvas=(FT_Bitmap *) RelinquishMagickMemory(canvas);
210 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
211 }
212 canvas->num_grays=256;
213 canvas->pixel_mode=ft_pixel_mode_grays;
214 ResetMagickMemory(canvas->buffer,0x00,canvas->pitch*canvas->rows);
cristy884cbde2011-10-28 14:42:14 +0000215 pango_ft2_render_layout(canvas,layout,0,0);
216 /*
217 Convert caption to image.
218 */
cristy6a851052011-10-28 17:21:10 +0000219 if (SetImageBackgroundColor(image,exception) == MagickFalse)
220 {
cristy2a11bef2011-10-28 18:33:11 +0000221 draw_info=DestroyDrawInfo(draw_info);
cristy6a851052011-10-28 17:21:10 +0000222 canvas->buffer=(unsigned char *) RelinquishMagickMemory(canvas->buffer);
223 canvas=(FT_Bitmap *) RelinquishMagickMemory(canvas);
224 caption=DestroyString(caption);
225 image=DestroyImageList(image);
226 return((Image *) NULL);
227 }
cristy884cbde2011-10-28 14:42:14 +0000228 GetPixelInfo(image,&fill_color);
229 p=canvas->buffer;
230 for (y=0; y < (ssize_t) image->rows; y++)
231 {
232 register ssize_t
233 x;
234
235 q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
236 if (q == (Quantum *) NULL)
237 break;
238 for (x=0; x < (ssize_t) image->columns; x++)
239 {
240 MagickRealType
241 fill_opacity;
242
243 (void) GetFillColor(draw_info,x,y,&fill_color,exception);
244 fill_opacity=(*p)*fill_color.alpha/canvas->num_grays;
cristy79497822011-10-28 14:51:23 +0000245 if (draw_info->text_antialias == MagickFalse)
246 fill_opacity=fill_opacity >= 0.5 ? 1.0 : 0.0;
cristy884cbde2011-10-28 14:42:14 +0000247 CompositePixelOver(image,&fill_color,fill_opacity,q,
248 GetPixelAlpha(image,q),q);
249 p++;
250 q+=GetPixelChannels(image);
251 }
cristy6a851052011-10-28 17:21:10 +0000252 for ( ; x < (ssize_t) ((canvas->width+3) & ~3); x++)
253 p++;
cristy884cbde2011-10-28 14:42:14 +0000254 }
255 /*
256 Relinquish resources.
257 */
258 draw_info=DestroyDrawInfo(draw_info);
259 canvas->buffer=(unsigned char *) RelinquishMagickMemory(canvas->buffer);
260 canvas=(FT_Bitmap *) RelinquishMagickMemory(canvas);
261 caption=DestroyString(caption);
262 return(GetFirstImageInList(image));
cristybd4fb6e2011-10-26 13:10:01 +0000263}
264#endif
265
266/*
267%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
268% %
269% %
270% %
271% R e g i s t e r P A N G O I m a g e %
272% %
273% %
274% %
275%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
276%
277% RegisterPANGOImage() adds attributes for the Pango Markup Language format to
278% the list of supported formats. The attributes include the image format
279% tag, a method to read and/or write the format, whether the format
280% supports the saving of more than one frame to the same file or blob,
281% whether the format supports native in-memory I/O, and a brief
282% description of the format.
283%
284% The format of the RegisterPANGOImage method is:
285%
286% size_t RegisterPANGOImage(void)
287%
288*/
289ModuleExport size_t RegisterPANGOImage(void)
290{
291 MagickInfo
292 *entry;
293
294 entry=SetMagickInfo("PANGO");
cristy884cbde2011-10-28 14:42:14 +0000295#if defined(MAGICKCORE_PANGOFT2_DELEGATE)
cristybd4fb6e2011-10-26 13:10:01 +0000296 entry->decoder=(DecodeImageHandler *) ReadPANGOImage;
297#endif
298 entry->description=ConstantString("Pango Markup Language");
299 entry->adjoin=MagickFalse;
300 entry->module=ConstantString("PANGO");
301 (void) RegisterMagickInfo(entry);
302 return(MagickImageCoderSignature);
303}
304
305/*
306%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
307% %
308% %
309% %
310% U n r e g i s t e r P A N G O I m a g e %
311% %
312% %
313% %
314%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
315%
316% UnregisterPANGOImage() removes format registrations made by the Pango module
317% from the list of supported formats.
318%
319% The format of the UnregisterPANGOImage method is:
320%
321% UnregisterPANGOImage(void)
322%
323*/
324ModuleExport void UnregisterPANGOImage(void)
325{
326 (void) UnregisterMagickInfo("PANGO");
327}