SetDictionary() public method

Internal function to set up the dictionary
public SetDictionary ( tk2dFontChar>.Dictionary dict ) : void
dict tk2dFontChar>.Dictionary
return void
Ejemplo n.º 1
0
        public static bool BuildFont(Info fontInfo, tk2dFontData target, float scale, int charPadX, bool dupeCaps, bool flipTextureY, Texture2D gradientTexture, int gradientCount)
        {
            float texWidth = fontInfo.scaleW;
            float texHeight = fontInfo.scaleH;
            float lineHeight = fontInfo.lineHeight;

            target.lineHeight = lineHeight * scale;

            // Get number of characters (lastindex + 1)
            int maxCharId = 0;
            int maxUnicodeChar = 100000;
            foreach (var theChar in fontInfo.chars)
            {
                if (theChar.id > maxUnicodeChar)
                {
                    // in most cases the font contains unwanted characters!
                    Debug.LogError("Unicode character id exceeds allowed limit: " + theChar.id.ToString() + ". Skipping.");
                    continue;
                }

                if (theChar.id > maxCharId) maxCharId = theChar.id;
            }

            // decide to use dictionary if necessary
            // 2048 is a conservative lower floor
            bool useDictionary = maxCharId > 2048;

            Dictionary<int, tk2dFontChar> charDict = (useDictionary)?new Dictionary<int, tk2dFontChar>():null;
            tk2dFontChar[] chars = (useDictionary)?null:new tk2dFontChar[maxCharId + 1];
            int minChar = 0x7fffffff;
            int maxCharWithinBounds = 0;
            int numLocalChars = 0;
            float largestWidth = 0.0f;
            foreach (var theChar in fontInfo.chars)
            {
                tk2dFontChar thisChar = new tk2dFontChar();
                int id = theChar.id;
                int x = theChar.x;
                int y = theChar.y;
                int width = theChar.width;
                int height = theChar.height;
                int xoffset = theChar.xoffset;
                int yoffset = theChar.yoffset;
                int xadvance = theChar.xadvance + charPadX;

                // special case, if the width and height are zero, the origin doesn't need to be offset
                // handles problematic case highlighted here:
                // http://2dtoolkit.com/forum/index.php/topic,89.msg220.html
                if (width == 0 && height == 0)
                {
                    xoffset = 0;
                    yoffset = 0;
                }

                // precompute required data
                float px = xoffset * scale;
                float py = (lineHeight - yoffset) * scale;

                if (theChar.texOverride)
                {
                    int w = theChar.texW;
                    int h = theChar.texH;
                    if (theChar.texFlipped)
                    {
                        h = theChar.texW;
                        w = theChar.texH;
                    }

                    thisChar.p0 = new Vector3(px + theChar.texOffsetX * scale, py - theChar.texOffsetY * scale, 0);
                    thisChar.p1 = new Vector3(px + (theChar.texOffsetX + w) * scale, py - (theChar.texOffsetY + h) * scale, 0);

                    thisChar.uv0 = new Vector2((theChar.texX) / texWidth, (theChar.texY + theChar.texH) / texHeight);
                    thisChar.uv1 = new Vector2((theChar.texX + theChar.texW) / texWidth, (theChar.texY) / texHeight);

                    thisChar.flipped = theChar.texFlipped;
                }
                else
                {
                    thisChar.p0 = new Vector3(px, py, 0);
                    thisChar.p1 = new Vector3(px + width * scale, py - height * scale, 0);
                    if (flipTextureY)
                    {
                        thisChar.uv0 = new Vector2(x / texWidth, y / texHeight);
                        thisChar.uv1 = new Vector2(thisChar.uv0.x + width / texWidth, thisChar.uv0.y + height / texHeight);
                    }
                    else
                    {
                        thisChar.uv0 = new Vector2(x / texWidth, 1.0f - y / texHeight);
                        thisChar.uv1 = new Vector2(thisChar.uv0.x + width / texWidth, thisChar.uv0.y - height / texHeight);
                    }

                    thisChar.flipped = false;
                }
                thisChar.advance = xadvance * scale;
                largestWidth = Mathf.Max(thisChar.advance, largestWidth);

                // Needs gradient data
                if (gradientTexture != null)
                {
                    // build it up assuming the first gradient
                    float x0 = (float)(0.0f / gradientCount);
                    float x1 = (float)(1.0f / gradientCount);
                    float y0 = 1.0f;
                    float y1 = 0.0f;

                    // align to glyph if necessary

                    thisChar.gradientUv = new Vector2[4];
                    thisChar.gradientUv[0] = new Vector2(x0, y0);
                    thisChar.gradientUv[1] = new Vector2(x1, y0);
                    thisChar.gradientUv[2] = new Vector2(x0, y1);
                    thisChar.gradientUv[3] = new Vector2(x1, y1);
                }

                if (id <= maxCharId)
                {
                    maxCharWithinBounds = (id > maxCharWithinBounds) ? id : maxCharWithinBounds;
                    minChar = (id < minChar) ? id : minChar;

                    if (useDictionary)
                        charDict[id] = thisChar;
                    else
                        chars[id] = thisChar;

                    ++numLocalChars;
                }
            }

            // duplicate capitals to lower case, or vice versa depending on which ones exist
            if (dupeCaps)
            {
                for (int uc = 'A'; uc <= 'Z'; ++uc)
                {
                    int lc = uc + ('a' - 'A');

                    if (useDictionary)
                    {
                        if (charDict.ContainsKey(uc))
                            charDict[lc] = charDict[uc];
                        else if (charDict.ContainsKey(lc))
                            charDict[uc] = charDict[lc];
                    }
                    else
                    {
                        if (chars[lc] == null) chars[lc] = chars[uc];
                        else if (chars[uc] == null) chars[uc] = chars[lc];
                    }
                }
            }

            // share null char, same pointer
            var nullChar = new tk2dFontChar();
            nullChar.gradientUv = new Vector2[4]; // this would be null otherwise

            target.largestWidth = largestWidth;
            if (useDictionary)
            {
                // guarantee at least the first 256 characters
                for (int i = 0; i < 256; ++i)
                {
                    if (!charDict.ContainsKey(i))
                        charDict[i] = nullChar;
                }

                target.chars = null;
                target.SetDictionary(charDict);
                target.useDictionary = true;
            }
            else
            {
                target.chars = new tk2dFontChar[maxCharId + 1];
                for (int i = 0; i <= maxCharId; ++i)
                {
                    target.chars[i] = chars[i];
                    if (target.chars[i] == null)
                    {
                        target.chars[i] = nullChar; // zero everything, null char
                    }
                }

                target.charDict = null;
                target.useDictionary = false;
            }

            // kerning
            target.kerning = new tk2dFontKerning[fontInfo.kernings.Count];
            for (int i = 0; i < target.kerning.Length; ++i)
            {
                tk2dFontKerning kerning = new tk2dFontKerning();
                kerning.c0 = fontInfo.kernings[i].first;
                kerning.c1 = fontInfo.kernings[i].second;
                kerning.amount = fontInfo.kernings[i].amount * scale;
                target.kerning[i] = kerning;
            }

            return true;
        }
