Example #1
0
    /// <summary>
    /// Retrieve the list of faces from the specified font. For example: regular, bold, italic.
    /// </summary>

    static public string[] GetFaces(Font font)
    {
        if (font == null || !isPresent)
        {
            return(null);
        }

        string[] names = null;
        IntPtr   lib   = IntPtr.Zero;
        IntPtr   face  = IntPtr.Zero;

        if (FT_Init_FreeType(out lib) != 0)
        {
            Debug.LogError("Failed to initialize FreeType");
            return(null);
        }

        string fileName = Application.dataPath.Substring(0, Application.dataPath.Length - "Assets".Length) +
                          UnityEditor.AssetDatabase.GetAssetPath(font);

        if (File.Exists(fileName))
        {
            if (FT_New_Face(lib, fileName, 0, out face) != 0)
            {
                Debug.LogError("Unable to use the chosen font (FT_New_Face).");
            }
            else
            {
                FT_FaceRec record = (FT_FaceRec)Marshal.PtrToStructure(face, typeof(FT_FaceRec));
                names = new string[record.num_faces];

                for (int i = 0; i < record.num_faces; i++)
                {
                    IntPtr ptr = IntPtr.Zero;

                    if (FT_New_Face(lib, fileName, i, out ptr) == 0)
                    {
                        string family = Marshal.PtrToStringAnsi(record.family_name);
                        string style  = Marshal.PtrToStringAnsi(record.style_name);
                        names[i] = family + " - " + style;
                        FT_Done_Face(ptr);
                    }
                }
            }
        }
        if (face != IntPtr.Zero)
        {
            FT_Done_Face(face);
        }
#if !UNITY_3_5
        if (lib != IntPtr.Zero)
        {
            FT_Done_FreeType(lib);
        }
#endif
        return(names);
    }
Example #2
0
        public override int GetCharWidth(PDFFont pdfFont, TTFontData data,
                                         char charCode)
        {
            InitLibrary();

            int aint = (int)charCode;

            if (data.Widths.IndexOfKey(charCode) >= 0)
            {
                return(data.Widths[charCode]);
            }
            LogFontFt cfont = data.LogFont;

            cfont.OpenFont();

            int awidth = 0;

            Monitor.Enter(flag);
            try
            {
                if (data.Widths.IndexOfKey(charCode) >= 0)
                {
                    awidth = data.Widths[charCode];
                }
                else
                {
                    if (0 == FT.FT_Load_Char(cfont.iface, (uint)charCode, (int)FT.FT_LOAD_NO_SCALE))
                    {
                        FT_FaceRec      aface  = (FT_FaceRec)Marshal.PtrToStructure(cfont.iface, typeof(FT_FaceRec));
                        FT_GlyphSlotRec aglyph = (FT_GlyphSlotRec)Marshal.PtrToStructure(aface.glyph, typeof(FT_GlyphSlotRec));
                        ushort          width1 = (ushort)(aglyph.linearHoriAdvance >> 16);
                        ushort          width2 = (ushort)(aglyph.linearHoriAdvance & 0x0000FFFF);
                        double          dwidth = width1 + width2 / (double)65535;
                        awidth = System.Convert.ToInt32(Math.Round(cfont.widthmult * dwidth));
                    }
                    data.Widths[charCode] = awidth;
                    data.Glyphs[charCode] = System.Convert.ToInt32(FT.FT_Get_Char_Index(cfont.iface, charCode));
                    if (data.FirstLoaded > aint)
                    {
                        data.FirstLoaded = aint;
                    }
                    if (data.LastLoaded < aint)
                    {
                        data.LastLoaded = aint;
                    }
                }
            }
            finally
            {
                Monitor.Exit(flag);
            }
            return(awidth);
        }
Example #3
0
        /// <summary>
        /// Creates a new font set.
        /// </summary>
        /// <param name="family">The font family.</param>
        /// <param name="size">Size in pixels.</param>
        /// <param name="resolution">Resolution in dpi.</param>
        public FontAssetCore(FontFamily family, int size, uint resolution)
        {
            _family     = family;
            _resolution = resolution;

            FT_FaceRec face = (FT_FaceRec)Marshal.PtrToStructure(_family.Face, typeof(FT_FaceRec));

            _charSet = new BitmapCharacterSet(face.num_glyphs)
            {
                RenderedSize = size,
                Width        = MAX_WIDTH,
                Height       = MAX_HEIGHT
            };
            _charSet.Ascender = _charSet.RenderedSize * face.ascender / face.height;
        }
