예제 #1
0
        // Performs layout on the given string.
        void PerformLayout(string text, TextureFont font, float width, bool wordWarp, StringAlignment alignment,
                           bool rightToLeft, ref Vector2[] vertices, ref ushort[] indices, out int num_indices)
        {
            if (text == null)
                throw new ArgumentNullException("Parameter cannot be null.", "text");

            if (text.Length > 8192)
                throw new ArgumentOutOfRangeException("text", text.Length, "Text length must be between 1 and 8192 characters");

            if (wordWarp || rightToLeft || alignment != StringAlignment.Near)
                throw new NotImplementedException();

            while (8 * text.Length > vertices.Length)
                vertices = new Vector2[vertices.Length << 1];

            while (6 * text.Length > indices.Length)
                indices = new ushort[indices.Length << 1];

            num_indices = 6 * text.Length;

            //Vector2[] vertices = new Vector2[8 * text.Length];  // Interleaved, vertex, texcoord, vertex, etc...
            //ushort[] indices = new ushort[6 * text.Length];
            float x_pos = 0, y_pos = 0;
            ushort i = 0, index_count = 0, vertex_count = 0, last_break_point = 0;
            Box2 rect = new Box2();
            float char_width, char_height, measured_width, measured_height;
            int texture;

            font.LoadGlyphs(text);

            // Every character comprises of 4 vertices, forming two triangles. We generate an index array which
            // indexes vertices in a triangle-strip fashion. To create a single strip for the whole string, we
            // need to add a degenerate triangle (0 height) to connect the last vertex of the previous line with
            // the first vertex of the next line.
            // This algorithm works for left-to-right scripts.

            if (alignment == StringAlignment.Near && !rightToLeft || alignment == StringAlignment.Far && rightToLeft)
            {
                foreach (char c in text)
                {
                    if (Char.IsSeparator(c))
                        last_break_point = index_count;

                    if (c != '\n' && c != '\r')
                    {
                        font.GlyphData(c, out char_width, out char_height, out rect, out texture);

                        vertices[vertex_count].X = x_pos;                // Vertex
                        vertices[vertex_count++].Y = y_pos;
                        vertices[vertex_count].X = rect.Left;            // Texcoord
                        vertices[vertex_count++].Y = rect.Top;
                        vertices[vertex_count].X = x_pos;                // Vertex
                        vertices[vertex_count++].Y = y_pos + char_height;
                        vertices[vertex_count].X = rect.Left;            // Texcoord
                        vertices[vertex_count++].Y = rect.Bottom;

                        vertices[vertex_count].X = x_pos + char_width;   // Vertex
                        vertices[vertex_count++].Y = y_pos + char_height;
                        vertices[vertex_count].X = rect.Right;           // Texcoord
                        vertices[vertex_count++].Y = rect.Bottom;
                        vertices[vertex_count].X = x_pos + char_width;   // Vertex
                        vertices[vertex_count++].Y = y_pos;
                        vertices[vertex_count].X = rect.Right;           // Texcoord
                        vertices[vertex_count++].Y = rect.Top;

                        indices[index_count++] = (ushort)(vertex_count - 8);
                        indices[index_count++] = (ushort)(vertex_count - 6);
                        indices[index_count++] = (ushort)(vertex_count - 4);

                        indices[index_count++] = (ushort)(vertex_count - 4);
                        indices[index_count++] = (ushort)(vertex_count - 2);
                        indices[index_count++] = (ushort)(vertex_count - 8);


                        font.MeasureString(text.Substring(i, 1), out measured_width, out measured_height);
                        x_pos += measured_width;
                    }
                    else if (c == '\n')
                    {
                        //x_pos = layoutRect.Left;
                        x_pos = 0;
                        y_pos += font.Height;
                    }
                    ++i;
                }
            }
            else if (alignment != StringAlignment.Center)
            {
                throw new NotImplementedException("This feature is not yet implemented. Sorry for the inconvenience.");
            }
            else
            {
                throw new NotImplementedException("This feature is not yet implemented. Sorry for the inconvenience.");
            }
        }
