예제 #1
0
        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, @"C:\Windows\Fonts\tahoma.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");
        }
예제 #2
0
		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, @"C:\Windows\Fonts\tahoma.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");
		}
예제 #3
0
		private void listBoxFont_SelectedIndexChanged(object sender, EventArgs e)
		{
			fontFace = new Face(lib, Path.Combine(Path.GetFullPath(fontFolder), (string)listBoxFont.SelectedItem));
			fontFace.SetCharSize(0, 62, 0, 96);

            dataGridView1.Columns.Add("PlatformId", "PlatformId");
            dataGridView1.Columns.Add("Encoding", "Encoding");
            dataGridView1.Columns.Add("EncodingId", "EncodingId");
            CharMap[] cmaps = fontFace.CharMaps;
            foreach(CharMap cmap in cmaps)
            {
                dataGridView1.Rows.Add(cmap.PlatformId, cmap.Encoding, cmap.EncodingId);
            }

            Header headerTable = (Header)fontFace.GetSfntTable(SfntTag.Header);
            HoriHeader horiHeaderTable = (HoriHeader)fontFace.GetSfntTable(SfntTag.HorizontalHeader);
            MaxProfile maxpTable = (MaxProfile)fontFace.GetSfntTable(SfntTag.MaxProfile);
            OS2 os2Table = (OS2)fontFace.GetSfntTable(SfntTag.OS2);
            Pclt PcltTable = (Pclt)fontFace.GetSfntTable(SfntTag.Pclt);
            Postscript postTable = (Postscript)fontFace.GetSfntTable(SfntTag.Postscript);
            VertHeader vertTable = (VertHeader)fontFace.GetSfntTable(SfntTag.VertHeader);

            pictureBoxText.Invalidate();
        }
예제 #4
0
 private void SetFontFaceSize(Face fontFace, Vector2 size)
 {
     // calculate and set the size of the font
     // size is in 26.6 factional points (that is in 1/64th of points)
     // 72 => the sizes are in "points" (=1/72 inch), setting resolution to 72 dpi let us specify the size in pixels directly
     fontFace.SetCharSize((int)Math.Ceiling(size.X * 64), (int)Math.Ceiling(size.Y * 64), 72, 72);
 }