Example #4
0
        /// <summary>
        /// Render the font to a series of OpenGL textures (one per letter)
        /// </summary>
        /// <param name="fontsize">size of the font</param>
        /// <param name="DPI">dots-per-inch setting</param>
        public void ftRenderToTexture(int fontsize, uint DPI)
        {
            font_size = fontsize;

            face = (FT_FaceRec)Marshal.PtrToStructure(faceptr, typeof(FT_FaceRec));
            Console.WriteLine("Num Faces:" + face.num_faces.ToString());
            Console.WriteLine("Num Glyphs:" + face.num_glyphs.ToString());
            Console.WriteLine("Num Char Maps:" + face.num_charmaps.ToString());
            Console.WriteLine("Font Family:" + face.family_name);
            Console.WriteLine("Style Name:" + face.style_name);
            Console.WriteLine("Generic:" + face.generic);
            Console.WriteLine("Bbox:" + face.bbox);
            Console.WriteLine("Glyph:" + face.glyph);
            //   IConsole.Write("Num Glyphs:", );

            //Freetype measures the font size in 1/64th of pixels for accuracy
            //so we need to request characters in size*64
            FT.FT_Set_Char_Size(faceptr, font_size << 6, font_size << 6, DPI, DPI);

            //Provide a reasonably accurate estimate for expected pixel sizes
            //when we later on create the bitmaps for the font
            FT.FT_Set_Pixel_Sizes(faceptr, (uint)font_size, (uint)font_size);


            // Once we have the face loaded and sized we generate opengl textures
            // from the glyphs  for each printable character
            Console.WriteLine("Compiling Font Characters 0..127");
            textures  = new int[128];
            extent_x  = new int[128];
            offsets   = new FTGlyphOffset[128];
            list_base = Gl.glGenLists(128);
            Gl.glGenTextures(128, textures);
            for (int c = 0; c < 128; c++)
            {
                CompileCharacterToTexture(face, c);

                if (c < 127)
                {
                    sChars += ",";
                }
            }
            //Console.WriteLine("Font Compiled:" + sChars);
        }
Example #5
0
 public void OpenFont()
 {
     if (faceinit)
     {
         return;
     }
     Monitor.Enter(FontInfoFt.flag);
     try
     {
         if (FontFaces.IndexOfKey(keyname) >= 0)
         {
             iface    = FontFaces[keyname];
             faceinit = true;
         }
         else
         {
             FontInfoFt.CheckFreeType(FT.FT_New_Face(ftlibrary, filename, 0, out iface));
             FT_FaceRec aface = new FT_FaceRec();
             FontInfoFt.CheckFreeType(FT.FT_New_Face(ftlibrary, filename, 0, out iface));
             aface    = (FT_FaceRec)Marshal.PtrToStructure(iface, typeof(FT_FaceRec));
             faceinit = true;
             if (type1)
             {
                 kerningfile = System.IO.Path.ChangeExtension(filename, ".afm");
                 if (File.Exists(kerningfile))
                 {
                     FontInfoFt.CheckFreeType(FT.FT_Attach_File(iface, kerningfile));
                 }
             }
             // Don't need scale, but this is a scale that returns
             // exact widht for pdf if you divide the result
             // of Get_Char_Width by 64
             FontInfoFt.CheckFreeType(FT.FT_Set_Char_Size(iface, 0, 64 * 100, 720, 720));
             FontFaces.Add(keyname, iface);
         }
     }
     finally
     {
         Monitor.Exit(FontInfoFt.flag);
     }
 }
Example #6
0
        public Font(string font, uint size)
        {
            if (!File.Exists(font))
            {
                throw new FileNotFoundException("Failed to load font file:" + font);
            }
            Size = size;
            if (Graphics.Instance.GraphicsDevice == null)
            {
                throw new NullReferenceException("Graphics Device is null.");
            }
            gd = Graphics.Instance.GraphicsDevice;
            IntPtr libptr;
            int    ret = FT.FT_Init_FreeType(out libptr);

            if (ret != 0)
            {
                throw new Exception("Failed to load FreeType library.");
            }

            int retb = FT.FT_New_Face(libptr, font, 0, out faceptr);

            if (retb != 0)
            {
                throw new Exception("Failed to create font face.");
            }

            face = (FT_FaceRec)Marshal.PtrToStructure(faceptr, typeof(FT_FaceRec));
            FT.FT_Set_Char_Size(faceptr, (int)size << 6, (int)size << 6, 96, 96);
            FT.FT_Set_Pixel_Sizes(faceptr, size, size);
            ascender      = face.ascender >> 6;
            descender     = face.descender >> 6;
            fontheight    = ((face.height >> 6) + descender + ascender) / 4;
            yoffset       = (int)(Size - ascender);
            baseCharacter = CreateChar('i');
        }