Ejemplo n.º 2
0
        public static bool BuildFont(Info fontInfo, tk2dFontData target, float scale, int charPadX, bool dupeCaps, bool flipTextureY, Texture2D gradientTexture, int gradientCount)
        {
            float texWidth   = fontInfo.scaleW;
            float texHeight  = fontInfo.scaleH;
            float lineHeight = fontInfo.lineHeight;

            target.lineHeight = lineHeight * scale;

            // Get number of characters (lastindex + 1)
            int maxCharId      = 0;
            int maxUnicodeChar = 100000;

            foreach (var theChar in fontInfo.chars)
            {
                if (theChar.id > maxUnicodeChar)
                {
                    // in most cases the font contains unwanted characters!
                    Debug.LogError("Unicode character id exceeds allowed limit: " + theChar.id.ToString() + ". Skipping.");
                    continue;
                }

                if (theChar.id > maxCharId)
                {
                    maxCharId = theChar.id;
                }
            }

            // decide to use dictionary if necessary
            // 2048 is a conservative lower floor
            bool useDictionary = maxCharId > 2048;

            Dictionary <int, tk2dFontChar> charDict = (useDictionary)?new Dictionary <int, tk2dFontChar>():null;

            tk2dFontChar[] chars               = (useDictionary)?null:new tk2dFontChar[maxCharId + 1];
            int            minChar             = 0x7fffffff;
            int            maxCharWithinBounds = 0;
            int            numLocalChars       = 0;
            float          largestWidth        = 0.0f;

            foreach (var theChar in fontInfo.chars)
            {
                tk2dFontChar thisChar = new tk2dFontChar();
                int          id       = theChar.id;
                int          x        = theChar.x;
                int          y        = theChar.y;
                int          width    = theChar.width;
                int          height   = theChar.height;
                int          xoffset  = theChar.xoffset;
                int          yoffset  = theChar.yoffset;
                int          xadvance = theChar.xadvance + charPadX;

                // special case, if the width and height are zero, the origin doesn't need to be offset
                // handles problematic case highlighted here:
                // http://unikronsoftware.com/2dtoolkit/forum/index.php/topic,89.msg220.html
                if (width == 0 && height == 0)
                {
                    xoffset = 0;
                    yoffset = 0;
                }

                // precompute required data
                float px = xoffset * scale;
                float py = (lineHeight - yoffset) * scale;

                if (theChar.texOverride)
                {
                    int w = theChar.texW;
                    int h = theChar.texH;
                    if (theChar.texFlipped)
                    {
                        h = theChar.texW;
                        w = theChar.texH;
                    }

                    thisChar.p0 = new Vector3(px + theChar.texOffsetX * scale, py - theChar.texOffsetY * scale, 0);
                    thisChar.p1 = new Vector3(px + (theChar.texOffsetX + w) * scale, py - (theChar.texOffsetY + h) * scale, 0);

                    thisChar.uv0 = new Vector2((theChar.texX) / texWidth, (theChar.texY + theChar.texH) / texHeight);
                    thisChar.uv1 = new Vector2((theChar.texX + theChar.texW) / texWidth, (theChar.texY) / texHeight);

                    thisChar.flipped = theChar.texFlipped;
                }
                else
                {
                    thisChar.p0 = new Vector3(px, py, 0);
                    thisChar.p1 = new Vector3(px + width * scale, py - height * scale, 0);
                    if (flipTextureY)
                    {
                        thisChar.uv0 = new Vector2(x / texWidth, y / texHeight);
                        thisChar.uv1 = new Vector2(thisChar.uv0.x + width / texWidth, thisChar.uv0.y + height / texHeight);
                    }
                    else
                    {
                        thisChar.uv0 = new Vector2(x / texWidth, 1.0f - y / texHeight);
                        thisChar.uv1 = new Vector2(thisChar.uv0.x + width / texWidth, thisChar.uv0.y - height / texHeight);
                    }

                    thisChar.flipped = false;
                }
                thisChar.advance = xadvance * scale;
                largestWidth     = Mathf.Max(thisChar.advance, largestWidth);

                // Needs gradient data
                if (gradientTexture != null)
                {
                    // build it up assuming the first gradient
                    float x0 = (float)(0.0f / gradientCount);
                    float x1 = (float)(1.0f / gradientCount);
                    float y0 = 1.0f;
                    float y1 = 0.0f;

                    // align to glyph if necessary

                    thisChar.gradientUv    = new Vector2[4];
                    thisChar.gradientUv[0] = new Vector2(x0, y0);
                    thisChar.gradientUv[1] = new Vector2(x1, y0);
                    thisChar.gradientUv[2] = new Vector2(x0, y1);
                    thisChar.gradientUv[3] = new Vector2(x1, y1);
                }

                if (id <= maxCharId)
                {
                    maxCharWithinBounds = (id > maxCharWithinBounds) ? id : maxCharWithinBounds;
                    minChar             = (id < minChar) ? id : minChar;

                    if (useDictionary)
                    {
                        charDict[id] = thisChar;
                    }
                    else
                    {
                        chars[id] = thisChar;
                    }

                    ++numLocalChars;
                }
            }

            // duplicate capitals to lower case, or vice versa depending on which ones exist
            if (dupeCaps)
            {
                for (int uc = 'A'; uc <= 'Z'; ++uc)
                {
                    int lc = uc + ('a' - 'A');

                    if (useDictionary)
                    {
                        if (charDict.ContainsKey(uc))
                        {
                            charDict[lc] = charDict[uc];
                        }
                        else if (charDict.ContainsKey(lc))
                        {
                            charDict[uc] = charDict[lc];
                        }
                    }
                    else
                    {
                        if (chars[lc] == null)
                        {
                            chars[lc] = chars[uc];
                        }
                        else if (chars[uc] == null)
                        {
                            chars[uc] = chars[lc];
                        }
                    }
                }
            }

            // share null char, same pointer
            var nullChar = new tk2dFontChar();

            nullChar.gradientUv = new Vector2[4];             // this would be null otherwise

            target.largestWidth = largestWidth;
            if (useDictionary)
            {
                // guarantee at least the first 256 characters
                for (int i = 0; i < 256; ++i)
                {
                    if (!charDict.ContainsKey(i))
                    {
                        charDict[i] = nullChar;
                    }
                }

                target.chars = null;
                target.SetDictionary(charDict);
                target.useDictionary = true;
            }
            else
            {
                target.chars = new tk2dFontChar[maxCharId + 1];
                for (int i = 0; i <= maxCharId; ++i)
                {
                    target.chars[i] = chars[i];
                    if (target.chars[i] == null)
                    {
                        target.chars[i] = nullChar;                         // zero everything, null char
                    }
                }

                target.charDict      = null;
                target.useDictionary = false;
            }

            // kerning
            target.kerning = new tk2dFontKerning[fontInfo.kernings.Count];
            for (int i = 0; i < target.kerning.Length; ++i)
            {
                tk2dFontKerning kerning = new tk2dFontKerning();
                kerning.c0        = fontInfo.kernings[i].first;
                kerning.c1        = fontInfo.kernings[i].second;
                kerning.amount    = fontInfo.kernings[i].amount * scale;
                target.kerning[i] = kerning;
            }

            return(true);
        }