예제 #5
0
        void BuildTextureOld()
        {
            #region attribution
            // Significant parts of this method were based off the following example:
            // https://github.com/Robmaister/SharpFont/blob/master/Source/Examples/Program.cs
            // The following license and attribution applies to those parts:

            /*Copyright (c) 2012 Robert Rouhani <*****@*****.**>
            Permission is hereby granted, free of charge, to any person obtaining a copy of
            this software and associated documentation files (the "Software"), to deal in
            the Software without restriction, including without limitation the rights to
            use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
            of the Software, and to permit persons to whom the Software is furnished to do
            so, subject to the following conditions:
            The above copyright notice and this permission notice shall be included in all
            copies or substantial portions of the Software.
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
            IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
            FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
            AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
            LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
            OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
            SOFTWARE.*/
            #endregion

            Face face = new Face(ftLib, "C:\\Windows\\Fonts\\segoeui.ttf");
            face.SetCharSize(0, 14, 72, 72);
            //face.SetPixelSizes(0, 14);

            const LoadFlags loadFlags = LoadFlags.Default;
            const LoadTarget loadTarget = LoadTarget.Light;
            const RenderMode renderMode = RenderMode.Light;

            float cx = 0, cy = 0, tw = 0, th = 0;

            // base size
            face.LoadGlyph(face.GetCharIndex('A'), loadFlags, loadTarget);
            th = (float)face.Glyph.Metrics.Height;

            for (int i = 0; i < text.Length; i++) {
                char c = text[i];
                uint cnum = face.GetCharIndex(c);
                face.LoadGlyph(cnum, loadFlags, loadTarget);
                tw += (float)face.Glyph.Advance.X;
                if (face.HasKerning && i < text.Length - 1)  tw += (float)face.GetKerning(cnum, face.GetCharIndex(text[i + 1]), KerningMode.Default).X;
                th = Math.Max(th, (float)face.Glyph.Metrics.Height);

            }
            if (tw == 0) tw = th;

            Bitmap bmp = new Bitmap((int)Math.Ceiling(tw), (int)Math.Ceiling(th*2)); // assumption that any downstem is at most half the height of a capital letter
            cy = th * 0.5f; // adjustment for such
            //Bitmap bmp = new Bitmap(128, 32);
            System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bmp);
            g.Clear(System.Drawing.Color.Transparent);
            //g.Clear(System.Drawing.Color.DimGray);

            for (int i = 0; i < text.Length; i++) {
                char c = text[i];
                uint cnum = face.GetCharIndex(c);
                face.LoadGlyph(cnum, loadFlags, loadTarget);
                face.Glyph.RenderGlyph(renderMode);
                if (c == ' ') {
                    cx += (float)face.Glyph.Advance.X;
                    // omitted an if statement that didn't seem to do anything relevant??
                    cy += (float)face.Glyph.Advance.Y;
                    continue;
                }

                FTBitmap ftb = face.Glyph.Bitmap; // lol ftb
                Bitmap cb = ftb.ToGdipBitmap(System.Drawing.Color.White);
                g.DrawImageUnscaled(cb, (int)Math.Round(cx + face.Glyph.BitmapLeft), (int)Math.Round(cy + (Math.Ceiling(th) - face.Glyph.BitmapTop))); // th and not bitmap.height
                cx += (float)face.Glyph.Metrics.HorizontalAdvance;
                cy += (float)face.Glyph.Advance.Y;
                if (face.HasKerning && i < text.Length - 1) cx += (float)face.GetKerning(cnum, face.GetCharIndex(text[i + 1]), KerningMode.Default).X;
            }
            g.Dispose();
            if (texture != null) texture.Dispose();
            //texture = GraphicsManager.ConvertToPreMultipliedAlphaGPU(GetTexture(GraphicsManager.device, bmp));
            texture = GetTexture(GraphicsManager.device, bmp);
        }