Example #7
0
        private bool AddGlyphInternal(uint glyphIndex)
        {
            // FreeType measures font size in terms Of 1/64ths of a point.
            // 1 point = 1/72th of an inch. Resolution is in dots (pixels) per inch.
            // Locking is also required here to avoid accessing to texture when handling glyphs (can lead to AccessViolationException)
            lock (_syncObj)
            {
                float pointSize = 64.0f * _charSet.RenderedSize * 72.0f / _resolution;
                FT.FT_Set_Char_Size(_family.Face, (int)pointSize, 0, _resolution, 0);

                // Font does not contain that glyph, the 'missing' glyph will be shown instead
                if (glyphIndex == 0 && _charSet.GetCharacter(0) != null)
                {
                    return(false);
                }

                // Load the glyph for the current character.
                if (FT.FT_Load_Glyph(_family.Face, glyphIndex, FT.FT_LOAD_DEFAULT) != 0)
                {
                    return(false);
                }

                FT_FaceRec face = (FT_FaceRec)Marshal.PtrToStructure(_family.Face, typeof(FT_FaceRec));

                IntPtr glyphPtr;
                // Load the glyph data into our local array.
                if (FT.FT_Get_Glyph(face.glyph, out glyphPtr) != 0)
                {
                    return(false);
                }

                // Convert the glyph to bitmap form.
                if (FT.FT_Glyph_To_Bitmap(ref glyphPtr, FT_Render_Mode.FT_RENDER_MODE_NORMAL, IntPtr.Zero, 1) != 0)
                {
                    return(false);
                }

                // Get the structure fron the intPtr
                FT_BitmapGlyph glyph = (FT_BitmapGlyph)Marshal.PtrToStructure(glyphPtr, typeof(FT_BitmapGlyph));

                // Width/height of char
                int cwidth  = glyph.bitmap.width;
                int cheight = glyph.bitmap.rows;

                // Width/height of char including padding
                int pwidth  = cwidth + 3 * PAD;
                int pheight = cheight + 3 * PAD;

                // Check glyph index is in the character set range.
                if (!_charSet.IsInRange(glyphIndex))
                {
                    return(false);
                }

                // Check glyph fits in our texture
                if (_currentX + pwidth > MAX_WIDTH)
                {
                    _currentX  = 0;
                    _currentY += _rowHeight;
                    _rowHeight = 0;
                }
                if (_currentY + pheight > MAX_HEIGHT)
                {
                    return(false);
                }

                // Create and store a BitmapCharacter for this glyph
                _charSet.SetCharacter(glyphIndex, CreateCharacter(glyph));

                // Copy the glyph bitmap to our local array
                Byte[] bitmapBuffer = new Byte[cwidth * cheight];
                if (glyph.bitmap.buffer != IntPtr.Zero)
                {
                    Marshal.Copy(glyph.bitmap.buffer, bitmapBuffer, 0, cwidth * cheight);
                }

                // Write glyph bitmap to our texture
                WriteGlyphToTexture(glyph, pwidth, pheight, bitmapBuffer);

                _currentX += pwidth;
                _rowHeight = Math.Max(_rowHeight, pheight);

                // Free the glyph
                FT.FT_Done_Glyph(glyphPtr);
            }
            return(true);
        }
