예제 #1
0
        public GlyphRun(OpenGLFont font, string text, float sizeWidth, float sizeHeight, OpenGLTextAlignment alignment, bool autoEllipsis)
        {
            Font = font;
            List <LineBreak> linebreaks = new List <LineBreak>();

            string processingText = text;
            int    totalHeight    = 0;
            int    totalWidth     = 0;
            int    totalChars     = 0;
            int    intWidth;

            if (sizeWidth != float.PositiveInfinity)
            {
                intWidth = (int)sizeWidth;
            }
            else
            {
                intWidth = int.MaxValue;
            }
            int intHeight;

            if (sizeHeight != float.PositiveInfinity)
            {
                intHeight = (int)sizeHeight;
            }
            else
            {
                intHeight = int.MaxValue;
            }
            LineBreak lineBreak = FitString(processingText, 0, intWidth);

            while (lineBreak.Index != processingText.Length)
            {
                LineBreak nextBreak = FitString(processingText, lineBreak.Index, intWidth);
                // see if this line needs ellipsis
                if (Font.myHeight + Font.myHeight + totalHeight > intHeight && autoEllipsis)
                {
                    string lineText      = lineBreak.Text;
                    int    ellipsisStart = lineText.Length - 3;
                    if (ellipsisStart < 0)
                    {
                        ellipsisStart = 0;
                    }
                    lineText        = lineText.Substring(0, ellipsisStart) + "...";
                    lineBreak.Width = MeasureString(lineText);
                    lineBreak.Text  = lineText;
                    break;
                }

                linebreaks.Add(lineBreak);
                totalWidth   = Math.Max(totalWidth, lineBreak.Width);
                totalHeight += Font.myHeight;
                totalChars  += lineBreak.Text.Length;
                lineBreak    = nextBreak;
            }
            linebreaks.Add(lineBreak);
            totalHeight    += Font.myHeight;
            totalWidth      = Math.Max(totalWidth, lineBreak.Width);
            totalChars     += lineBreak.Text.Length;
            myTriangleCount = totalChars * 2;

            GlyphPosition[]  rectangles = new GlyphPosition[totalChars];
            GlyphTexCoords[] texCoords  = new GlyphTexCoords[totalChars];
            short[]          indices    = new short[totalChars * 6];

            Glyphs     = rectangles;
            FontCoords = texCoords;
            Indices    = indices;

            if (sizeWidth == float.PositiveInfinity)
            {
                myWidth = totalWidth;
            }
            else
            {
                myWidth = sizeWidth;
            }
            if (sizeHeight == float.PositiveInfinity)
            {
                myHeight = totalHeight;
            }
            else
            {
                myHeight = sizeHeight;
            }

            float y        = 0;
            int   curChars = 0;

            for (int i = 0; i < linebreaks.Count; i++)
            {
                LineBreak lbreak = linebreaks[i];
                float     x;
                float     spaceAdjust = 0;
                string    lbreakText  = lbreak.Text;
                switch (alignment)
                {
                case OpenGLTextAlignment.Left:
                    x = 0;
                    break;

                case OpenGLTextAlignment.Right:
                    x = myWidth - lbreak.Width;
                    break;

                case OpenGLTextAlignment.Center:
                    x = (myWidth - lbreak.Width) / 2;
                    break;

                case OpenGLTextAlignment.Justified:
                    x = 0;
                    if (i != linebreaks.Count - 1)
                    {
                        lbreakText = lbreakText.TrimStart(' ').TrimEnd(' ');
                        int spaceCount = 0;
                        foreach (char c in lbreakText)
                        {
                            if (c == ' ')
                            {
                                spaceCount++;
                            }
                        }
                        int newWidth = MeasureString(lbreakText);
                        if (spaceCount != 0)
                        {
                            spaceAdjust = (myWidth - newWidth) / spaceCount;
                        }
                    }
                    break;

                default:
                    throw new ArgumentException("Unknown alignment type.");
                }

                BuildLine(font, lbreakText, curChars, x, y, spaceAdjust);
                y        += Font.myHeight;
                curChars += lbreakText.Length;
            }
        }