예제 #2
0
 /// <summary>
 /// Returns the characteristics of a loaded glyph.
 /// </summary>
 /// <param name="glyph">The character corresponding to this glyph.</param>
 /// <param name="width">The width of this glyph.</param>
 /// <param name="height">The height of this glyph (line spacing).</param>
 /// <param name="textureRectangle">The bounding box of the texture data of this glyph.</param>
 /// <param name="texture">The handle to the texture that contains this glyph.</param>
 /// <returns>True if the glyph has been loaded, false otherwise.</returns>
 /// <seealso cref="LoadGlyphs"/>
 public bool GlyphData(char glyph, out float width, out float height, out Box2 textureRectangle, out int texture)
 {
     if (loaded_glyphs.TryGetValue(glyph, out textureRectangle))
     {
         width = textureRectangle.Width * texture_width;
         height = textureRectangle.Height * texture_height;
         texture = TextureFont.texture;
         return true;
     }
     width = height = texture = 0;
     return false;
 }
예제 #3
0
 /// <summary>
 /// Prepares the specified glyph for rendering.
 /// </summary>
 /// <param name="glyphs">The glyph to prepare for rendering.</param>
 public void LoadGlyph(char glyph)
 {
     Box2 rect = new Box2();
     if (!loaded_glyphs.ContainsKey(glyph))
         LoadGlyph(glyph, out rect);
 }
예제 #4
0
        /// <summary>
        /// Adds a glyph to the texture packer.
        /// </summary>
        /// <param name="c">The character of the glyph.</param>
        /// <param name="rectangle">An OpenTK.Math.Box2 that will hold the data for this glyph.</param>
        private void LoadGlyph(char c, out Box2 rectangle)
        {
            if (pack == null)
                PrepareTexturePacker();

            Glyph g = new Glyph(c, font);
            Rectangle rect = new Rectangle();

            try
            {
                pack.Add(g, out rect);
            }
            catch (InvalidOperationException expt)
            {
                // TODO: The TexturePacker is full, create a new font sheet.
                Trace.WriteLine(expt);
                throw;
            }

            GL.BindTexture(TextureTarget.Texture2d, texture);

            gfx.Clear(System.Drawing.Color.Transparent);
            gfx.DrawString(g.Character.ToString(), g.Font, System.Drawing.Brushes.White, 0.0f, 0.0f);

            //BitmapData bitmap_data = bitmap.LockBits(new Rectangle(0, 0, rect.Width, rect.Height), ImageLockMode.ReadOnly,
            //    System.Drawing.Imaging.PixelFormat.Format32bppArgb);
            //GL.TexSubImage2D(TextureTarget.Texture2d, 0, rect.Left, rect.Top, rect.Width, rect.Height,
            //    OpenTK.OpenGL.Enums.PixelFormat.Rgba, PixelType.UnsignedByte, bitmap_data.Scan0);
            //bitmap.UnlockBits(bitmap_data);

            BitmapData bitmap_data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly,
                System.Drawing.Imaging.PixelFormat.Format32bppArgb);
            int needed_size = rect.Width * rect.Height;
            if (data.Length < needed_size)
                Array.Resize<int>(ref data, needed_size);
            Array.Clear(data, 0, needed_size);
            unsafe
            {
                int* bitmap_data_ptr = (int*)bitmap_data.Scan0;
                for (int y = 0; y < rect.Height; y++)
                {
                    for (int x = 0; x < rect.Width; x++)
                    {
                        data[y * rect.Width + x] = *(bitmap_data_ptr + y * bmp.Width + x);
                    }
                }

                fixed (int* data_ptr = data)
                    GL.TexSubImage2D(TextureTarget.Texture2d, 0, rect.Left, rect.Top, rect.Width, rect.Height,
                                     OpenTK.OpenGL.Enums.PixelFormat.Rgba, PixelType.UnsignedByte, (IntPtr)data_ptr);
            }
            bmp.UnlockBits(bitmap_data);

            rectangle = new Box2(
                rect.Left / (float)texture_width,
                rect.Top / (float)texture_height,
                rect.Right / (float)texture_width,
                rect.Bottom / (float)texture_height);

            loaded_glyphs.Add(g.Character, rectangle);

        }
예제 #5
0
 /// <summary>
 /// Prepares the specified glyphs for rendering.
 /// </summary>
 /// <param name="glyphs">The glyphs to prepare for rendering.</param>
 public void LoadGlyphs(string glyphs)
 {
     Box2 rect = new Box2();
     foreach (char c in glyphs)
     {
         if (!loaded_glyphs.ContainsKey(c))
             LoadGlyph(c, out rect);
     }
 }