1/* 2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3% % 4% % 5% % 6% M M V V GGGG % 7% MM MM V V G % 8% M M M V V G GG % 9% M M V V G G % 10% M M V GGG % 11% % 12% % 13% Read/Write Magick Vector Graphics Metafiles. % 14% % 15% Software Design % 16% Cristy % 17% April 2000 % 18% % 19% % 20% Copyright 1999-2016 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" 43#include "MagickCore/artifact.h" 44#include "MagickCore/blob.h" 45#include "MagickCore/blob-private.h" 46#include "MagickCore/draw.h" 47#include "MagickCore/exception.h" 48#include "MagickCore/exception-private.h" 49#include "MagickCore/image.h" 50#include "MagickCore/image-private.h" 51#include "MagickCore/list.h" 52#include "MagickCore/magick.h" 53#include "MagickCore/memory_.h" 54#include "MagickCore/module.h" 55#include "MagickCore/property.h" 56#include "MagickCore/quantum-private.h" 57#include "MagickCore/static.h" 58#include "MagickCore/string_.h" 59 60/* 61 Forward declarations. 62*/ 63static MagickBooleanType 64 WriteMVGImage(const ImageInfo *,Image *,ExceptionInfo *); 65 66/* 67%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 68% % 69% % 70% % 71% I s M V G % 72% % 73% % 74% % 75%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 76% 77% IsMVG() returns MagickTrue if the image format type, identified by the 78% magick string, is MVG. 79% 80% The format of the IsMVG method is: 81% 82% MagickBooleanType IsMVG(const unsigned char *magick,const size_t length) 83% 84% A description of each parameter follows: 85% 86% o magick: compare image format pattern against these bytes. 87% 88% o length: Specifies the length of the magick string. 89% 90*/ 91static MagickBooleanType IsMVG(const unsigned char *magick,const size_t length) 92{ 93 if (length < 20) 94 return(MagickFalse); 95 if (LocaleNCompare((const char *) magick,"push graphic-context",20) == 0) 96 return(MagickTrue); 97 return(MagickFalse); 98} 99 100/* 101%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 102% % 103% % 104% % 105% R e a d M V G I m a g e % 106% % 107% % 108% % 109%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 110% 111% ReadMVGImage creates a gradient image and initializes it to 112% the X server color range as specified by the filename. It allocates the 113% memory necessary for the new Image structure and returns a pointer to the 114% new image. 115% 116% The format of the ReadMVGImage method is: 117% 118% Image *ReadMVGImage(const ImageInfo *image_info,ExceptionInfo *exception) 119% 120% A description of each parameter follows: 121% 122% o image_info: the image info. 123% 124% o exception: return any errors or warnings in this structure. 125% 126*/ 127static Image *ReadMVGImage(const ImageInfo *image_info,ExceptionInfo *exception) 128{ 129#define BoundingBox "viewbox" 130 131 DrawInfo 132 *draw_info; 133 134 Image 135 *image; 136 137 MagickBooleanType 138 status; 139 140 /* 141 Open image. 142 */ 143 assert(image_info != (const ImageInfo *) NULL); 144 assert(image_info->signature == MagickCoreSignature); 145 if (image_info->debug != MagickFalse) 146 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", 147 image_info->filename); 148 assert(exception != (ExceptionInfo *) NULL); 149 assert(exception->signature == MagickCoreSignature); 150 image=AcquireImage(image_info,exception); 151 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); 152 if (status == MagickFalse) 153 { 154 image=DestroyImageList(image); 155 return((Image *) NULL); 156 } 157 if ((image->columns == 0) || (image->rows == 0)) 158 { 159 char 160 primitive[MagickPathExtent]; 161 162 register char 163 *p; 164 165 SegmentInfo 166 bounds; 167 168 /* 169 Determine size of image canvas. 170 */ 171 while (ReadBlobString(image,primitive) != (char *) NULL) 172 { 173 for (p=primitive; (*p == ' ') || (*p == '\t'); p++) ; 174 if (LocaleNCompare(BoundingBox,p,strlen(BoundingBox)) != 0) 175 continue; 176 (void) sscanf(p,"viewbox %lf %lf %lf %lf",&bounds.x1,&bounds.y1, 177 &bounds.x2,&bounds.y2); 178 image->columns=(size_t) floor((bounds.x2-bounds.x1)+0.5); 179 image->rows=(size_t) floor((bounds.y2-bounds.y1)+0.5); 180 break; 181 } 182 } 183 if ((image->columns == 0) || (image->rows == 0)) 184 ThrowReaderException(OptionError,"MustSpecifyImageSize"); 185 draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL); 186 draw_info->affine.sx=image->resolution.x == 0.0 ? 1.0 : image->resolution.x/ 187 DefaultResolution; 188 draw_info->affine.sy=image->resolution.y == 0.0 ? 1.0 : image->resolution.y/ 189 DefaultResolution; 190 image->columns=(size_t) (draw_info->affine.sx*image->columns); 191 image->rows=(size_t) (draw_info->affine.sy*image->rows); 192 status=SetImageExtent(image,image->columns,image->rows,exception); 193 if (status == MagickFalse) 194 return(DestroyImageList(image)); 195 if (SetImageBackgroundColor(image,exception) == MagickFalse) 196 { 197 image=DestroyImageList(image); 198 return((Image *) NULL); 199 } 200 /* 201 Render drawing. 202 */ 203 if (GetBlobStreamData(image) == (unsigned char *) NULL) 204 draw_info->primitive=FileToString(image->filename,~0UL,exception); 205 else 206 { 207 draw_info->primitive=(char *) AcquireMagickMemory(GetBlobSize(image)+1); 208 if (draw_info->primitive != (char *) NULL) 209 { 210 CopyMagickMemory(draw_info->primitive,GetBlobStreamData(image), 211 GetBlobSize(image)); 212 draw_info->primitive[GetBlobSize(image)]='\0'; 213 } 214 } 215 if (draw_info->primitive == (char *) NULL) 216 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 217 (void) DrawImage(image,draw_info,exception); 218 draw_info=DestroyDrawInfo(draw_info); 219 (void) CloseBlob(image); 220 return(GetFirstImageInList(image)); 221} 222 223/* 224%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 225% % 226% % 227% % 228% R e g i s t e r M V G I m a g e % 229% % 230% % 231% % 232%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 233% 234% RegisterMVGImage() adds properties for the MVG image format 235% to the list of supported formats. The properties include the image format 236% tag, a method to read and/or write the format, whether the format 237% supports the saving of more than one frame to the same file or blob, 238% whether the format supports native in-memory I/O, and a brief 239% description of the format. 240% 241% The format of the RegisterMVGImage method is: 242% 243% size_t RegisterMVGImage(void) 244% 245*/ 246ModuleExport size_t RegisterMVGImage(void) 247{ 248 MagickInfo 249 *entry; 250 251 entry=AcquireMagickInfo("MVG","MVG","Magick Vector Graphics"); 252 entry->decoder=(DecodeImageHandler *) ReadMVGImage; 253 entry->encoder=(EncodeImageHandler *) WriteMVGImage; 254 entry->magick=(IsImageFormatHandler *) IsMVG; 255 entry->format_type=ImplicitFormatType; 256 entry->flags^=CoderAdjoinFlag; 257 entry->flags|=CoderSeekableStreamFlag; 258 (void) RegisterMagickInfo(entry); 259 return(MagickImageCoderSignature); 260} 261 262/* 263%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 264% % 265% % 266% % 267% U n r e g i s t e r M V G I m a g e % 268% % 269% % 270% % 271%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 272% 273% UnregisterMVGImage() removes format registrations made by the 274% MVG module from the list of supported formats. 275% 276% The format of the UnregisterMVGImage method is: 277% 278% UnregisterMVGImage(void) 279% 280*/ 281ModuleExport void UnregisterMVGImage(void) 282{ 283 (void) UnregisterMagickInfo("MVG"); 284} 285 286/* 287%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 288% % 289% % 290% % 291% W r i t e M V G I m a g e % 292% % 293% % 294% % 295%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 296% 297% WriteMVGImage() writes an image to a file in MVG image format. 298% 299% The format of the WriteMVGImage method is: 300% 301% MagickBooleanType WriteMVGImage(const ImageInfo *image_info, 302% Image *image,ExceptionInfo *exception) 303% 304% A description of each parameter follows. 305% 306% o image_info: the image info. 307% 308% o image: The image. 309% 310% o exception: return any errors or warnings in this structure. 311% 312*/ 313static MagickBooleanType WriteMVGImage(const ImageInfo *image_info,Image *image, 314 ExceptionInfo *exception) 315{ 316 const char 317 *value; 318 319 MagickBooleanType 320 status; 321 322 /* 323 Open output image file. 324 */ 325 assert(image_info != (const ImageInfo *) NULL); 326 assert(image_info->signature == MagickCoreSignature); 327 assert(image != (Image *) NULL); 328 assert(image->signature == MagickCoreSignature); 329 if (image->debug != MagickFalse) 330 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 331 value=GetImageArtifact(image,"MVG"); 332 if (value == (const char *) NULL) 333 ThrowWriterException(OptionError,"NoImageVectorGraphics"); 334 status=OpenBlob(image_info,image,WriteBlobMode,exception); 335 if (status == MagickFalse) 336 return(status); 337 (void) WriteBlob(image,strlen(value),(const unsigned char *) value); 338 (void) CloseBlob(image); 339 return(MagickTrue); 340} 341