缺根弦

如何让我和.Net跑的更快?

使用GdipDrawDriverString实现行距及字符间距控制

前几天,一个朋友请求帮忙处理个LED图片生成问题,主要是要将一个标题和几段文字绘制到固定大小的图片上,如果一张放不下就生成多张。在使用DrawString是发现无法控制行距,请教了baidu大神找到了GdipDrawDriverString函数,但没看到完整的例子,于是将自己实现的方法发出来,以便初接触者了解,主要还是请大家批评指正。

  1public class ConvertImage
  2     {
  3         public bool TextToImage(string title_Text, string title_FontFamily, float title_FontEmSize, FontStyle title_FontStyle, Color title_Color, int title_MarginTop, int title_MarginBottom,
  4             string content_Text, string content_FontFamily, float content_FontEmSize, FontStyle content_FontStyle, Color content_Color, int content_RowSpacing, int content_WordSpacing,
  5             int page_Width, int page_Height, int page_MarginLeftRight, int page_MarginTop, Color background_Color, string SavePath)
  6         {
  7             //TODO:检测并修正参数
  8             System.Drawing.Bitmap bit = new System.Drawing.Bitmap(page_Width, page_Height);
  9             System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bit);
 10             g.SmoothingMode = SmoothingMode.HighQuality;
 11             g.InterpolationMode = InterpolationMode.HighQualityBicubic;
 12             g.CompositingQuality = CompositingQuality.HighQuality;
 13             g.Clear(background_Color);
 14             //--写标题--本代码假定标题内容不会超出一页
 15             Font title_font = new Font(title_FontFamily, title_FontEmSize, title_FontStyle);
 16             Brush title_brush = new SolidBrush(title_Color);
 17             SizeF size = g.MeasureString(title_Text, title_font, page_Width - page_MarginLeftRight * 2);
 18             g.DrawString(title_Text, title_font, title_brush,
 19                 new RectangleF(new PointF(page_MarginLeftRight, title_MarginTop), //标题的上边距单独指定
 20                     new SizeF(page_Width - page_MarginLeftRight * 2, page_Height - title_MarginTop)));
 21             //--计算内容每个字符的显示位置
 22             Font font = new Font(content_FontFamily, content_FontEmSize, content_FontStyle);
 23             Brush brush = new SolidBrush(content_Color);
 24             List<PageClass> lpageClass = GetShowList(content_Text, g, font, page_Width, page_Height, content_RowSpacing, content_WordSpacing, size.Height + title_MarginTop + title_MarginBottom, page_MarginLeftRight, page_MarginTop);
 25             foreach (PageClass pc in lpageClass)
 26             {
 27                 if (pc.pageindex > 1)
 28                 {
 29                     g.Dispose();
 30                     bit.Dispose();
 31                     bit = new System.Drawing.Bitmap(page_Width, page_Height);
 32                     g = System.Drawing.Graphics.FromImage(bit);
 33                     g.Clear(background_Color);
 34                     g.SmoothingMode = SmoothingMode.HighQuality;
 35                     g.InterpolationMode = InterpolationMode.HighQualityBicubic;
 36                     g.CompositingQuality = CompositingQuality.HighQuality;
 37                 }
 38                 GdiplusMethods.DrawDriverString(g, pc.txt, font, brush, pc.pos);
 39                 bit.RotateFlip(RotateFlipType.Rotate90FlipXY);
 40                 bit.Save(string.Format(SavePath, pc.pageindex), System.Drawing.Imaging.ImageFormat.Bmp);
 41 
 42             }
 43             return true;
 44 
 45         }
 46         /// <summary>
 47         /// 计算内容每个字符的显示位置,根据字符大小自动分行,支持空格、换行、两边自动对齐
 48         /// </summary>
 49         /// <param name="txt">文本内容</param>
 50         /// <param name="g">绘图区域</param>
 51         /// <param name="font">字体</param>
 52         /// <param name="pagewidth">页宽</param>
 53         /// <param name="pageheight">页高</param>
 54         /// <param name="rowspace">行距</param>
 55         /// <param name="wordspace">字符间距</param>
 56         /// <param name="firstPageMaginTop">首页上边距</param>
 57         /// <param name="marginleftright">页左右边距</param>
 58         /// <param name="margintop">普通页上边距</param>
 59         /// <returns></returns>
 60         public List<PageClass> GetShowList(string txt, Graphics g, Font font, int pagewidth, int pageheight,
 61             float rowspace, float wordspace, float firstPageMaginTop, int marginleftright, int margintop)
 62         {
 63             int pageindex = 1;
 64             float left = 0, top = firstPageMaginTop + font.SizeInPoints; ;
 65             float lastRight = marginleftright - wordspace;
 66             float lastRowBotton = top;
 67             float rowheight = font.SizeInPoints + rowspace;
 68             int colstart = 0, colend = 0;
 69             float colspace;
 70             string curTxt, measureStr;
 71             SizeF size;
 72             List<PointF> lpos = new List<PointF>();
 73             List<PageClass> lpageClass = new List<PageClass>();
 74             PageClass curPage = new PageClass();
 75             System.Text.StringBuilder str = new System.Text.StringBuilder();
 76             for (int i = 0; i < txt.Length; i++) //这个字在这行放不下,要放到下一行
 77             {
 78                 curTxt = txt.Substring(i, 1);
 79                 switch (curTxt)
 80                 {
 81                     case " ":
 82                         measureStr = "2";
 83                         break;
 84                     case "\t":
 85                         measureStr = "2222";
 86                         break;
 87                     case " ":
 88                         measureStr = "";
 89                         break;
 90                     default:
 91                         measureStr = curTxt;
 92                         break;
 93                 }
 94                 size = g.MeasureString(measureStr, font, int.MaxValue, StringFormat.GenericTypographic);
 95                 left = lastRight + wordspace;
 96                 if ((left + size.Width) > pagewidth || curTxt == "\n")
 97                 {
 98                     if (curTxt != "\n")
 99                     {
100                         colspace = (pagewidth - lastRight - marginleftright) / (colend - colstart);
101                         for (int j = colstart; j < colend; j++)//处理两边对齐
102                         {
103                             lpos[j] = new PointF(lpos[j].X + colspace * (j - colstart + 1), lpos[j].Y);
104                         }
105                     }
106                     colstart = colend;
107 
108                     left = marginleftright;
109                     top = lastRowBotton + rowheight;
110 
111                     lastRowBotton = top;
112                 }
113                 colend++;
114                 lastRight = left + size.Width;
115 
116                 if (top > pageheight) //这行应该放到下一页了
117                 {
118                     curPage.pageindex = pageindex;
119                     curPage.txt = str.ToString();
120                     curPage.pos = lpos.ToArray();
121                     lpageClass.Add(curPage);
122 
123                     pageindex++;
124                     curPage = new PageClass();
125                     lpos.Clear();
126                     //str.Clear();
127                     str.Remove(0, str.Length);
128                     top = margintop + rowheight;
129                     lastRowBotton = top;
130                     colstart = 0;
131                     colend = 1;
132                 }
133 
134                 str.Append(curTxt);
135                 lpos.Add(new PointF(left, top));
136 
137             }
138             //保存最后一页
139             if (lpos.Count > 0)
140             {
141                 curPage.pageindex = pageindex;
142                 curPage.txt = str.ToString();
143                 curPage.pos = lpos.ToArray();
144                 lpageClass.Add(curPage);
145             }
146             return lpageClass;
147         }
148     }
149 
150     public class PageClass
151     {
152         public int pageindex;
153         public string txt;
154         public PointF[] pos;
155     }
156     public class GdiplusMethods
157     {
158         private GdiplusMethods() { }
159 
160         private enum DriverStringOptions
161         {
162             CmapLookup = 1,
163             Vertical = 2,
164             Advance = 4,
165             LimitSubpixel = 8,
166         }
167 
168         public static void DrawDriverString(Graphics graphics, string text,
169             Font font, Brush brush, PointF[] positions)
170         {
171             DrawDriverString(graphics, text, font, brush, positions, null);
172         }
173 
174         public static void DrawDriverString(Graphics graphics, string text,
175             Font font, Brush brush, PointF[] positions, Matrix matrix)
176         {
177             if (graphics == null)
178                 throw new ArgumentNullException("graphics");
179             if (text == null)
180                 throw new ArgumentNullException("text");
181             if (font == null)
182                 throw new ArgumentNullException("font");
183             if (brush == null)
184                 throw new ArgumentNullException("brush");
185             if (positions == null)
186                 throw new ArgumentNullException("positions");
187 
188             // Get hGraphics
189             FieldInfo field = typeof(Graphics).GetField("nativeGraphics",
190                 BindingFlags.Instance | BindingFlags.NonPublic);
191             IntPtr hGraphics = (IntPtr)field.GetValue(graphics);
192 
193             // Get hFont
194             field = typeof(Font).GetField("nativeFont",
195                 BindingFlags.Instance | BindingFlags.NonPublic);
196             IntPtr hFont = (IntPtr)field.GetValue(font);
197 
198             // Get hBrush
199             field = typeof(Brush).GetField("nativeBrush",
200                 BindingFlags.Instance | BindingFlags.NonPublic);
201             IntPtr hBrush = (IntPtr)field.GetValue(brush);
202 
203             // Get hMatrix
204             IntPtr hMatrix = IntPtr.Zero;
205             if (matrix != null)
206             {
207                 field = typeof(Matrix).GetField("nativeMatrix",
208                     BindingFlags.Instance | BindingFlags.NonPublic);
209                 hMatrix = (IntPtr)field.GetValue(matrix);
210             }
211 
212             int result = GdipDrawDriverString(hGraphics, text, text.Length,
213                 hFont, hBrush, positions, (int)DriverStringOptions.CmapLookup, hMatrix);
214         }
215 
216         [DllImport("Gdiplus.dll", CharSet = CharSet.Unicode)]
217         internal extern static int GdipMeasureDriverString(IntPtr graphics,
218             string text, int length, IntPtr font, PointF[] positions,
219             int flags, IntPtr matrix, ref RectangleF bounds);
220 
221         [DllImport("Gdiplus.dll", CharSet = CharSet.Unicode)]
222         internal extern static int GdipDrawDriverString(IntPtr graphics,
223             string text, int length, IntPtr font, IntPtr brush,
224             PointF[] positions, int flags, IntPtr matrix);
225     }

posted on 2012-07-04 15:29  缺根弦  阅读(1723)  评论(0编辑  收藏  举报

导航