/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % M a g i c k Q u e r y M u l t i l i n e F o n t M e t r i c s % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % MagickQueryMultilineFontMetrics() returns a 13 element array representing the % following font metrics: % % Element Description % ------------------------------------------------- % 0 character width % 1 character height % 2 ascender % 3 descender % 4 text width % 5 text height % 6 maximum horizontal advance % 7 bounding box: x1 % 8 bounding box: y1 % 9 bounding box: x2 % 10 bounding box: y2 % 11 origin: x % 12 origin: y % % This method is like MagickQueryFontMetrics() but it returns the maximum text % width and height for multiple lines of text. % % The format of the MagickQueryFontMetrics method is: % % double *MagickQueryMultilineFontMetrics(MagickWand *wand, % const DrawingWand *drawing_wand,const char *text) % % A description of each parameter follows: % % o wand: the Magick wand. % % o drawing_wand: the drawing wand. % % o text: the text. % */ WandExport double *MagickQueryMultilineFontMetrics(MagickWand *wand, const DrawingWand *drawing_wand,const char *text) { double *font_metrics; DrawInfo *draw_info; MagickBooleanType status; TypeMetric metrics; assert(wand != (MagickWand *) NULL); assert(wand->signature == WandSignature); if (wand->debug != MagickFalse) (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",wand->name); assert(drawing_wand != (const DrawingWand *) NULL); if (wand->images == (Image *) NULL) { (void) ThrowMagickException(wand->exception,GetMagickModule(),WandError, "ContainsNoImages","`%s'",wand->name); return((double *) NULL); } font_metrics=(double *) AcquireQuantumMemory(13UL,sizeof(*font_metrics)); if (font_metrics == (double *) NULL) return((double *) NULL); draw_info=PeekDrawingWand(drawing_wand); if (draw_info == (DrawInfo *) NULL) { font_metrics=(double *) RelinquishMagickMemory(font_metrics); return((double *) NULL); } (void) CloneString(&draw_info->text,text); (void) ResetMagickMemory(&metrics,0,sizeof(metrics)); status=GetMultilineTypeMetrics(wand->images,draw_info,&metrics, wand->exception); draw_info=DestroyDrawInfo(draw_info); if (status == MagickFalse) { font_metrics=(double *) RelinquishMagickMemory(font_metrics); return((double *) NULL); } font_metrics[0]=metrics.pixels_per_em.x; font_metrics[1]=metrics.pixels_per_em.y; font_metrics[2]=metrics.ascent; font_metrics[3]=metrics.descent; font_metrics[4]=metrics.width; font_metrics[5]=metrics.height; font_metrics[6]=metrics.max_advance; font_metrics[7]=metrics.bounds.x1; font_metrics[8]=metrics.bounds.y1; font_metrics[9]=metrics.bounds.x2; font_metrics[10]=metrics.bounds.y2; font_metrics[11]=metrics.origin.x; font_metrics[12]=metrics.origin.y; return(font_metrics); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d L A B E L I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadLABELImage() reads a LABEL image file and returns it. It % allocates the memory necessary for the new Image structure and returns a % pointer to the new image. % % The format of the ReadLABELImage method is: % % Image *ReadLABELImage(const ImageInfo *image_info, % ExceptionInfo *exception) % % A description of each parameter follows: % % o image_info: the image info. % % o exception: return any errors or warnings in this structure. % */ static Image *ReadLABELImage(const ImageInfo *image_info, ExceptionInfo *exception) { char geometry[MaxTextExtent], *property; const char *label; DrawInfo *draw_info; Image *image; MagickBooleanType status; TypeMetric metrics; size_t height, width; /* Initialize Image structure. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickSignature); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); image=AcquireImage(image_info); (void) ResetImagePage(image,"0x0+0+0"); property=InterpretImageProperties(image_info,image,image_info->filename); (void) SetImageProperty(image,"label",property); property=DestroyString(property); label=GetImageProperty(image,"label"); draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL); draw_info->text=ConstantString(label); if (((image->columns != 0) || (image->rows != 0)) && (image_info->pointsize == 0.0)) { /* Fit label to canvas size. */ status=GetMultilineTypeMetrics(image,draw_info,&metrics); for ( ; status != MagickFalse; draw_info->pointsize*=2.0) { width=(size_t) floor(metrics.width+draw_info->stroke_width+0.5); height=(size_t) floor(metrics.height+draw_info->stroke_width+0.5); if (((image->columns != 0) && (width > (image->columns+1))) || ((image->rows != 0) && (height > (image->rows+1)))) break; status=GetMultilineTypeMetrics(image,draw_info,&metrics); } for ( ; status != MagickFalse; draw_info->pointsize--) { width=(size_t) floor(metrics.width+draw_info->stroke_width+0.5); height=(size_t) floor(metrics.height+draw_info->stroke_width+0.5); if ((image->columns != 0) && (width <= (image->columns+1)) && ((image->rows == 0) || (height <= (image->rows+1)))) break; if ((image->rows != 0) && (height <= (image->rows+1)) && ((image->columns == 0) || (width <= (image->columns+1)))) break; if (draw_info->pointsize < 2.0) break; status=GetMultilineTypeMetrics(image,draw_info,&metrics); } } status=GetMultilineTypeMetrics(image,draw_info,&metrics); if (status == MagickFalse) { InheritException(exception,&image->exception); image=DestroyImageList(image); return((Image *) NULL); } if (image->columns == 0) image->columns=(size_t) (metrics.width+draw_info->stroke_width+1.5); if (image->columns == 0) image->columns=(size_t) (draw_info->pointsize+ draw_info->stroke_width+1.5); if (draw_info->gravity == UndefinedGravity) { (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g", -metrics.bounds.x1+draw_info->stroke_width/2.0,metrics.ascent+ draw_info->stroke_width/2.0); draw_info->geometry=AcquireString(geometry); } if (image->rows == 0) image->rows=(size_t) floor(metrics.height+draw_info->stroke_width+0.5); if (image->rows == 0) image->rows=(size_t) floor(draw_info->pointsize+draw_info->stroke_width+ 0.5); if (SetImageBackgroundColor(image) == MagickFalse) { InheritException(exception,&image->exception); image=DestroyImageList(image); return((Image *) NULL); } (void) AnnotateImage(image,draw_info); if (image_info->pointsize == 0.0) { char pointsize[MaxTextExtent]; (void) FormatLocaleString(pointsize,MaxTextExtent,"%.20g", draw_info->pointsize); (void) SetImageProperty(image,"label:pointsize",pointsize); } draw_info=DestroyDrawInfo(draw_info); return(GetFirstImageInList(image)); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d C A P T I O N I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadCAPTIONImage() reads a CAPTION image file and returns it. It % allocates the memory necessary for the new Image structure and returns a % pointer to the new image. % % The format of the ReadCAPTIONImage method is: % % Image *ReadCAPTIONImage(const ImageInfo *image_info, % ExceptionInfo *exception) % % A description of each parameter follows: % % o image_info: the image info. % % o exception: return any errors or warnings in this structure. % */ static Image *ReadCAPTIONImage(const ImageInfo *image_info, ExceptionInfo *exception) { char *caption, geometry[MaxTextExtent], *property; const char *gravity; DrawInfo *draw_info; Image *image; MagickBooleanType status; register long i; TypeMetric metrics; unsigned long height, width; /* Initialize Image structure. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickSignature); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); image=AcquireImage(image_info); if (image->columns == 0) ThrowReaderException(OptionError,"MustSpecifyImageSize"); (void) ResetImagePage(image,"0x0+0+0"); /* Format caption. */ property=InterpretImageProperties(image_info,image,image_info->filename); (void) SetImageProperty(image,"caption",property); property=DestroyString(property); caption=ConstantString(GetImageProperty(image,"caption")); draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL); draw_info->text=ConstantString(caption); gravity=GetImageOption(image_info,"gravity"); if (gravity != (char *) NULL) draw_info->gravity=(GravityType) ParseMagickOption(MagickGravityOptions, MagickFalse,gravity); if ((*caption != '\0') && (image->rows != 0) && (image_info->pointsize == 0.0)) { char *text; /* Scale text to fit bounding box. */ for ( ; ; ) { text=AcquireString(caption); i=FormatMagickCaption(image,draw_info,&metrics,&text); (void) CloneString(&draw_info->text,text); text=DestroyString(text); (void) FormatMagickString(geometry,MaxTextExtent,"%+g%+g", -metrics.bounds.x1,metrics.ascent); if (draw_info->gravity == UndefinedGravity) (void) CloneString(&draw_info->geometry,geometry); status=GetMultilineTypeMetrics(image,draw_info,&metrics); width=(unsigned long) floor(metrics.width+draw_info->stroke_width+0.5); height=(unsigned long) floor(metrics.height+draw_info->stroke_width+ 0.5); if ((width > (image->columns+1)) || (height > (image->rows+1))) break; draw_info->pointsize*=2.0; } draw_info->pointsize/=2.0; for ( ; ; ) { text=AcquireString(caption); i=FormatMagickCaption(image,draw_info,&metrics,&text); (void) CloneString(&draw_info->text,text); text=DestroyString(text); (void) FormatMagickString(geometry,MaxTextExtent,"%+g%+g", -metrics.bounds.x1,metrics.ascent); if (draw_info->gravity == UndefinedGravity) (void) CloneString(&draw_info->geometry,geometry); status=GetMultilineTypeMetrics(image,draw_info,&metrics); width=(unsigned long) floor(metrics.width+draw_info->stroke_width+0.5); height=(unsigned long) floor(metrics.height+draw_info->stroke_width+ 0.5); if ((width > (image->columns+1)) || (height > (image->rows+1))) break; draw_info->pointsize++; } draw_info->pointsize--; } i=FormatMagickCaption(image,draw_info,&metrics,&caption); if (image->rows == 0) image->rows=(unsigned long) ((i+1)*(metrics.ascent-metrics.descent+ draw_info->stroke_width)+0.5); if (image->rows == 0) image->rows=(unsigned long) ((i+1)*draw_info->pointsize+ draw_info->stroke_width+0.5); if (SetImageBackgroundColor(image) == MagickFalse) { InheritException(exception,&image->exception); image=DestroyImageList(image); return((Image *) NULL); } /* Draw caption. */ (void) CloneString(&draw_info->text,caption); status=GetMultilineTypeMetrics(image,draw_info,&metrics); if (draw_info->gravity != UndefinedGravity) image->page.x=(long) (metrics.bounds.x1-draw_info->stroke_width/2.0); else { (void) FormatMagickString(geometry,MaxTextExtent,"%+g%+g", -metrics.bounds.x1+draw_info->stroke_width/2.0,metrics.ascent+ draw_info->stroke_width/2.0); (void) CloneString(&draw_info->geometry,geometry); } (void) AnnotateImage(image,draw_info); draw_info=DestroyDrawInfo(draw_info); caption=DestroyString(caption); return(GetFirstImageInList(image)); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d C A P T I O N I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadCAPTIONImage() reads a CAPTION image file and returns it. It % allocates the memory necessary for the new Image structure and returns a % pointer to the new image. % % The format of the ReadCAPTIONImage method is: % % Image *ReadCAPTIONImage(const ImageInfo *image_info, % ExceptionInfo *exception) % % A description of each parameter follows: % % o image_info: the image info. % % o exception: return any errors or warnings in this structure. % */ static Image *ReadCAPTIONImage(const ImageInfo *image_info, ExceptionInfo *exception) { char *caption, geometry[MaxTextExtent], *property, *text; const char *gravity, *option; DrawInfo *draw_info; Image *image; MagickBooleanType split, status; register ssize_t i; size_t height, width; TypeMetric metrics; /* Initialize Image structure. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickSignature); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); image=AcquireImage(image_info); (void) ResetImagePage(image,"0x0+0+0"); /* Format caption. */ option=GetImageOption(image_info,"filename"); if (option == (const char *) NULL) property=InterpretImageProperties(image_info,image,image_info->filename); else if (LocaleNCompare(option,"caption:",8) == 0) property=InterpretImageProperties(image_info,image,option+8); else property=InterpretImageProperties(image_info,image,option); (void) SetImageProperty(image,"caption",property); property=DestroyString(property); caption=ConstantString(GetImageProperty(image,"caption")); draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL); (void) CloneString(&draw_info->text,caption); gravity=GetImageOption(image_info,"gravity"); if (gravity != (char *) NULL) draw_info->gravity=(GravityType) ParseCommandOption(MagickGravityOptions, MagickFalse,gravity); split=MagickFalse; status=MagickTrue; if (image->columns == 0) { text=AcquireString(caption); i=FormatMagickCaption(image,draw_info,split,&metrics,&text); (void) CloneString(&draw_info->text,text); text=DestroyString(text); (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g", -metrics.bounds.x1,metrics.ascent); if (draw_info->gravity == UndefinedGravity) (void) CloneString(&draw_info->geometry,geometry); status=GetMultilineTypeMetrics(image,draw_info,&metrics); width=(size_t) floor(metrics.width+draw_info->stroke_width+0.5); image->columns=width; } if (image->rows == 0) { split=MagickTrue; text=AcquireString(caption); i=FormatMagickCaption(image,draw_info,split,&metrics,&text); (void) CloneString(&draw_info->text,text); text=DestroyString(text); (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g", -metrics.bounds.x1,metrics.ascent); if (draw_info->gravity == UndefinedGravity) (void) CloneString(&draw_info->geometry,geometry); status=GetMultilineTypeMetrics(image,draw_info,&metrics); image->rows=(size_t) ((i+1)*(metrics.ascent-metrics.descent+ draw_info->interline_spacing+draw_info->stroke_width)+0.5); } if (status != MagickFalse) status=SetImageExtent(image,image->columns,image->rows); if (status == MagickFalse) { draw_info=DestroyDrawInfo(draw_info); InheritException(exception,&image->exception); return(DestroyImageList(image)); } if (SetImageBackgroundColor(image) == MagickFalse) { draw_info=DestroyDrawInfo(draw_info); InheritException(exception,&image->exception); image=DestroyImageList(image); return((Image *) NULL); } if (fabs(image_info->pointsize) < MagickEpsilon) { double high, low; /* Auto fit text into bounding box. */ for ( ; ; draw_info->pointsize*=2.0) { text=AcquireString(caption); i=FormatMagickCaption(image,draw_info,split,&metrics,&text); (void) CloneString(&draw_info->text,text); text=DestroyString(text); (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g", -metrics.bounds.x1,metrics.ascent); if (draw_info->gravity == UndefinedGravity) (void) CloneString(&draw_info->geometry,geometry); status=GetMultilineTypeMetrics(image,draw_info,&metrics); (void) status; width=(size_t) floor(metrics.width+draw_info->stroke_width+0.5); height=(size_t) floor(metrics.height+draw_info->stroke_width+0.5); if ((image->columns != 0) && (image->rows != 0)) { if ((width >= image->columns) && (height >= image->rows)) break; } else if (((image->columns != 0) && (width >= image->columns)) || ((image->rows != 0) && (height >= image->rows))) break; } high=draw_info->pointsize; for (low=1.0; (high-low) > 0.5; ) { draw_info->pointsize=(low+high)/2.0; text=AcquireString(caption); i=FormatMagickCaption(image,draw_info,split,&metrics,&text); (void) CloneString(&draw_info->text,text); text=DestroyString(text); (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g", -metrics.bounds.x1,metrics.ascent); if (draw_info->gravity == UndefinedGravity) (void) CloneString(&draw_info->geometry,geometry); (void) GetMultilineTypeMetrics(image,draw_info,&metrics); width=(size_t) floor(metrics.width+draw_info->stroke_width+0.5); height=(size_t) floor(metrics.height+draw_info->stroke_width+0.5); if ((image->columns != 0) && (image->rows != 0)) { if ((width < image->columns) && (height < image->rows)) low=draw_info->pointsize+0.5; else high=draw_info->pointsize-0.5; } else if (((image->columns != 0) && (width < image->columns)) || ((image->rows != 0) && (height < image->rows))) low=draw_info->pointsize+0.5; else high=draw_info->pointsize-0.5; } draw_info->pointsize=(low+high)/2.0-0.5; } /* Draw caption. */ i=FormatMagickCaption(image,draw_info,split,&metrics,&caption); (void) CloneString(&draw_info->text,caption); (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g",MagickMax( draw_info->direction == RightToLeftDirection ? image->columns- metrics.bounds.x2 : -metrics.bounds.x1,0.0),draw_info->gravity == UndefinedGravity ? metrics.ascent : 0.0); draw_info->geometry=AcquireString(geometry); status=AnnotateImage(image,draw_info); if (image_info->pointsize == 0.0) { char pointsize[MaxTextExtent]; (void) FormatLocaleString(pointsize,MaxTextExtent,"%.20g", draw_info->pointsize); (void) SetImageProperty(image,"caption:pointsize",pointsize); } draw_info=DestroyDrawInfo(draw_info); caption=DestroyString(caption); if (status == MagickFalse) { image=DestroyImageList(image); return((Image *) NULL); } return(GetFirstImageInList(image)); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d C A P T I O N I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadCAPTIONImage() reads a CAPTION image file and returns it. It % allocates the memory necessary for the new Image structure and returns a % pointer to the new image. % % The format of the ReadCAPTIONImage method is: % % Image *ReadCAPTIONImage(const ImageInfo *image_info, % ExceptionInfo *exception) % % A description of each parameter follows: % % o image_info: the image info. % % o exception: return any errors or warnings in this structure. % */ static Image *ReadCAPTIONImage(const ImageInfo *image_info, ExceptionInfo *exception) { char *caption, geometry[MaxTextExtent], *property; const char *gravity, *option; DrawInfo *draw_info; Image *image; MagickBooleanType status; register ssize_t i; size_t height, width; TypeMetric metrics; /* Initialize Image structure. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickSignature); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); image=AcquireImage(image_info,exception); if (image->columns == 0) ThrowReaderException(OptionError,"MustSpecifyImageSize"); (void) ResetImagePage(image,"0x0+0+0"); /* Format caption. */ option=GetImageOption(image_info,"filename"); if (option == (const char *) NULL) property=InterpretImageProperties(image_info,image,image_info->filename, exception); else if (LocaleNCompare(option,"caption:",8) == 0) property=InterpretImageProperties(image_info,image,option+8,exception); else property=InterpretImageProperties(image_info,image,option,exception); (void) SetImageProperty(image,"caption",property,exception); property=DestroyString(property); caption=ConstantString(GetImageProperty(image,"caption",exception)); draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL); (void) CloneString(&draw_info->text,caption); gravity=GetImageOption(image_info,"gravity"); if (gravity != (char *) NULL) draw_info->gravity=(GravityType) ParseCommandOption(MagickGravityOptions, MagickFalse,gravity); if ((*caption != '\0') && (image->rows != 0) && (image_info->pointsize == 0.0)) { char *text; double high, low; /* Auto fit text into bounding box. */ for ( ; ; ) { text=AcquireString(caption); i=FormatMagickCaption(image,draw_info,MagickTrue,&metrics,&text, exception); (void) CloneString(&draw_info->text,text); text=DestroyString(text); (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g", -metrics.bounds.x1,metrics.ascent); if (draw_info->gravity == UndefinedGravity) (void) CloneString(&draw_info->geometry,geometry); status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception); (void) status; width=(size_t) floor(metrics.width+draw_info->stroke_width+0.5); height=(size_t) floor(metrics.height+draw_info->stroke_width+0.5); if ((width > image->columns) && (height > image->rows)) break; draw_info->pointsize*=2.0; } high=draw_info->pointsize/2.0; low=high/2.0; while ((high-low) > 1.0) { draw_info->pointsize=(low+high)/2.0; text=AcquireString(caption); i=FormatMagickCaption(image,draw_info,MagickTrue,&metrics,&text, exception); (void) CloneString(&draw_info->text,text); text=DestroyString(text); (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g", -metrics.bounds.x1,metrics.ascent); if (draw_info->gravity == UndefinedGravity) (void) CloneString(&draw_info->geometry,geometry); status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception); width=(size_t) floor(metrics.width+draw_info->stroke_width+0.5); height=(size_t) floor(metrics.height+draw_info->stroke_width+0.5); if ((width <= image->columns) && (height <= image->rows)) low=draw_info->pointsize+1.0; else high=draw_info->pointsize-1.0; } for (draw_info->pointsize=(low+high)/2.0; ; ) { text=AcquireString(caption); i=FormatMagickCaption(image,draw_info,MagickTrue,&metrics,&text, exception); (void) CloneString(&draw_info->text,text); text=DestroyString(text); (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g", -metrics.bounds.x1,metrics.ascent); if (draw_info->gravity == UndefinedGravity) (void) CloneString(&draw_info->geometry,geometry); status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception); width=(size_t) floor(metrics.width+draw_info->stroke_width+0.5); height=(size_t) floor(metrics.height+draw_info->stroke_width+0.5); if ((width <= image->columns) && (height <= image->rows)) break; draw_info->pointsize--; } draw_info->pointsize=floor(draw_info->pointsize); } i=FormatMagickCaption(image,draw_info,MagickTrue,&metrics,&caption,exception); if (image->rows == 0) image->rows=(size_t) ((i+1)*(metrics.ascent-metrics.descent+ draw_info->interline_spacing+draw_info->stroke_width)+0.5); if (image->rows == 0) image->rows=(size_t) ((i+1)*draw_info->pointsize+ draw_info->interline_spacing+draw_info->stroke_width+0.5); if (SetImageBackgroundColor(image,exception) == MagickFalse) { image=DestroyImageList(image); return((Image *) NULL); } /* Draw caption. */ (void) CloneString(&draw_info->text,caption); status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception); if ((draw_info->gravity != UndefinedGravity) && (draw_info->direction != RightToLeftDirection)) image->page.x=(ssize_t) (metrics.bounds.x1-draw_info->stroke_width/2.0); else { (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g", -metrics.bounds.x1+draw_info->stroke_width/2.0,metrics.ascent+ draw_info->stroke_width/2.0); if (draw_info->direction == RightToLeftDirection) (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g", image->columns-(metrics.bounds.x2+draw_info->stroke_width/2.0), metrics.ascent+draw_info->stroke_width/2.0); draw_info->geometry=AcquireString(geometry); } status=AnnotateImage(image,draw_info,exception); draw_info=DestroyDrawInfo(draw_info); caption=DestroyString(caption); if (status == MagickFalse) { image=DestroyImageList(image); return((Image *) NULL); } return(GetFirstImageInList(image)); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d L A B E L I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadLABELImage() reads a LABEL image file and returns it. It % allocates the memory necessary for the new Image structure and returns a % pointer to the new image. % % The format of the ReadLABELImage method is: % % Image *ReadLABELImage(const ImageInfo *image_info, % ExceptionInfo *exception) % % A description of each parameter follows: % % o image_info: the image info. % % o exception: return any errors or warnings in this structure. % */ static Image *ReadLABELImage(const ImageInfo *image_info, ExceptionInfo *exception) { char geometry[MagickPathExtent], *property; const char *label; DrawInfo *draw_info; Image *image; MagickBooleanType status; TypeMetric metrics; size_t height, width; /* Initialize Image structure. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickCoreSignature); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickCoreSignature); image=AcquireImage(image_info,exception); (void) ResetImagePage(image,"0x0+0+0"); property=InterpretImageProperties((ImageInfo *) image_info,image, image_info->filename,exception); (void) SetImageProperty(image,"label",property,exception); property=DestroyString(property); label=GetImageProperty(image,"label",exception); draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL); draw_info->text=ConstantString(label); metrics.width=0; metrics.ascent=0.0; status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception); if ((image->columns == 0) && (image->rows == 0)) { image->columns=(size_t) (metrics.width+draw_info->stroke_width+0.5); image->rows=(size_t) floor(metrics.height+draw_info->stroke_width+0.5); } else if (((image->columns == 0) || (image->rows == 0)) || (fabs(image_info->pointsize) < MagickEpsilon)) { double high, low; /* Auto fit text into bounding box. */ for ( ; ; draw_info->pointsize*=2.0) { (void) FormatLocaleString(geometry,MagickPathExtent,"%+g%+g", -metrics.bounds.x1,metrics.ascent); if (draw_info->gravity == UndefinedGravity) (void) CloneString(&draw_info->geometry,geometry); status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception); width=(size_t) floor(metrics.width+draw_info->stroke_width+0.5); height=(size_t) floor(metrics.height+draw_info->stroke_width+0.5); if ((image->columns != 0) && (image->rows != 0)) { if ((width >= image->columns) && (height >= image->rows)) break; } else if (((image->columns != 0) && (width >= image->columns)) || ((image->rows != 0) && (height >= image->rows))) break; } high=draw_info->pointsize; for (low=1.0; (high-low) > 0.5; ) { draw_info->pointsize=(low+high)/2.0; (void) FormatLocaleString(geometry,MagickPathExtent,"%+g%+g", -metrics.bounds.x1,metrics.ascent); if (draw_info->gravity == UndefinedGravity) (void) CloneString(&draw_info->geometry,geometry); status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception); width=(size_t) floor(metrics.width+draw_info->stroke_width+0.5); height=(size_t) floor(metrics.height+draw_info->stroke_width+0.5); if ((image->columns != 0) && (image->rows != 0)) { if ((width < image->columns) && (height < image->rows)) low=draw_info->pointsize+0.5; else high=draw_info->pointsize-0.5; } else if (((image->columns != 0) && (width < image->columns)) || ((image->rows != 0) && (height < image->rows))) low=draw_info->pointsize+0.5; else high=draw_info->pointsize-0.5; } draw_info->pointsize=(low+high)/2.0-0.5; } status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception); if (status == MagickFalse) { draw_info=DestroyDrawInfo(draw_info); image=DestroyImageList(image); return((Image *) NULL); } if (image->columns == 0) image->columns=(size_t) (metrics.width+draw_info->stroke_width+0.5); if (image->columns == 0) image->columns=(size_t) (draw_info->pointsize+draw_info->stroke_width+0.5); if (image->rows == 0) image->rows=(size_t) (metrics.ascent-metrics.descent+ draw_info->stroke_width+0.5); if (image->rows == 0) image->rows=(size_t) (draw_info->pointsize+draw_info->stroke_width+0.5); status=SetImageExtent(image,image->columns,image->rows,exception); if (status == MagickFalse) { draw_info=DestroyDrawInfo(draw_info); return(DestroyImageList(image)); } if (SetImageBackgroundColor(image,exception) == MagickFalse) { draw_info=DestroyDrawInfo(draw_info); image=DestroyImageList(image); return((Image *) NULL); } /* Draw label. */ (void) FormatLocaleString(geometry,MagickPathExtent,"%+g%+g", draw_info->direction == RightToLeftDirection ? image->columns- metrics.bounds.x2 : 0.0,draw_info->gravity == UndefinedGravity ? metrics.ascent : 0.0); draw_info->geometry=AcquireString(geometry); status=AnnotateImage(image,draw_info,exception); if (image_info->pointsize == 0.0) { char pointsize[MagickPathExtent]; (void) FormatLocaleString(pointsize,MagickPathExtent,"%.20g", draw_info->pointsize); (void) SetImageProperty(image,"label:pointsize",pointsize,exception); } draw_info=DestroyDrawInfo(draw_info); if (status == MagickFalse) { image=DestroyImageList(image); return((Image *) NULL); } return(GetFirstImageInList(image)); }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d L A B E L I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadLABELImage() reads a LABEL image file and returns it. It % allocates the memory necessary for the new Image structure and returns a % pointer to the new image. % % The format of the ReadLABELImage method is: % % Image *ReadLABELImage(const ImageInfo *image_info, % ExceptionInfo *exception) % % A description of each parameter follows: % % o image_info: the image info. % % o exception: return any errors or warnings in this structure. % */ static Image *ReadLABELImage(const ImageInfo *image_info, ExceptionInfo *exception) { char geometry[MaxTextExtent], *property; const char *label; DrawInfo *draw_info; Image *image; MagickBooleanType status; TypeMetric metrics; size_t height, width; /* Initialize Image structure. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickSignature); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); image=AcquireImage(image_info); (void) ResetImagePage(image,"0x0+0+0"); property=InterpretImageProperties(image_info,image,image_info->filename); (void) SetImageProperty(image,"label",property); property=DestroyString(property); label=GetImageProperty(image,"label"); draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL); draw_info->text=ConstantString(label); status=GetMultilineTypeMetrics(image,draw_info,&metrics); if (image->columns == 0) { (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g", -metrics.bounds.x1,metrics.ascent); if (draw_info->gravity == UndefinedGravity) (void) CloneString(&draw_info->geometry,geometry); status=GetMultilineTypeMetrics(image,draw_info,&metrics); (void) status; image->columns=(size_t) floor(metrics.width+draw_info->stroke_width+0.5); } if (image->rows == 0) { (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g", -metrics.bounds.x1,metrics.ascent); if (draw_info->gravity == UndefinedGravity) (void) CloneString(&draw_info->geometry,geometry); status=GetMultilineTypeMetrics(image,draw_info,&metrics); image->rows=(size_t) floor(metrics.height+draw_info->stroke_width+0.5); } if (image_info->pointsize == 0.0) { double high, low; /* Auto fit text into bounding box. */ for ( ; ; draw_info->pointsize*=2.0) { (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g", -metrics.bounds.x1,metrics.ascent); if (draw_info->gravity == UndefinedGravity) (void) CloneString(&draw_info->geometry,geometry); status=GetMultilineTypeMetrics(image,draw_info,&metrics); (void) status; width=(size_t) floor(metrics.width+draw_info->stroke_width+0.5); height=(size_t) floor(metrics.height+draw_info->stroke_width+0.5); if ((width >= image->columns) && (height >= image->rows)) break; if ((width >= (image->columns << 1)) || (height >= (image->rows << 1))) break; } high=draw_info->pointsize/2.0; for (low=high/2.0; (high-low) > 1.0; ) { draw_info->pointsize=(low+high)/2.0; (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g", -metrics.bounds.x1,metrics.ascent); if (draw_info->gravity == UndefinedGravity) (void) CloneString(&draw_info->geometry,geometry); status=GetMultilineTypeMetrics(image,draw_info,&metrics); width=(size_t) floor(metrics.width+draw_info->stroke_width+0.5); height=(size_t) floor(metrics.height+draw_info->stroke_width+0.5); if ((width <= image->columns) && (height <= image->rows)) low=draw_info->pointsize+1.0; else high=draw_info->pointsize-1.0; } for (draw_info->pointsize=(low+high)/2.0; (high-low) > 1.0; ) { (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g", -metrics.bounds.x1,metrics.ascent); if (draw_info->gravity == UndefinedGravity) (void) CloneString(&draw_info->geometry,geometry); status=GetMultilineTypeMetrics(image,draw_info,&metrics); width=(size_t) floor(metrics.width+draw_info->stroke_width+0.5); height=(size_t) floor(metrics.height+draw_info->stroke_width+0.5); if ((width <= image->columns) && (height <= image->rows)) break; draw_info->pointsize--; } draw_info->pointsize=floor(draw_info->pointsize+0.5); } status=GetMultilineTypeMetrics(image,draw_info,&metrics); if (status == MagickFalse) { InheritException(exception,&image->exception); image=DestroyImageList(image); return((Image *) NULL); } if (draw_info->gravity == UndefinedGravity) { (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g", -metrics.bounds.x1+draw_info->stroke_width/2.0,metrics.ascent+ draw_info->stroke_width/2.0); (void) CloneString(&draw_info->geometry,geometry); } if (draw_info->direction == RightToLeftDirection) { if (draw_info->direction == RightToLeftDirection) (void) FormatLocaleString(geometry,MaxTextExtent,"%+g%+g", image->columns-(metrics.bounds.x2+draw_info->stroke_width/2.0), metrics.ascent+draw_info->stroke_width/2.0); (void) CloneString(&draw_info->geometry,geometry); } if (SetImageBackgroundColor(image) == MagickFalse) { InheritException(exception,&image->exception); image=DestroyImageList(image); return((Image *) NULL); } (void) AnnotateImage(image,draw_info); if (image_info->pointsize == 0.0) { char pointsize[MaxTextExtent]; (void) FormatLocaleString(pointsize,MaxTextExtent,"%.20g", draw_info->pointsize); (void) SetImageProperty(image,"label:pointsize",pointsize); } draw_info=DestroyDrawInfo(draw_info); return(GetFirstImageInList(image)); }