예제 #2
0
        unsafe public OpenGLFont(Font font)
        {
            IntPtr hdc   = myTempGraphics.GetHdc();
            IntPtr hfont = font.ToHfont();

            SelectObject(hdc, hfont);

            if (!GetCharWidth32(hdc, 0, 255, CharacterWidths))
            {
                throw new SystemException("Unable to measure character widths.");
            }

            tagTEXTMETRIC metrics = new tagTEXTMETRIC();

            GetTextMetrics(hdc, ref metrics);
            myLeadingSpace  = metrics.tmInternalLeading;
            myTrailingSpace = metrics.tmExternalLeading;

            myTempGraphics.ReleaseHdc(hdc);

            int width = 0;

            for (int i = myFirstCharacterOfInterest; i <= myLastCharacterOfInterest; i++)
            {
                CharacterWidths[i] += myLeadingSpace + myTrailingSpace;
                width += CharacterWidths[i];
            }
            myHeight = (int)Math.Round(myTempGraphics.MeasureString(myCharactersOfInterest, font).Height);

            mySquareDim = (int)Math.Ceiling(Math.Sqrt(width * myHeight));
            mySquareDim = Texture.GetValidTextureDimensionFromSize(mySquareDim);
            float  fSquareDim = mySquareDim;
            Bitmap bitmap     = new Bitmap(mySquareDim, mySquareDim, PixelFormat.Format16bppRgb565);

            using (Graphics g = Graphics.FromImage(bitmap))
            {
                int x = 0;
                int y = 0;

                for (char i = myFirstCharacterOfInterest; i <= myLastCharacterOfInterest; i++)
                {
                    if (x + CharacterWidths[i] >= mySquareDim)
                    {
                        y += myHeight;
                        x  = 0;
                    }
                    CharacterLocations[i] = new Point(x, y);

                    float uStart = x / fSquareDim;
                    float uEnd   = (x + CharacterWidths[i]) / fSquareDim;
                    float vStart = y / fSquareDim;
                    float vEnd   = (y + myHeight) / fSquareDim;
                    TextureCoordinates[i] = new GlyphTexCoords(uStart, vStart, uEnd, vEnd);

                    g.DrawString(i.ToString(), font, myWhiteBrush, x, y);
                    x += CharacterWidths[i];
                }
            }

            byte[]     alphaBytes = new byte[bitmap.Width * bitmap.Height];
            BitmapData data       = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, PixelFormat.Format16bppRgb565);

            int pixCount = 0;

            for (int y = 0; y < bitmap.Height; y++)
            {
                short *yp = (short *)((int)data.Scan0 + data.Stride * y);
                for (int x = 0; x < bitmap.Width; x++, pixCount++)
                {
                    short *p          = (short *)(yp + x);
                    short  pixel      = *p;
                    byte   b          = (byte)((pixel & 0x1F) << 3);
                    byte   g          = (byte)(((pixel >> 5) & 0x3F) << 2);
                    byte   r          = (byte)(((pixel >> 11) & 0x1F) << 3);
                    byte   totalAlpha = (byte)((r + g + b) / 3);
                    alphaBytes[pixCount] = totalAlpha;
                }
            }
            bitmap.UnlockBits(data);

            uint tex = 0;

            gl.GenTextures(1, &tex);
            myName = tex;
            gl.BindTexture(gl.GL_TEXTURE_2D, myName);

            fixed(byte *alphaBytesPointer = alphaBytes)
            {
                gl.TexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_ALPHA, mySquareDim, mySquareDim, 0, gl.GL_ALPHA, gl.GL_UNSIGNED_BYTE, (IntPtr)alphaBytesPointer);
            }

            gl.TexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR);
            gl.TexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR);
            gl.TexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP_TO_EDGE);
            gl.TexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP_TO_EDGE);

            // below is debug code I used to see the results of my texture generation

            //try
            //{
            //    Directory.CreateDirectory("\\Temp");
            //}
            //catch (Exception)
            //{
            //}
            //bitmap.Save("\\temp\\temp.png", ImageFormat.Png);

            //for (int i = myFirstCharacterOfInterest; i <= myLastCharacterOfInterest; i++)
            //{
            //    using (Bitmap ch = new Bitmap(bfont.CharacterWidths[i], height, PixelFormat.Format16bppRgb565))
            //    {
            //        using (Graphics tg = Graphics.FromImage(ch))
            //        {
            //            tg.DrawImage(bitmap, 0, 0, new Rectangle(bfont.CharacterLocations[i].X, bfont.CharacterLocations[i].Y, ch.Width, ch.Height), GraphicsUnit.Pixel);
            //        }
            //        ch.Save(string.Format("\\temp\\{0}.png", i), ImageFormat.Png);
            //    }
            //}

            bitmap.Dispose();
        }