Example #8
0
    /// <summary>
    /// Create a bitmap font from the specified dynamic font.
    /// </summary>

    static public bool CreateFont(Font ttf, int size, int faceIndex, bool kerning, string characters, int padding, out BMFont font, out Texture2D tex)
    {
        font = null;
        tex  = null;

        if (ttf == null || !isPresent)
        {
            return(false);
        }

        IntPtr lib  = IntPtr.Zero;
        IntPtr face = IntPtr.Zero;

        if (FT_Init_FreeType(out lib) != 0)
        {
            Debug.LogError("Failed to initialize FreeType");
            return(false);
        }

        string fileName = Application.dataPath.Substring(0, Application.dataPath.Length - "Assets".Length) +
                          UnityEditor.AssetDatabase.GetAssetPath(ttf);

        if (!File.Exists(fileName))
        {
            Debug.LogError("Unable to use the chosen font.");
        }
        else if (FT_New_Face(lib, fileName, faceIndex, out face) != 0)
        {
            Debug.LogError("Unable to use the chosen font (FT_New_Face).");
        }
        else
        {
            font          = new BMFont();
            font.charSize = size;

            Color32          white    = Color.white;
            List <int>       entries  = new List <int>();
            List <Texture2D> textures = new List <Texture2D>();

            FT_FaceRec faceRec = (FT_FaceRec)Marshal.PtrToStructure(face, typeof(FT_FaceRec));
            FT_Set_Pixel_Sizes(face, 0, (uint)size);

            // Calculate the baseline value that would let the printed font be centered vertically
            //int ascender = (faceRec.met.ascender >> 6);
            //int descender = (faceRec.descender >> 6);
            //int baseline = ((ascender - descender) >> 1);
            //if ((baseline & 1) == 1) --baseline;

            //Debug.Log(ascender + " " + descender + " " + baseline);

            // Space character is not renderable
            FT_Load_Glyph(face, FT_Get_Char_Index(face, 32), FT_LOAD_DEFAULT);
            FT_GlyphSlotRec space = (FT_GlyphSlotRec)Marshal.PtrToStructure(faceRec.glyph, typeof(FT_GlyphSlotRec));

            // Space is not visible and doesn't have a texture
            BMGlyph spaceGlyph = font.GetGlyph(32, true);
            spaceGlyph.offsetX = 0;
            spaceGlyph.offsetY = 0;
            spaceGlyph.advance = (space.metrics.horiAdvance >> 6);
            spaceGlyph.channel = 15;
            spaceGlyph.x       = 0;
            spaceGlyph.y       = 0;
            spaceGlyph.width   = 0;
            spaceGlyph.height  = 0;

            // Save kerning information
            if (kerning)
            {
                for (int b = 0; b < characters.Length; ++b)
                {
                    uint ch2 = characters[b];
                    if (ch2 == 32)
                    {
                        continue;
                    }

                    FT_Vector vec;
                    if (FT_Get_Kerning(face, ch2, 32, 0, out vec) != 0)
                    {
                        continue;
                    }

                    int offset = (vec.x >> 6);
                    if (offset != 0)
                    {
                        spaceGlyph.SetKerning((int)ch2, offset);
                    }
                }
            }

            // Run through all requested characters
            foreach (char ch in characters)
            {
                uint charIndex = FT_Get_Char_Index(face, (uint)ch);
                FT_Load_Glyph(face, charIndex, FT_LOAD_DEFAULT);
                FT_GlyphSlotRec glyph = (FT_GlyphSlotRec)Marshal.PtrToStructure(faceRec.glyph, typeof(FT_GlyphSlotRec));
                FT_Render_Glyph(ref glyph, FT_Render_Mode.FT_RENDER_MODE_NORMAL);

                if (glyph.bitmap.width > 0 && glyph.bitmap.rows > 0)
                {
                    byte[] buffer = new byte[glyph.bitmap.width * glyph.bitmap.rows];
                    Marshal.Copy(glyph.bitmap.buffer, buffer, 0, buffer.Length);

                    Texture2D texture = new Texture2D(glyph.bitmap.width, glyph.bitmap.rows, UnityEngine.TextureFormat.ARGB32, false);
                    Color32[] colors  = new Color32[buffer.Length];

                    for (int i = 0, y = 0; y < glyph.bitmap.rows; ++y)
                    {
                        for (int x = 0; x < glyph.bitmap.width; ++x)
                        {
                            white.a = buffer[i++];
                            colors[x + glyph.bitmap.width * (glyph.bitmap.rows - y - 1)] = white;
                        }
                    }

                    // Save the texture
                    texture.SetPixels32(colors);
                    texture.Apply();
                    textures.Add(texture);
                    entries.Add(ch);

                    // Record the metrics
                    BMGlyph bmg = font.GetGlyph(ch, true);
                    bmg.offsetX = (glyph.metrics.horiBearingX >> 6);
                    bmg.offsetY = -(glyph.metrics.horiBearingY >> 6);
                    bmg.advance = (glyph.metrics.horiAdvance >> 6);
                    bmg.channel = 15;

                    // Save kerning information
                    if (kerning)
                    {
                        for (int b = 0; b < characters.Length; ++b)
                        {
                            uint ch2 = characters[b];
                            if (ch2 == ch)
                            {
                                continue;
                            }

                            FT_Vector vec;
                            if (FT_Get_Kerning(face, ch2, ch, 0, out vec) != 0)
                            {
                                continue;
                            }

                            int offset = (vec.x >> 6);
                            if (offset != 0)
                            {
                                bmg.SetKerning((int)ch2, offset);
                            }
                        }
                    }
                }
            }

            // Create a packed texture with all the characters
            tex = new Texture2D(32, 32, TextureFormat.ARGB32, false);
            Rect[] rects = tex.PackTextures(textures.ToArray(), padding);

            // Make the RGB channel pure white
            Color32[] cols = tex.GetPixels32();
            for (int i = 0, imax = cols.Length; i < imax; ++i)
            {
                Color32 c = cols[i];
                c.r     = 255;
                c.g     = 255;
                c.b     = 255;
                cols[i] = c;
            }
            tex.SetPixels32(cols);
            tex.Apply();

            font.texWidth  = tex.width;
            font.texHeight = tex.height;

            int min = int.MaxValue;
            int max = int.MinValue;

            // Other glyphs are visible and need to be added
            for (int i = 0, imax = entries.Count; i < imax; ++i)
            {
                // Destroy the texture now that it's a part of an atlas
                UnityEngine.Object.DestroyImmediate(textures[i]);
                textures[i] = null;
                Rect rect = rects[i];

                // Set the texture coordinates
                BMGlyph glyph = font.GetGlyph(entries[i], true);
                glyph.x      = Mathf.RoundToInt(rect.x * font.texWidth);
                glyph.y      = Mathf.RoundToInt(rect.y * font.texHeight);
                glyph.width  = Mathf.RoundToInt(rect.width * font.texWidth);
                glyph.height = Mathf.RoundToInt(rect.height * font.texHeight);

                // Flip the Y since the UV coordinate system is different
                glyph.y = font.texHeight - glyph.y - glyph.height;

                max = Mathf.Max(max, -glyph.offsetY);
                min = Mathf.Min(min, -glyph.offsetY - glyph.height);
            }

            int baseline = size + min;
            baseline += ((max - min - size) >> 1);

            // Offset all glyphs so that they are not using the baseline
            for (int i = 0, imax = entries.Count; i < imax; ++i)
            {
                BMGlyph glyph = font.GetGlyph(entries[i], true);
                glyph.offsetY += baseline;
            }
        }

        if (face != IntPtr.Zero)
        {
            FT_Done_Face(face);
        }
#if !UNITY_3_5
        if (lib != IntPtr.Zero)
        {
            FT_Done_FreeType(lib);
        }
#endif
        return(tex != null);
    }