예제 #6
0
        private void InitFont(float scaleFactor)
        {
            try {
                System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew();

                ScaleFactor   = scaleFactor;
                YOffsetScaled = YOffset * scaleFactor;

                // Reset everything
                Clear();

                Font = new Face(FontManager.Library, FilePath);

                // Go on

                float size = Size.Scale(ScaleFactor);

                Fixed26Dot6 sz = new Fixed26Dot6(size / 64);
                Font.SetCharSize(sz, sz, 72, 72);

                int pixelSize = (size * 1.3334).Ceil();
                Font.SetPixelSizes((uint)pixelSize, (uint)pixelSize);

                GlyphCount = Font.GlyphCount;
                int glyphCount = GlyphCount;
                Monospace = Font.FaceFlags.HasFlag(FaceFlags.FixedWidth);

                string tmpName = Font.GetPostscriptName();
                if (!String.IsNullOrEmpty(tmpName))
                {
                    Name = tmpName;
                }


                // We support 4 different glyph loading strategies:
                //
                // (1) All: all glyphs loaded at once on start
                // (2) Filtered: all filtered glyphs loaded at once on start
                // (3) OnDemand: no glyphs loaded at start, all glyphs on demand


                if (OnDemand)
                {
                    // Startegy (3)
                    GlyphCount = 0;
                }
                else if (Filter > GlyphFilterFlags.OnDemand)
                {
                    // Startegy (2)
                    // If we have a Filter set, let's count the number of valid glyphs
                    // to minimize graphics memory.
                    uint glyphindex;
                    uint cc    = Font.GetFirstChar(out glyphindex);
                    int  count = 0;
                    while (glyphindex > 0)
                    {
                        char c = (char)cc;
                        if (Filter.IsValid(c))
                        {
                            count++;
                        }
                        cc = Font.GetNextChar(cc, out glyphindex);
                    }
                    GlyphCount = count;
                }
                else
                {
                    // Strategy (1), loading the entire font
                }

                m_Textures = new int[Math.Max(32, GlyphCount)];
                CharMap    = new ThreadSafeDictionary <char, GlyphInfo>(Math.Max(31, GlyphCount));

                if (!OnDemand)
                {
                    // Strategy (1) + (2): Load all or filtered glyphs
                    m_ListBase = GL.GenLists(GlyphCount);
                    GL.GenTextures(GlyphCount, m_Textures);

                    uint glyphindex;
                    uint cc = Font.GetFirstChar(out glyphindex);
                    while (glyphindex > 0)
                    {
                        char c = (char)cc;
                        if (!CharMap.ContainsKey(c) && Filter.IsValid(c))
                        {
                            try {
                                CharMap.Add(c, CompileCharacter(Font, glyphindex, c));
                            } catch (Exception ex) {
                                ex.LogWarning();
                            }
                        }
                        cc = Font.GetNextChar(cc, out glyphindex);
                    }
                    CharMap.TryGetValue(SpecialCharacters.Ellipsis, out m_EllipsisGlyphIndex);
                }
                else
                {
                    try {
                        GetGlyphIndex(SpecialCharacters.Ellipsis, out m_EllipsisGlyphIndex);
                    } catch (Exception ex) {
                        ex.LogError();
                    }
                }

                //if (Height <= 1)
                //Height = pixelSize.NextPowerOf2();
                //Height = pixelSize * 1.33335f;

                Height = pixelSize;

                float fscale = Height / Font.Height * 1.33334f;
                //float fscale = Height / Font.Height * 0.776f;

                Ascender  = Font.Ascender * fscale;
                Descender = Font.Descender * fscale;
                //HalfHeight = Height / 2;

                Height     = (Ascender).Ceil();
                HalfHeight = (int)(Height / 2);

                //LineHeight = Height * 1.42f * LineSpacing;
                LineHeight = (int)((Height * 1.42f * LineSpacing) + 0.5f);

                //TextBoxHeight = ((Height * 2f) + (ScaleFactor * 2f)).Ceil();
                //TextBoxHeight = (int)(Height * 1.85f + 0.5f);
                TextBoxHeight = (int)(Height * 1.85f + 2);
                CaptionHeight = (int)(Height * 1.55 + 2);

                YOffsetScaled = (YOffset * ScaleFactor) - HalfHeight;

                if (OnDemand)
                {
                    Count.LogInformation("Font {0} ({1}), {2}/{3} glyphs pre-loaded in {4} ms, more glyphs are loaded on demand.", Name, Size, Count, glyphCount, sw.ElapsedMilliseconds);
                }
                else
                {
                    Count.LogInformation("Font {0} ({1}), {2}/{3} glyphs loaded in {4} ms.", Name, Size, Count, glyphCount, sw.ElapsedMilliseconds);
                }
            } catch (Exception ex) {
                ex.LogError();
            } finally {
                if (!OnDemand && Font != null)
                {
                    Font.Dispose();
                    Font = null;
                }
            }
        }
예제 #7
0
 private void listBoxFont_SelectedIndexChanged(object sender, EventArgs e)
 {
     fontFace = new Face(lib, Path.Combine(Path.GetFullPath(fontFolder), (string)listBoxFont.SelectedItem));
     fontFace.SetCharSize(0, 62, 0, 96);
     pictureBoxText.Invalidate();
 }
