/// <summary> /// 从缓存区构造多边形填充到字型轮廓(一个字型轮廓包含多个多边形,每个多边形由若干个直线或曲线组成) /// </summary> /// <param name="outline">轮廓</param> /// <param name="buffer">缓存区指针</param> /// <param name="bufferSize">缓存区大小</param> /// <returns></returns> private static void FillPolygons(DOutline outline, IntPtr buffer, int bufferSize) { //多边形头大小 int polygonHeaderSize = Marshal.SizeOf(typeof(TTPOLYGONHEADER)); //线大小 int lineSize = Marshal.SizeOf(typeof(TTPOLYCURVEHEAD)); //点大小 int pointFxSize = Marshal.SizeOf(typeof(POINTFX)); //缓存区首地址值 int ptr = buffer.ToInt32(); //偏移量 int offset = 0; //轮廓的多边形列表 IList <DPolygon> polygons = outline.Polygons; while (offset < bufferSize) { //多边形头信息 TTPOLYGONHEADER header = (TTPOLYGONHEADER)Marshal.PtrToStructure(new IntPtr(ptr + offset), typeof(TTPOLYGONHEADER)); //构建多边形 DPolygon polygon = new DPolygon(header.dwType); //起始点 polygon.Start = header.pfxStart; //获取尾索引 int endCurvesIndex = offset + header.cb; //向后偏移一个项 offset += polygonHeaderSize; while (offset < endCurvesIndex) { //线段信息 TTPOLYCURVEHEAD lineHeader = (TTPOLYCURVEHEAD)Marshal.PtrToStructure(new IntPtr(ptr + offset), typeof(TTPOLYCURVEHEAD)); //偏移到点序列首地址 offset += lineSize; //构建线段 DLine line = new DLine(lineHeader.wType); //读取点序列,加入线段中 for (int i = 0; i < lineHeader.cpfx; i++) { POINTFX point = (POINTFX)Marshal.PtrToStructure(new IntPtr(ptr + offset), typeof(POINTFX)); //将点加入线段 line.Points.Add(point); //偏移 offset += pointFxSize; } //将线加入多边形 polygon.Lines.Add(line); } //将多边形加入轮廓 polygons.Add(polygon); } }
/// <summary> /// 获取轮廓多边形列表 /// </summary> /// <param name="hdc">场景</param> /// <param name="uChar">字符</param> /// <returns></returns> private static DOutline GetOutline(IntPtr hdc, uint uChar) { // 转置矩阵 MAT2 mat2 = new MAT2(); mat2.eM11.value = 1; mat2.eM22.value = 1; GLYPHMETRICS lpGlyph = new GLYPHMETRICS(); //获取缓存区大小 int bufferSize = GdiNativeMethods.GetGlyphOutline(hdc, uChar, GGO_NATIVE, out lpGlyph, 0, IntPtr.Zero, ref mat2); if (bufferSize > 0) { //获取成功后,分配托管内存 IntPtr buffer = Marshal.AllocHGlobal(bufferSize); try { int ret = GdiNativeMethods.GetGlyphOutline(hdc, uChar, GGO_NATIVE, out lpGlyph, (uint)bufferSize, buffer, ref mat2); if (ret > 0) { //构建轮廓 DOutline outline = new DOutline(lpGlyph.gmBlackBoxX, lpGlyph.gmBlackBoxY); //从缓存区构造字型轮廓 FillPolygons(outline, buffer, bufferSize); return(outline); } else { throw new Exception("获取字型数据失败!"); } } finally { //释放托管内存 Marshal.FreeHGlobal(buffer); } } else { throw new Exception("未能获取缓存区!"); } }
/// <summary> /// 填充所有字符轮廓 /// </summary> /// <param name="x">起始X</param> /// <param name="y">Y值</param> /// <param name="spacing">字符间隔</param> private void FillWordOutlines(int x, int y, int spacing, Font font) { string text = tbWords.Text; if (!string.IsNullOrEmpty(text)) { foreach (char t in text) { TreeNode wordNode = new TreeNode(t.ToString()); tvList.Nodes.Add(wordNode); //获取字符编码 uint ch = GetGB2312Coding(t); //获取轮廓数据 DOutline outline = WordGraph.GetOutline(ch, font); //构建轮廓实例 WordOutlineDrawing word = BuildWordOutline(outline, new PointF(x, y), wordNode); wordOutlines.Add(word); //下个字的起始位置=当前起始位置+宽度+间隔 x += (int)outline.Width + spacing; } } }
/// <summary> /// 通过轮廓数据构建字体轮廓 /// </summary> /// <param name="outline">轮廓数据</param> /// <param name="offset">偏移量</param> /// <param name="wordNode"></param> /// <returns></returns> private WordOutlineDrawing BuildWordOutline(DOutline outline, PointF offset, TreeNode wordNode) { //获取轮廓大小 SizeF size = new SizeF(outline.Width, outline.Height); WordOutlineDrawing word = new WordOutlineDrawing(size); //--------------------- wordNode.Tag = word; //--------------------- int index = 0; //遍历填充轮廓数据 foreach (DPolygon p in outline.Polygons) { //新增多边形实例 PolygonDrawing polygon = new PolygonDrawing(); //--------------------- TreeNode polygonNode = new TreeNode("多边形" + (++index)); polygonNode.Tag = polygon; wordNode.Nodes.Add(polygonNode); //--------------------- //起始点 PointF start = new PointF(offset.X + ConvertUtil.FixedToFloat(p.Start.x), offset.Y - ConvertUtil.FixedToFloat(p.Start.y)); PointF point = start; foreach (DLine l in p.Lines) { LineDrawing line = null; //如果类型为1则为折线,为2则为曲线 if (l.Type == 1) { line = new PolylineDrawing(); } else { line = new CurvelineDrawing(); } //加入起始点 line.Points.Add(point); //--------------------- StringBuilder builder = new StringBuilder(l.Type == 1 ? "折" : "曲"); builder.AppendFormat(" ({0},{1}) ", point.X, point.Y); //--------------------- foreach (POINTFX fx in l.Points) { point = new PointF(offset.X + ConvertUtil.FixedToFloat(fx.x), offset.Y - ConvertUtil.FixedToFloat(fx.y)); Console.WriteLine("{0}.{1}, {2}.{3}({4},{5})", fx.x.value, fx.x.fract, fx.y.value, fx.y.fract, ConvertUtil.FixedToFloat(fx.x), ConvertUtil.FixedToFloat(fx.y)); line.Points.Add(point); builder.AppendFormat("({0},{1}) ", point.X, point.Y); } polygon.Lines.Add(line); //--------------------- TreeNode lineNode = new TreeNode(builder.ToString()); lineNode.Tag = line; polygonNode.Nodes.Add(lineNode); //--------------------- } if (point != start) { //增加结束到开始的闭合线段 LineDrawing endLine = new BeelineDrawing(); endLine.Points.Add(point); endLine.Points.Add(start); polygon.Lines.Add(endLine); //--------------------- TreeNode endNode = new TreeNode(string.Format("直 ({0},{1}) ({0},{1}) ", point.X, point.Y, start.X, start.Y)); endNode.Tag = endLine; polygonNode.Nodes.Add(endNode); //--------------------- } //加入到字符轮廓的多边形列表中 word.Polygons.Add(polygon); } return(word); }