Example #9
0
		private void CompileCharacterToTexture(FT_FaceRec face, int c)
		{
			FTGlyphOffset offset = new FTGlyphOffset();

			//We first convert the number index to a character index
			uint index = FT.FT_Get_Char_Index(faceptr, (uint)c);

			string sError = "";
			if (index == 0) sError = "No Glyph";

			//Here we load the actual glyph for the character
			int ret = FT.FT_Load_Glyph(faceptr, index, FT.FT_LOAD_DEFAULT);
			if (ret != 0)
			{
				Console.Write("Load_Glyph failed for character " + c.ToString());
			}

			FT_GlyphSlotRec glyphrec = (FT_GlyphSlotRec)Marshal.PtrToStructure(face.glyph, typeof(FT_GlyphSlotRec));

			ret = FT.FT_Render_Glyph(ref glyphrec, FT_Render_Mode.FT_RENDER_MODE_NORMAL);

			if (ret != 0)
			{
				Console.Write("Render failed for character " + c.ToString());
			}

			int size = (glyphrec.bitmap.width * glyphrec.bitmap.rows);
			if (size <= 0)
			{
				//Console.Write("Blank Character: " + c.ToString());
				//space is a special `blank` character
				extent_x[c] = 0;
				if (c == 32)
				{
					Gl.glNewList((list_base + c), Gl.GL_COMPILE);
					Gl.glTranslatef(font_size >> 1, 0, 0);
					extent_x[c] = font_size >> 1;
					Gl.glEndList();
					offset.left = 0;
					offset.top = 0;
					offset.height = 0;
					offset.width = extent_x[c];
					offsets[c] = offset;
				}
				return;

			}

			byte[] bmp = new byte[size];
			Marshal.Copy(glyphrec.bitmap.buffer, bmp, 0, bmp.Length);

			//Next we expand the bitmap into an opengl texture 	    	
			int width = next_po2(glyphrec.bitmap.width);
			int height = next_po2(glyphrec.bitmap.rows);

			byte[] expanded = new byte[2 * width * height];
			for (int j = 0; j < height; j++)
			{
				for (int i = 0; i < width; i++)
				{
					//Luminance
					expanded[2 * (i + j * width)] = (byte)255;
					//expanded[4 * (i + j * width) + 1] = (byte)255;
					//expanded[4 * (i + j * width) + 2] = (byte)255;

					// Alpha
					expanded[2 * (i + j * width) + 1] =
						(i >= glyphrec.bitmap.width || j >= glyphrec.bitmap.rows) ?
						(byte)0 : (byte)(bmp[i + glyphrec.bitmap.width * j]);
				}
			}

			//Set up some texture parameters for opengl
			Gl.glBindTexture(Gl.GL_TEXTURE_2D, textures[c]);
			Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_WRAP_S, Gl.GL_CLAMP_TO_EDGE);
			Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_WRAP_T, Gl.GL_CLAMP_TO_EDGE);
			Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MAG_FILTER, Gl.GL_LINEAR);
			Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MIN_FILTER, Gl.GL_LINEAR);

			//Create the texture
			Gl.glTexImage2D(Gl.GL_TEXTURE_2D, 0, Gl.GL_RGBA, width, height,
				0, Gl.GL_LUMINANCE_ALPHA, Gl.GL_UNSIGNED_BYTE, expanded);
			expanded = null;
			bmp = null;

			//Create a display list and bind a texture to it
			Gl.glNewList((list_base + c), Gl.GL_COMPILE);
			Gl.glBindTexture(Gl.GL_TEXTURE_2D, textures[c]);

			//Account for freetype spacing rules
			Gl.glTranslatef(glyphrec.bitmap_left, 0, 0);
			Gl.glPushMatrix();
			Gl.glTranslatef(0, glyphrec.bitmap_top - glyphrec.bitmap.rows, 0);
			float x = (float)glyphrec.bitmap.width / (float)width;
			float y = (float)glyphrec.bitmap.rows / (float)height;

			offset.left = glyphrec.bitmap_left;
			offset.top = glyphrec.bitmap_top;
			offset.height = glyphrec.bitmap.rows;
			offset.width = glyphrec.bitmap.width;
			offset.advance = glyphrec.advance;
			offset.lsb_delta = glyphrec.lsb_delta;
			offset.rsb_delta = glyphrec.rsb_delta;
			offset.linearHoriAdvance = glyphrec.linearHoriAdvance;
			offset.linearVertAdvance = glyphrec.linearVertAdvance;
			offsets[c] = offset;

			//Draw the quad
			Gl.glBegin(Gl.GL_QUADS);
			Gl.glTexCoord2d(0, 0); Gl.glVertex2f(0, glyphrec.bitmap.rows);
			Gl.glTexCoord2d(0, y); Gl.glVertex2f(0, 0);
			Gl.glTexCoord2d(x, y); Gl.glVertex2f(glyphrec.bitmap.width, 0);
			Gl.glTexCoord2d(x, 0); Gl.glVertex2f(glyphrec.bitmap.width, glyphrec.bitmap.rows);
			Gl.glEnd();
			Gl.glPopMatrix();

			//Advance for the next character			
			Gl.glTranslatef(glyphrec.bitmap.width, 0, 0);
			extent_x[c] = glyphrec.bitmap_left + glyphrec.bitmap.width;
			Gl.glEndList();
			sChars += "f:" + c.ToString() + "[w:" + glyphrec.bitmap.width.ToString() + "][h:" + glyphrec.bitmap.rows.ToString() + "]" + sError;
		}