예제 #8
0
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            string hello = "The quick brown fox jumps over the lazy dog.";

            charCache = new Dictionary<char, GlyphData>();

            Library lib = new Library();
            Face fontFace = new Face(lib, "fonts/roboto-regular.ttf");

            fontFace.SetCharSize(0, 18 * 64, 0, 96);

            int wX          = 0;
            int wY          = 0;

            int xB          = 0;

            int pX          = 0;
            int pY          = 0;

            uint current    = 0;
            uint previous   = 0;

            GlyphData       data;

            DateTime iTimeS = DateTime.Now;

            foreach (var item in hello)
            {
                current = fontFace.GetCharIndex(item);

                if (!charCache.ContainsKey(item))
                {
                    fontFace.LoadGlyph(current, LoadFlags.Default, LoadTarget.Normal);
                    fontFace.Glyph.RenderGlyph(RenderMode.Normal);

                    FTBitmap bitmap = fontFace.Glyph.Bitmap;

                    data = new GlyphData();

                    if (item != ' ')
                        data.buffer = bitmap.BufferData;

                    data.charIndex  = current;

                    data.metrics    = fontFace.Glyph.Metrics;

                    data.height     = fontFace.Glyph.Metrics.Height / 64;
                    data.width      = fontFace.Glyph.Metrics.Width / 64;

                    data.pitch      = fontFace.Glyph.BitmapTop;
                    data.forward    = fontFace.Glyph.BitmapLeft;

                    data.aX         = fontFace.Glyph.Metrics.HorizontalAdvance;
                    data.aY         = fontFace.Glyph.Metrics.VerticalAdvance;

                    charCache.Add(item, data);
                }
                else
                {
                    data = charCache[item];
                }

                wX     += data.aX / 64;

                if (fontFace.HasKerning && previous != 0 && current != 0)
                {
                    var kInfo = fontFace.GetKerning(previous, current, KerningMode.Default);

                    wX += kInfo.X / 64;

                    data.kX = kInfo.X / 64;
                    data.kY = kInfo.Y / 64;
                }

                previous = current;
            }

            xB = Math.Abs(fontFace.Size.Metrics.Descender / 64);
            wY = fontFace.Size.Metrics.Height / 64;

            DateTime iTimeF = DateTime.Now;

            Console.WriteLine("Time in letting freetype render the glyphs: {0} milliseconds.", (iTimeF - iTimeS).TotalMilliseconds);

            bmp = new Bitmap(wX, wY);

            int[] map = new int[wX * wY];

            for (int i = 0; i < map.Length; i++ )
            {
                map[i] = 0;
            }

            current     = 0;
            previous    = 0;

            DateTime timeS = DateTime.Now;

            for (int i = 0; i < hello.Length; i++)
            {
                GlyphData pdata = charCache[hello[i]];

                for (int y = 0; y < pdata.height; y++)
                {
                    for (int x = 0; x < pdata.width; x++)
                    {
                        int fx = x + pX + pdata.forward;
                        int fy = wY - pdata.pitch + y - xB;

                        fy = y + (wY - pdata.pitch - xB);

                        if (fy < 0 || fy >= wY)
                        {
                            //Console.WriteLine("Overflow on fy! :(");
                            continue;
                        }

                        if (fx < 0 || fx >= wX)
                        {
                            //Console.WriteLine("Overflow on fx! :(");
                            continue;
                        }

                        int fdata = pdata.buffer[y * pdata.width + x] + map[fy * wX + fx];

                        if (fdata >= 255)
                            fdata = 255;

                        map[fy * wX + fx] = (fdata << 24);
                    }
                }

                pX += pdata.aX / 64;
                pX += pdata.kX;
            }

            BitmapData bData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);

            Marshal.Copy(map, 0, bData.Scan0, map.Length);

            bmp.UnlockBits(bData);

            map = null;

            DateTime timeF = DateTime.Now;

            Console.WriteLine("Time in mapping them pixels: {0} milliseconds.", (timeF- timeS).TotalMilliseconds);

            GC.Collect();

            ClientSize      = new System.Drawing.Size(wX, wY);
            StartPosition   = FormStartPosition.CenterScreen;

            BackColor       = Color.White;

            Invalidate();
        }