static void Main(string[] args) { Console.WriteLine("Version string: " + HB.VersionString); Version v = HB.Version; Console.WriteLine("Version: " + v.Major + "." + v.Minor + "." + v.Build); Console.WriteLine("VersionCheck: " + HB.VersionAtLeast(v)); var lib = new Library(); var face = new SharpFont.Face(lib, @"/usr/share/fonts/noto/NotoSans-Regular.ttf"); face.SetCharSize(0, 50, 72, 72); var font = HarfBuzz.Font.FromFTFace(face); var buf = new HarfBuzz.Buffer(); buf.Direction = Direction.RightToLeft; buf.Script = Script.Arabic; buf.AddText("متن"); font.Shape(buf); var glyphInfos = buf.GlyphInfo(); var glyphPositions = buf.GlyphPositions(); int height = (face.MaxAdvanceHeight - face.Descender) >> 6; int width = 0; for (int i = 0; i < glyphInfos.Length; ++i) { width += glyphPositions[i].xAdvance >> 6; } Bitmap bmp = new Bitmap(width, height); Graphics g = Graphics.FromImage(bmp); g.Clear(Color.Gray); int penX = 0, penY = face.MaxAdvanceHeight >> 6; //draw the string for (int i = 0; i < glyphInfos.Length; ++i) { face.LoadGlyph(glyphInfos[i].codepoint, LoadFlags.Default, LoadTarget.Normal); face.Glyph.RenderGlyph(RenderMode.Normal); Bitmap cBmp = face.Glyph.Bitmap.ToGdipBitmap(Color.Firebrick); g.DrawImageUnscaled(cBmp, penX + (glyphPositions[i].xOffset >> 6) + face.Glyph.BitmapLeft, penY - (glyphPositions[i].yOffset >> 6) - face.Glyph.BitmapTop); penX += glyphPositions[i].xAdvance >> 6; penY -= glyphPositions[i].yAdvance >> 6; } g.Dispose(); bmp.Save("output.bmp"); }
/* * private void DrawChar(Char c) * { * var g = this.CreateGraphics(); * g.ResetTransform(); * g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; * g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixel; * //g. * var charWidth = Int32.Parse(textBoxCharWidth.Text); * var charHeight = Int32.Parse(textBoxCharHeight.Text); * //Console.WriteLine(textBoxFontPreview.Font); * var size = GetCharSize(c, g); * Bitmap bm = new Bitmap(size.Width, size.Height); * Brush br = new SolidBrush(Color.White); * //Graphics g = Graphics.FromImage(bm); * //String s = ""; * //s += c; * StringFormat sf = new StringFormat(); * //sf.Alignment = StringAlignment.Center; * //sf.LineAlignment = StringAlignment.Center; * //g.ResetTransform(); * //g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; * //g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixel; * g.Clear(Color.Black); * //g.DrawString(s, fontDialog1.Font, br, 1, 1, sf); * TextRenderer.DrawText(g, c.ToString(), fontDialog1.Font, new Point(0, 0), Color.White); * // * var bmf = String.Format("{0}\\pcf_{1}.bmp", textBoxOutputDir.Text, (Int32)c); * bm.Save(bmf); * // * g.Dispose(); * } */ private bool DrawChar(Char c) { try { //ftFace.SetCharSize(appSettings.CharSize.Width, appSettings.CharSize.Height, (uint)appSettings.DPI.Width, (uint)appSettings.DPI.Height); ftFace.SetPixelSizes((uint)appSettings.CharSize.Width, (uint)appSettings.CharSize.Height); var glyphIndex = ftFace.GetCharIndex((uint)c); ftFace.LoadGlyph(glyphIndex, SharpFont.LoadFlags.Default | SharpFont.LoadFlags.NoHinting, SharpFont.LoadTarget.Mono); ftFace.Glyph.RenderGlyph(SharpFont.RenderMode.Mono); var penX = ftFace.Glyph.BitmapLeft; var penY = (int)ftFace.Size.Metrics.Ascender - ftFace.Glyph.BitmapTop; while (penY > 0 && penY + ftFace.Glyph.Metrics.Height > appSettings.CharSize.Height) { penY--; } Console.WriteLine("X {0} Y {1} L {2} T {3}", ftFace.Glyph.Advance.X, ftFace.Glyph.Advance.Y, ftFace.Glyph.BitmapLeft, ftFace.Glyph.BitmapTop); Console.WriteLine("{0} {1} {2}", ftFace.Size.Metrics.Ascender, ftFace.Size.Metrics.Descender, ftFace.Glyph.Metrics.Height); Bitmap bm = ftFace.Glyph.Bitmap.ToGdipBitmap(Color.Black); var nbm = new Bitmap(appSettings.CharSize.Width, appSettings.CharSize.Height); var g = Graphics.FromImage(nbm); g.Clear(Color.White); g.DrawImageUnscaled(bm, penX, penY); //nbm.SetPixel() // byte[] mbc; if (c > 127) { mbc = Encoding.GetEncoding(appSettings.CharEncoding).GetBytes(c.ToString().ToCharArray()); } else { mbc = new byte[] { 0, (byte)c } }; outputWriter.WriteLine(@"0x{0:x2},0x{1:x2}, // {2}", mbc[0], mbc[1], c); Console.WriteLine("W {0} H {1}", nbm.Width, nbm.Height); BitArray ba = new BitArray(nbm.Width * nbm.Height); for (var y = 0; y < nbm.Height; y++) { for (var x = 0; x < nbm.Width; x++) { var a = nbm.GetPixel(x, y); ba.Set(y * nbm.Width + x, a.B == 0); } } byte[] bba = new byte[nbm.Width * nbm.Height / 8]; ba.CopyTo(bba, 0); for (var i = 0; i < bba.Length; i++) { if (i > 0 && i % 16 == 0) { outputWriter.WriteLine(); } outputWriter.Write(@"0x{0:x2},", bba[i]); } outputWriter.WriteLine(); outputWriter.WriteLine(); Console.WriteLine(bba.Length); if (appSettings.SaveBitmap) { var nbmf = String.Format("{0}\\pcf_{1:x2}{2:x2}.bmp", appSettings.OutputDir, mbc[0], mbc[1]); nbm.Save(nbmf); } ShowBitmap(nbm); } catch (Exception ex) { Console.WriteLine(ex); return(false); } return(true); }
private void GenerateTextures() { if (_fontGlyphs == null) { _fontGlyphs = new FontGlyph[256]; } if (_textureID == 0) { _textureID = GL.GenTexture(); } _textureSize = Next_P2(16 * _size); int spacing = _textureSize / 16; byte[] textureData = new byte[4 * _textureSize * _textureSize]; byte[] outlineData = new byte[4 * _textureSize * _textureSize]; for (int i = 0; i < 256; i++) { char c = (char)i; uint glyphIndex = _fontFace.GetCharIndex(Convert.ToUInt32(c)); _fontFace.LoadGlyph(glyphIndex, SharpFont.LoadFlags.Default, SharpFont.LoadTarget.Normal); _fontFace.Glyph.RenderGlyph(SharpFont.RenderMode.Normal); SharpFont.FTBitmap bitmap = _fontFace.Glyph.Bitmap; if (_fontGlyphs[i] == null) { _fontGlyphs[i] = new FontGlyph(); } try { int blitX = (i % 16 * spacing); // +(spacing / 2) - (bitmap.Width / 2); //trying to center glyph on on tile region int blitY = (i / 16 * spacing); // +(spacing / 2) - (bitmap.Rows / 2); byte[] bitmapData = bitmap.BufferData; for (int y = 0; y < spacing; y++) { for (int x = 0; x < spacing; x++) { byte bltVal = (x >= bitmap.Width || y >= bitmap.Rows) ? (byte)0 : bitmapData[x + bitmap.Width * y]; int index = 4 * ((x + blitX) + (y + blitY) * _textureSize); textureData[index] = 255; textureData[index + 1] = 255; textureData[index + 2] = 255; textureData[index + 3] = bltVal; /* Experimental Outlining of text * int[] xOffsets = new int[]{ * -1, -1, -1, 0, 1, 1, 1, 0 * }; * * int[] yOffsets = new int[]{ * 1, 0, -1, -1, -1, 0, 1, 1 * }; * * if (bltVal != 0) * { * int outlineThickness = 1; * bool done = false; * for (int dir = 0; dir < 8; dir++) * { * int xOffsetBase = xOffsets[dir]; * int yOffsetBase = yOffsets[dir]; * for (int j = 1; j <= outlineThickness; j++) * { * int xOffset = xOffsetBase * j; * int yOffset = yOffsetBase * j; * * byte nextVal = (x + xOffset < 0 || x + xOffset >= bitmap.Width || y + yOffset < 0 || y + yOffset >= bitmap.Rows) ? (byte)0 * : bitmapData[(x + xOffset) + bitmap.Width * (y + yOffset)]; * if (nextVal == 0) * { * outlineData[index] = 255; * outlineData[index + 1] = 255; * outlineData[index + 2] = 255; * outlineData[index + 3] = 255; * done = true; * break; * } * } * if (done) * break; * * * } * } */ } } _fontGlyphs[i].GlpyhID = glyphIndex; Shape glyphRect = ShapeFactory.GenerateRectangle(); glyphRect.SetTextureCoordOffset(blitX / (float)_textureSize, blitY / (float)_textureSize); glyphRect.SetTextureCoordScale(bitmap.Width / (float)_textureSize, bitmap.Rows / (float)_textureSize); _fontGlyphs[i].GlyphRect = glyphRect; _fontGlyphs[i].SourceX = blitX / (float)_textureSize; _fontGlyphs[i].SourceY = blitY / (float)_textureSize; _fontGlyphs[i].SourceWidth = bitmap.Width / (float)_textureSize; _fontGlyphs[i].SourceHeight = bitmap.Rows / (float)_textureSize; _fontGlyphs[i].RealWidth = bitmap.Width; _fontGlyphs[i].RealHeight = bitmap.Rows; if (_lineHeight < bitmap.Rows) { _lineHeight = bitmap.Rows; } _fontGlyphs[i].BearingX = (int)_fontFace.Glyph.Metrics.HorizontalBearingX; _fontGlyphs[i].BearingY = (int)_fontFace.Glyph.Metrics.HorizontalBearingY; _fontGlyphs[i].AdvanceX = (int)_fontFace.Glyph.Advance.X; _fontGlyphs[i].TextureID = _textureID; _fontGlyphs[i].Loaded = true; } catch { _fontGlyphs[i].Loaded = false; } } Texture.BindTexture(_textureID); GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, _textureSize, _textureSize, 0, OpenTK.Graphics.OpenGL.PixelFormat.Rgba, PixelType.UnsignedByte, textureData); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1); }