Example #10
0
		/// <summary>
		/// Render the font to a series of OpenGL textures (one per letter)
		/// </summary>
		/// <param name="fontsize">size of the font</param>
		/// <param name="DPI">dots-per-inch setting</param>
		public void ftRenderToTexture(int fontsize, uint DPI)
		{
			font_size = fontsize;

			face = (FT_FaceRec)Marshal.PtrToStructure(faceptr, typeof(FT_FaceRec));
			Console.WriteLine("Num Faces:" + face.num_faces.ToString());
			Console.WriteLine("Num Glyphs:" + face.num_glyphs.ToString());
			Console.WriteLine("Num Char Maps:" + face.num_charmaps.ToString());
			Console.WriteLine("Font Family:" + face.family_name);
			Console.WriteLine("Style Name:" + face.style_name);
			Console.WriteLine("Generic:" + face.generic);
			Console.WriteLine("Bbox:" + face.bbox);
			Console.WriteLine("Glyph:" + face.glyph);
			//   IConsole.Write("Num Glyphs:", );

			//Freetype measures the font size in 1/64th of pixels for accuracy 
			//so we need to request characters in size*64
			FT.FT_Set_Char_Size(faceptr, font_size << 6, font_size << 6, DPI, DPI);

			//Provide a reasonably accurate estimate for expected pixel sizes
			//when we later on create the bitmaps for the font
			FT.FT_Set_Pixel_Sizes(faceptr, (uint)font_size, (uint)font_size);


			// Once we have the face loaded and sized we generate opengl textures 
			// from the glyphs  for each printable character
			Console.WriteLine("Compiling Font Characters 0..127");
			textures = new int[128];
			extent_x = new int[128];
			offsets = new FTGlyphOffset[128];
			list_base = Gl.glGenLists(128);
			Gl.glGenTextures(128, textures);
			for (int c = 0; c < 128; c++)
			{
				CompileCharacterToTexture(face, c);

				if (c < 127)
					sChars += ",";
			}
			//Console.WriteLine("Font Compiled:" + sChars);            
		}
