// Last updated 2008/12/03 11:44 // From: https://imagemagick.org.cn/discourse-server/viewtopic.php?f=18&t=12079 #include <windows.h> #include <wand/magick_wand.h> /* 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 example font metrics from my tcl script test_metrics.tcl Arial 48 CWxCH = 48.0 x 48.0 AxD = 44.0 x -11.0 TWxTH = 248.0 x 55.0 MHA = 96.0 BB = (0.0,0.0) (48.0,35.0) origin = 249.0 x 0.0 Arial 24 CWxCH = 24.0 x 24.0 AxD = 22.0 x -6.0 TWxTH = 125.0 x 28.0 MHA = 48.0 BB = (0.0,0.0) (23.0,17.0) origin = 126.0 x 0.0 Times-New-Roman 18 CWxCH = 18.0 x 18.0 AxD = 17.0 x -4.0 TWxTH = 87.0 x 21.0 MHA = 36.0 BB = (0.0,0.0) (16.859375,13.0) origin = 87.0 x 0.0 Times-New-Roman 72 CWxCH = 72.0 x 72.0 AxD = 65.0 x -16.0 TWxTH = 352.0 x 83.0 MHA = 144.0 BB = (0.0,-1.0) (67.453125,50.0) origin = 352.0 x 0.0 */ // Set up the drawingwand "dw" for the given font name, font size, and colour. // If the font or size changes return the new width of a space (metric[4]) in sx // (the magickwand is required if it is necessary to query the font metrics) void draw_setfont(MagickWand *mw,DrawingWand *dw,unsigned char *font,int size,unsigned char *colour,int *sx) { double *fm; PixelWand *pw = NULL; int sflag = 0; if(font && *font) { DrawSetFont(dw,font); sflag = 1; } if(colour && *colour) { pw = NewPixelWand(); PixelSetColor(pw,colour); DrawSetFillColor(dw,pw); DestroyPixelWand(pw); sflag = 1; } if(size) { DrawSetFontSize(dw,size); } // If either the font or the fontsize (or both) have changed // we need to get the size of a space again if(sflag) { fm = MagickQueryFontMetrics(mw, dw, " "); *sx = (int)fm[4]; RelinquishMagickMemory(fm); } } // sx is the width of a space in the current font and fontsize. // If the font or fontsize is changed a new value for the space // width must be obtained before calling this again (by calling draw_setfont) // The easiest (?) way to handle vertical text placement is // not to use gravity at all because then you know that all the text is // placed relative to ImageMagick's (0,0) coordinate which is the top left of // the screen and the baseline will be y=0. void draw_metrics(MagickWand *mw,DrawingWand *dw,int *dx,int *dy,int sx,unsigned char *text) { double *fm; MagickAnnotateImage(mw, dw, *dx, *dy, 0, text); MagickDrawImage(mw,dw); // get the font metrics fm = MagickQueryFontMetrics(mw, dw, text); if(fm) { // Adjust the new x coordinate *dx += (int)fm[4]+sx; RelinquishMagickMemory(fm); } } void test_wand(LPTSTR lpCmdLine) { MagickWand *mw = NULL; DrawingWand *dw = NULL; PixelWand *pw = NULL; // Current coordinates of text int dx,dy; // Width of a space in current font/size int sx; double *fm = NULL; MagickWandGenesis(); mw = NewMagickWand(); dw = NewDrawingWand(); pw = NewPixelWand(); // Set the size of the image MagickSetSize(mw,300,100); // MagickSetImageAlphaChannel(mw,SetAlphaChannel); MagickReadImage(mw,"xc:white"); // DO NOT SET GRAVITY - it makes text placement more complicated // (unless it does exactly what you wanted anyway). // Start near the left edge dx = 10; // If we know the largest font we're using, we can set the y coordinate // fairly accurately. In this case it is the 72 point Times font, so to // place the text such that the largest almost touches the top of the image // we just add the text height to the descender to give the coordinate for // our baseline. // In this case the largest is the 72 point Times-New-Roman so I'll use that // to compute the baseline DrawSetFontSize(dw,72); DrawSetFont(dw,"Times-New-Roman"); fm = MagickQueryFontMetrics(mw, dw,"M"); dy = fm[1]+fm[3]; // Note that we must free up the fontmetric array once we're done with it RelinquishMagickMemory(fm); // this draw_setfont(mw,dw,"Arial",48,"#40FF80",&sx); draw_metrics(mw,dw,&dx,&dy,sx,"this"); // is // A NULL signals to draw_setfont that the font stays the same draw_setfont(mw,dw,NULL,24,"#8040BF",&sx); draw_metrics(mw,dw,&dx,&dy,sx,"is"); // my draw_setfont(mw,dw,"Times-New-Roman",18,"#BF00BF",&sx); draw_metrics(mw,dw,&dx,&dy,sx,"my"); // text draw_setfont(mw,dw,NULL,72,"#0F0FBF",&sx); draw_metrics(mw,dw,&dx,&dy,sx,"text"); MagickDrawImage(mw,dw); // Now write the magickwand image MagickWriteImage(mw,"metric1.gif"); if(mw)mw = DestroyMagickWand(mw); if(dw)dw = DestroyDrawingWand(dw); if(pw)pw = DestroyPixelWand(pw); MagickWandTerminus(); }