void BtnPreviewUpdateClick(object sender, EventArgs e) { if (String.IsNullOrEmpty(previewChar.Text) || String.IsNullOrEmpty(txtInput.Text)) return; this.Cursor = Cursors.WaitCursor; Glyph[] glyphs = new Glyph[previewChar.Text.Length]; Image[] images = new Image[previewChar.Text.Length]; uint[] indexes = new uint[previewChar.Text.Length]; uint charHeight = Convert.ToUInt32(numSize.Value); GlyphRenderer.NewFace(txtInput.Text, charHeight); for (int i = 0; i < previewChar.Text.Length; i++) { GlyphRenderer.CreateGlyph(Convert.ToUInt32(previewChar.Text[i]), out indexes[i], out glyphs[i], out images[i]); } Dictionary<KerningInfoKey, KerningInfo> kerningMap = new Dictionary<KerningInfoKey, KerningInfo>(); for (int i1 = 0; i1 < indexes.Length; i1++) { for (int i2 = 0; i2 < indexes.Length; i2++) { KerningInfo info = GlyphRenderer.CreateKerningInfo(indexes[i1], indexes[i2]); if (info.HorizontalAdjust == 0 && info.VerticalAdjust == 0) continue; info.LeftChar = Convert.ToUInt32(previewChar.Text[i1]); info.RightChar = Convert.ToUInt32(previewChar.Text[i2]); KerningInfoKey key = new KerningInfoKey(info); kerningMap[key] = info; } } Image image = CreatePreviewImage(glyphs, images, kerningMap);//, Image oldImage = null; if (previewBox.Image != null) oldImage = previewBox.Image; if(image != null) previewBox.Image = image; if (oldImage != null) oldImage.Dispose(); GlyphRenderer.DoneFace(); Cursor = Cursors.Default; }
public void AdjustGlyphInfo(ref Glyph glyphInfo) { return; }
public static bool CreateGlyph(uint charCode, out uint charIndex, out Glyph glyph, out Image image) { glyph = new Glyph(); charIndex = FT.FT_Get_Char_Index(ftFace, charCode); image = null; if (charIndex == 0) return false; int error = FT.FT_Load_Glyph(ftFace, charIndex, FT.FT_LOAD_DEFAULT| FT.FT_LOAD_NO_HINTING); if (error != 0) return false; FT_FaceRec* faceRect = (FT_FaceRec*)ftFace.ToPointer(); FT_GlyphSlotRec* ft_glyph = (FT_GlyphSlotRec*)faceRect->glyph.ToPointer(); glyph.Code = charCode; glyph.HorizontalAdvance = (double)ft_glyph->metrics.horiAdvance / 64.0d; glyph.HorizontalBearingX = (double)ft_glyph->metrics.horiBearingX / 64.0d; glyph.HorizontalBearingY = (double)ft_glyph->metrics.horiBearingY / 64.0d; glyph.VerticalAdvance = (double)ft_glyph->metrics.vertAdvance / 64.0d; glyph.VerticalBearingX =(double)ft_glyph->metrics.vertBearingX / 64.0d; glyph.VerticalBearingY = (double)ft_glyph->metrics.vertBearingY / 64.0d; Painter.AdjustGlyphInfo(ref glyph); FT_Outline outline; GraphicsPath path = new GraphicsPath(FillMode.Alternate); if(ft_glyph->format == FT_Glyph_Format.FT_GLYPH_FORMAT_OUTLINE) { outline = ft_glyph->outline; } else return false; PointF[] points = new PointF[outline.n_points]; TagFlag[] tags = new TagFlag[outline.n_points]; int* ptr = (int*)outline.points.ToPointer(); byte* bptr = (byte*)outline.tags.ToPointer(); for(int i =0; i<outline.n_points; i++) { points[i] = new PointF(); points[i].X = (int)*ptr; points[i].X /=64; ptr++; points[i].Y = (int)(*ptr); points[i].Y /= - 64; ptr++; tags[i] = (TagFlag)(*bptr); bptr++; } short[] contours = new short[outline.n_contours]; short* sptr = (short*)outline.contours.ToPointer(); for(int i = 0; i<outline.n_contours; i++, sptr++) { contours[i] = *sptr; } for( int i = 0; i<contours.Length; i++) { int begin; if(i == 0) begin = 0; else begin = contours[i - 1]+1; for(int j = begin; j<=contours[i]; j++) { int p1 = j; int p2 = (j + 1 > contours[i]) ? j + 1 + begin - contours[i] -1: j + 1; if ((tags[j] & TagFlag.OnCurve) == 0) continue; if ((tags[p2] & TagFlag.OnCurve) != 0) { path.AddLine(points[p1], points[p2]); } else { List<PointF> pointList = new List<PointF>(); pointList.Add(points[p1]); int p = p2; while ((tags[p] & TagFlag.OnCurve) == 0) { pointList.Add(points[p]); p++; if (p > contours[i]) p = begin; } pointList.Add(points[p]); AddBezierSpline(pointList.ToArray(), path); } } path.CloseFigure(); } RectangleF bounds = path.GetBounds(); bounds.Width = (float) Math.Ceiling(bounds.Width); bounds.Height = (float) Math.Ceiling(bounds.Height); if(bounds.Width != 0 || bounds.Height != 0) { Bitmap output = new Bitmap((int)bounds.Width, (int)bounds.Height); Graphics g = Graphics.FromImage(output); g.SmoothingMode = antialias? SmoothingMode.AntiAlias:SmoothingMode.None; g.TranslateTransform(-bounds.X, -bounds.Y); if(painter != null) { painter.PaintPath(g, path); } path.Dispose(); g.Dispose(); image = TrimImage(output); } if(image != null) { glyph.Width = (uint) image.Width; glyph.Height = (uint) image.Height; } else { glyph.Width = 0; glyph.Height = 0; } return true; }
Image CreatePreviewImage(Glyph[] glyphs, Image[] images, Dictionary<KerningInfoKey, KerningInfo> kerningMap) { int width = 0; for (int i = 0; i < glyphs.Length; i++) { width += (int)glyphs[i].HorizontalAdvance; } int height = previewBox.Height*3; if (height == 0) return null; Image image = new Bitmap( width>previewBox.Width ? width: previewBox.Width, height); Graphics g = Graphics.FromImage(image); Point origin = new Point(0, height/2); Pen pen = new Pen(Color.BlueViolet); pen.DashStyle = DashStyle.Dash; g.DrawLine(pen, origin, new Point(width, origin.Y)); for (int i = 0; i < glyphs.Length; i++) { int x = origin.X, y = origin.Y; if (i != 0) { KerningInfoKey key = new KerningInfoKey((uint)previewChar.Text[i - 1], (uint)previewChar.Text[i]); if (kerningMap.ContainsKey(key)) { x += (int)kerningMap[key].HorizontalAdjust; y -= (int)kerningMap[key].VerticalAdjust; origin.X += (int)kerningMap[key].HorizontalAdjust; } } x += (int)glyphs[i].HorizontalBearingX; y -= (int)glyphs[i].HorizontalBearingY; origin.X += (int)glyphs[i].HorizontalAdvance; if (images[i] == null) continue; g.DrawImage(images[i], x, y); images[i].Dispose(); } return image; }