Example #11
0
        private void CompileCharacterToTexture(FT_FaceRec face, int c)
        {
            FTGlyphOffset offset = new FTGlyphOffset();

            //We first convert the number index to a character index
            uint index = FT.FT_Get_Char_Index(faceptr, (uint)c);

            string sError = "";

            if (index == 0)
            {
                sError = "No Glyph";
            }

            //Here we load the actual glyph for the character
            int ret = FT.FT_Load_Glyph(faceptr, index, FT.FT_LOAD_DEFAULT);

            if (ret != 0)
            {
                Console.Write("Load_Glyph failed for character " + c.ToString());
            }

            FT_GlyphSlotRec glyphrec = (FT_GlyphSlotRec)Marshal.PtrToStructure(face.glyph, typeof(FT_GlyphSlotRec));

            ret = FT.FT_Render_Glyph(ref glyphrec, FT_Render_Mode.FT_RENDER_MODE_NORMAL);

            if (ret != 0)
            {
                Console.Write("Render failed for character " + c.ToString());
            }

            int size = (glyphrec.bitmap.width * glyphrec.bitmap.rows);

            if (size <= 0)
            {
                //Console.Write("Blank Character: " + c.ToString());
                //space is a special `blank` character
                extent_x[c] = 0;
                if (c == 32)
                {
                    Gl.glNewList((list_base + c), Gl.GL_COMPILE);
                    Gl.glTranslatef(font_size >> 1, 0, 0);
                    extent_x[c] = font_size >> 1;
                    Gl.glEndList();
                    offset.left   = 0;
                    offset.top    = 0;
                    offset.height = 0;
                    offset.width  = extent_x[c];
                    offsets[c]    = offset;
                }
                return;
            }

            byte[] bmp = new byte[size];
            Marshal.Copy(glyphrec.bitmap.buffer, bmp, 0, bmp.Length);

            //Next we expand the bitmap into an opengl texture
            int width  = next_po2(glyphrec.bitmap.width);
            int height = next_po2(glyphrec.bitmap.rows);

            byte[] expanded = new byte[2 * width * height];
            for (int j = 0; j < height; j++)
            {
                for (int i = 0; i < width; i++)
                {
                    //Luminance
                    expanded[2 * (i + j * width)] = (byte)255;
                    //expanded[4 * (i + j * width) + 1] = (byte)255;
                    //expanded[4 * (i + j * width) + 2] = (byte)255;

                    // Alpha
                    expanded[2 * (i + j * width) + 1] =
                        (i >= glyphrec.bitmap.width || j >= glyphrec.bitmap.rows) ?
                        (byte)0 : (byte)(bmp[i + glyphrec.bitmap.width * j]);
                }
            }

            //Set up some texture parameters for opengl
            Gl.glBindTexture(Gl.GL_TEXTURE_2D, textures[c]);
            Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_WRAP_S, Gl.GL_CLAMP_TO_EDGE);
            Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_WRAP_T, Gl.GL_CLAMP_TO_EDGE);
            Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MAG_FILTER, Gl.GL_LINEAR);
            Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MIN_FILTER, Gl.GL_LINEAR);

            //Create the texture
            Gl.glTexImage2D(Gl.GL_TEXTURE_2D, 0, Gl.GL_RGBA, width, height,
                            0, Gl.GL_LUMINANCE_ALPHA, Gl.GL_UNSIGNED_BYTE, expanded);
            expanded = null;
            bmp      = null;

            //Create a display list and bind a texture to it
            Gl.glNewList((list_base + c), Gl.GL_COMPILE);
            Gl.glBindTexture(Gl.GL_TEXTURE_2D, textures[c]);

            //Account for freetype spacing rules
            Gl.glTranslatef(glyphrec.bitmap_left, 0, 0);
            Gl.glPushMatrix();
            Gl.glTranslatef(0, glyphrec.bitmap_top - glyphrec.bitmap.rows, 0);
            float x = (float)glyphrec.bitmap.width / (float)width;
            float y = (float)glyphrec.bitmap.rows / (float)height;

            offset.left              = glyphrec.bitmap_left;
            offset.top               = glyphrec.bitmap_top;
            offset.height            = glyphrec.bitmap.rows;
            offset.width             = glyphrec.bitmap.width;
            offset.advance           = glyphrec.advance;
            offset.lsb_delta         = glyphrec.lsb_delta;
            offset.rsb_delta         = glyphrec.rsb_delta;
            offset.linearHoriAdvance = glyphrec.linearHoriAdvance;
            offset.linearVertAdvance = glyphrec.linearVertAdvance;
            offsets[c]               = offset;

            //Draw the quad
            Gl.glBegin(Gl.GL_QUADS);
            Gl.glTexCoord2d(0, 0); Gl.glVertex2f(0, glyphrec.bitmap.rows);
            Gl.glTexCoord2d(0, y); Gl.glVertex2f(0, 0);
            Gl.glTexCoord2d(x, y); Gl.glVertex2f(glyphrec.bitmap.width, 0);
            Gl.glTexCoord2d(x, 0); Gl.glVertex2f(glyphrec.bitmap.width, glyphrec.bitmap.rows);
            Gl.glEnd();
            Gl.glPopMatrix();

            //Advance for the next character
            Gl.glTranslatef(glyphrec.bitmap.width, 0, 0);
            extent_x[c] = glyphrec.bitmap_left + glyphrec.bitmap.width;
            Gl.glEndList();
            sChars += "f:" + c.ToString() + "[w:" + glyphrec.bitmap.width.ToString() + "][h:" + glyphrec.bitmap.rows.ToString() + "]" + sError;
        }
Example #12
0
        private static void InitLibrary()
        {
            Monitor.Enter(flag);
            try
            {
                if (libraryinitialized)
                {
                    return;
                }
                CheckFreeType(FT.FT_Init_FreeType(out FreeTypeLib));
                libraryinitialized = true;

                Strings npaths = GetFontDirectories();
                foreach (string ndir in npaths)
                {
                    if (Directory.Exists(ndir))
                    {
                        string[] nfiles = StreamUtil.GetFiles(ndir, "*.TTF|*.ttf|*.pf*", SearchOption.TopDirectoryOnly);
                        foreach (string nfile in nfiles)
                        {
                            IntPtr     iface = (IntPtr)0;
                            FT_FaceRec aface = new FT_FaceRec();
                            CheckFreeType(FT.FT_New_Face(FreeTypeLib, nfile, 0, out iface));
                            try
                            {
                                aface = (FT_FaceRec)Marshal.PtrToStructure(iface, typeof(FT_FaceRec));
                                if ((aface.face_flags & (int)FT_Face_Flags.FT_FACE_FLAG_SCALABLE) != 0)
                                {
                                    LogFontFt aobj = new LogFontFt();
                                    aobj.ftlibrary = FreeTypeLib;
                                    aobj.fullinfo  = false;
                                    // Fill font properties
                                    aobj.type1 = ((int)FT_Face_Flags.FT_FACE_FLAG_SFNT & aface.face_flags) == 0;
                                    if (aobj.type1)
                                    {
                                        aobj.convfactor = 1;
                                        //       aobj.convfactor:=1000/aface.units_per_EM;
                                        aobj.widthmult = aobj.convfactor;
                                    }
                                    else
                                    {
                                        aobj.convfactor = 1;
                                        //       aobj.convfactor:=1000/aface.units_per_EM;
                                        aobj.widthmult = aobj.convfactor;
                                    }
                                    aobj.filename = nfile;
                                    string family_name = Marshal.PtrToStringAnsi(aface.family_name);
                                    aobj.postcriptname = family_name.Replace(" ", "");
                                    aobj.familyname    = family_name;
                                    aobj.keyname       = family_name + "____";
                                    aobj.fixedpitch    = (aface.face_flags & (int)FT_Face_Flags.FT_FACE_FLAG_FIXED_WIDTH) != 0;
                                    aobj.havekerning   = (aface.face_flags & (int)FT_Face_Flags.FT_FACE_FLAG_KERNING) != 0;
                                    int nleft   = System.Convert.ToInt32(Math.Round(aobj.convfactor * aface.bbox.xMin));
                                    int nright  = System.Convert.ToInt32(Math.Round(aobj.convfactor * aface.bbox.xMax));
                                    int ntop    = System.Convert.ToInt32(Math.Round(aobj.convfactor * aface.bbox.yMax));
                                    int nbottom = System.Convert.ToInt32(Math.Round(aobj.convfactor * aface.bbox.yMin));
                                    aobj.BBox      = new Rectangle(nleft, ntop, nright - nleft, nbottom - ntop);
                                    aobj.ascent    = System.Convert.ToInt32(Math.Round(aobj.convfactor * aface.ascender));
                                    aobj.descent   = System.Convert.ToInt32(Math.Round(aobj.convfactor * aface.descender));
                                    aobj.leading   = System.Convert.ToInt32(Math.Round(aobj.convfactor * aface.height) - (aobj.ascent - aobj.descent));
                                    aobj.MaxWidth  = System.Convert.ToInt32(Math.Round(aobj.convfactor * aface.max_advance_width));
                                    aobj.Capheight = System.Convert.ToInt32(Math.Round(aobj.convfactor * aface.ascender));
                                    string style_name = Marshal.PtrToStringAnsi(aface.style_name);
                                    aobj.stylename = style_name;
                                    aobj.bold      = (aface.style_flags & (int)FT_Style_Flags.FT_STYLE_FLAG_BOLD) != 0;
                                    aobj.italic    = (aface.style_flags & (int)FT_Style_Flags.FT_STYLE_FLAG_ITALIC) != 0;
                                    if (aobj.bold)
                                    {
                                        aobj.keyname = aobj.keyname + "B1";
                                    }
                                    else
                                    {
                                        aobj.keyname = aobj.keyname + "B0";
                                    }

                                    if (aobj.italic)
                                    {
                                        aobj.keyname = aobj.keyname + "I1";
                                    }
                                    else
                                    {
                                        aobj.keyname = aobj.keyname + "I0";
                                    }
                                    // Default font configuration, LUXI SANS is default
                                    if ((!aobj.italic) && (!aobj.bold))
                                    {
                                        if (defaultfont == null)
                                        {
                                            defaultfont = aobj;
                                        }
                                        else
                                        {
                                            if (aobj.familyname.ToUpper() == "LUXI SANS")
                                            {
                                                defaultfont = aobj;
                                            }
                                        }
                                    }
                                    else
                                    if ((!aobj.italic) && (aobj.bold))
                                    {
                                        if (defaultfontb == null)
                                        {
                                            defaultfontb = aobj;
                                        }
                                        else
                                        {
                                            if (aobj.familyname.ToUpper() == "LUXI SANS")
                                            {
                                                defaultfontb = aobj;
                                            }
                                        }
                                    }
                                    else
                                    if ((aobj.italic) && (!aobj.bold))
                                    {
                                        if (defaultfontit == null)
                                        {
                                            defaultfontit = aobj;
                                        }
                                        else
                                        {
                                            if (aobj.familyname.ToUpper() == "LUXI SANS")
                                            {
                                                defaultfontit = aobj;
                                            }
                                        }
                                    }
                                    else
                                    if ((aobj.italic) && (aobj.bold))
                                    {
                                        if (defaultfontbit == null)
                                        {
                                            defaultfontbit = aobj;
                                        }
                                        else
                                        {
                                            if (aobj.familyname.ToUpper() == "LUXI SANS")
                                            {
                                                defaultfontbit = aobj;
                                            }
                                        }
                                    }

                                    aobj.keyname = aobj.keyname.ToUpper();
                                    if (fontlist.IndexOfKey(aobj.keyname) < 0)
                                    {
                                        fontlist.Add(aobj.keyname.ToUpper(), aobj);
                                    }
                                }
                                int nindex = fontfiles.IndexOfKey(nfile);
                                if (nindex < 0)
                                {
                                    fontfiles.Add(nfile, nfile);
                                }
                            }
                            finally
                            {
                                CheckFreeType(FT.FT_Done_Face(iface));
                            }
                        }
                    }
                }
            }
            finally
            {
                Monitor.Exit(flag);
            }
        }