Exemple #1
0
        void LayoutLabel()
        {
            if (FontAtlas == null || string.IsNullOrEmpty(Text))
            {
                ContentSize = CCSize.Zero;
                return;
            }

            TextureAtlas.RemoveAllQuads();
            Descendants.Clear();
            lettersInfo.Clear();

            FontAtlas.PrepareLetterDefinitions(Text);

            var start      = 0;
            var typesetter = new CCTLTextLayout(this);

            var length      = Text.Length;
            var insetBounds = labelDimensions;

            var layoutAvailable = true;

            if (insetBounds == CCSize.Zero)
            {
                insetBounds     = new CCSize(8388608, 8388608);
                layoutAvailable = false;
            }

            var boundsWidth              = insetBounds.Width;
            var contentScaleFactorWidth  = CCLabel.DefaultTexelToContentSizeRatios.Width;
            var contentScaleFactorHeight = CCLabel.DefaultTexelToContentSizeRatios.Height;

            List <CCTLLine> lineList = new List <CCTLLine>();

            while (start < length)// && textPosition.Y < insetBounds.Bottom)
            {
                // Now we ask the typesetter to break off a line for us.
                // This also will take into account line feeds embedded in the text.
                //  Example: "This is text \n with a line feed embedded inside it"
                int count = typesetter.SuggestLineBreak(start, boundsWidth);
                var line  = typesetter.GetLine(start, start + count);
                lineList.Add(line);

                start += count;
            }


            // Calculate our vertical starting position
            var totalHeight       = lineList.Count * LineHeight;
            var nextFontPositionY = totalHeight;

            if (Dimensions.Height > 0)
            {
                var labelHeightPixel = Dimensions.Height * contentScaleFactorHeight;
                if (totalHeight > labelHeightPixel)
                {
                    int numLines = (int)(labelHeightPixel / LineHeight);
                    totalHeight = numLines * LineHeight;
                }
                switch (VerticalAlignment)
                {
                case CCVerticalTextAlignment.Top:
                    nextFontPositionY = labelHeightPixel;
                    break;

                case CCVerticalTextAlignment.Center:
                    nextFontPositionY = (labelHeightPixel + totalHeight) * 0.5f;
                    break;

                case CCVerticalTextAlignment.Bottom:
                    nextFontPositionY = totalHeight;
                    break;

                default:
                    break;
                }
            }


            var   lineGlyphIndex = 0;
            float longestLine    = (labelDimensions.Width > 0) ? labelDimensions.Width : 0;

            // Used for calculating overlapping on last line character
            var lastCharWidth   = 0.0f;
            int lastCharAdvance = 0;

            // Define our horizontal justification
            var flushFactor = (float)HorizontalAlignment / (float)CCTextAlignment.Right;

            // We now loop through all of our line's glyph runs
            foreach (var line in lineList)
            {
                var gliphRun  = line.GlyphRun;
                var lineWidth = line.Bounds.Width * contentScaleFactorWidth;
                var flush     = line.PenOffsetForFlush(flushFactor, boundsWidth);

                foreach (var glyph in gliphRun)
                {
                    var letterPosition = glyph.Position;
                    var letterDef      = glyph.Definition;
                    lastCharWidth     = letterDef.Width * contentScaleFactorWidth;
                    letterPosition.X += flush;
                    letterPosition.Y  = (nextFontPositionY - letterDef.YOffset) / contentScaleFactorHeight;

                    //recordLetterInfo(letterPosition, glyph.def, lineGlyphIndex++);

                    var tmpInfo = new LetterInfo();

                    tmpInfo.Definition         = letterDef;
                    tmpInfo.Position           = letterPosition;
                    tmpInfo.ContentSize.Width  = letterDef.Width;
                    tmpInfo.ContentSize.Height = letterDef.Height;

                    if (lineGlyphIndex >= lettersInfo.Count)
                    {
                        lettersInfo.Add(tmpInfo);
                    }
                    else
                    {
                        lettersInfo[lineGlyphIndex] = tmpInfo;
                    }

                    lineGlyphIndex++;

                    lastCharAdvance = (int)glyph.Definition.XAdvance;
                }

                // calculate our longest line which is used for calculating our ContentSize
                if (lineWidth > longestLine)
                {
                    longestLine = lineWidth;
                }

                nextFontPositionY -= LineHeight;
            }

            CCSize tmpSize;

            // If the last character processed has an xAdvance which is less that the width of the characters image, then we need
            // to adjust the width of the string to take this into account, or the character will overlap the end of the bounding
            // box
            if (lastCharAdvance < lastCharWidth)
            {
                tmpSize.Width = longestLine - lastCharAdvance + lastCharWidth;
            }
            else
            {
                tmpSize.Width = longestLine;
            }

            tmpSize.Height = totalHeight;

            if (Dimensions.Height > 0)
            {
                tmpSize.Height = Dimensions.Height * contentScaleFactorHeight;
            }

            ContentSize = tmpSize / CCLabel.DefaultTexelToContentSizeRatios;

            lineList.Clear();

            CCRect   uvRect;
            CCSprite letterSprite;

            for (int c = 0; c < Children.Count; c++)
            {
                letterSprite = (CCSprite)Children[c];
                int tag = letterSprite.Tag;
                if (tag >= length)
                {
                    RemoveChild(letterSprite, true);
                }
                else if (tag >= 0)
                {
                    if (letterSprite != null)
                    {
                        uvRect = lettersInfo[tag].Definition.Subrect;
                        letterSprite.TextureRectInPixels = uvRect;
                        letterSprite.ContentSize         = uvRect.Size;
                    }
                }
            }

            UpdateQuads();
            UpdateColor();
        }
        void LayoutLabel ()
        {

            if (FontAtlas == null || string.IsNullOrEmpty(Text))
            {
                ContentSize = CCSize.Zero;
                return;
            }

            TextureAtlas.RemoveAllQuads();
            Descendants.Clear();
            lettersInfo.Clear();

            FontAtlas.PrepareLetterDefinitions(Text);

            var start = 0;
            var typesetter = new CCTLTextLayout(this);

            var length = Text.Length;
            var insetBounds = labelDimensions;

            var layoutAvailable = true;

            if (insetBounds.Width <= 0) 
            {
                insetBounds.Width = MAX_BOUNDS;
                layoutAvailable = false;
            }

            if (insetBounds.Height <= 0) 
            {
                insetBounds.Height = MAX_BOUNDS;
                layoutAvailable = false;
            }


            var contentScaleFactorWidth = CCLabel.DefaultTexelToContentSizeRatios.Width;
            var contentScaleFactorHeight = CCLabel.DefaultTexelToContentSizeRatios.Height;
            var scaleX = ScaleX;
            var scaleY = ScaleY;

            List<CCTLLine> lineList = new List<CCTLLine>();

            var boundingSize = CCSize.Zero;

            while (start < length)
            {

                // Now we ask the typesetter to break off a line for us.
                // This also will take into account line feeds embedded in the text.
                //  Example: "This is text \n with a line feed embedded inside it"
                int count = typesetter.SuggestLineBreak(start, insetBounds.Width);
                var line = typesetter.GetLine(start, start + count);

                lineList.Add(line);

                if (line.Bounds.Width > boundingSize.Width)
                    boundingSize.Width = line.Bounds.Width;
                
                boundingSize.Height += line.Bounds.Height;

                start += count;
            }

            if (!layoutAvailable)
            {
                if (insetBounds.Width == MAX_BOUNDS)
                {
                    insetBounds.Width = boundingSize.Width;
                }
                if (insetBounds.Height == MAX_BOUNDS)
                {
                    insetBounds.Height = boundingSize.Height;
                }
            }

            // Calculate our vertical starting position
            var totalHeight = lineList.Count * LineHeight;
            var nextFontPositionY = totalHeight;

            if (layoutAvailable && labelDimensions.Height > 0)
            {
                var labelHeightPixel = labelDimensions.Height / scaleY * contentScaleFactorHeight;
                if (totalHeight > labelHeightPixel)
                {
                    int numLines = (int)(labelHeightPixel / LineHeight);
                    totalHeight = numLines * LineHeight;
                }
                switch (VerticalAlignment)
                {
                    case CCVerticalTextAlignment.Top:
                        nextFontPositionY = labelHeightPixel;
                        break;
                    case CCVerticalTextAlignment.Center:
                        nextFontPositionY = (labelHeightPixel + totalHeight) * 0.5f;
                        break;
                    case CCVerticalTextAlignment.Bottom:
                        nextFontPositionY = totalHeight;
                        break;
                    default:
                        break;
                }
            }


            var lineGlyphIndex = 0;
            float longestLine = 0;

            // Used for calculating overlapping on last line character
            var lastCharWidth = 0.0f;
            int lastCharAdvance = 0;

            // Define our horizontal justification
            var flushFactor = (float)HorizontalAlignment / (float)CCTextAlignment.Right;

            // We now loop through all of our line's glyph runs
            foreach (var line in lineList)
            {

                var gliphRun = line.GlyphRun;
                var lineWidth = line.Bounds.Width * contentScaleFactorWidth;
                var flushWidth = (layoutAvailable) ? insetBounds.Width / scaleX : boundingSize.Width;
                var flush = line.PenOffsetForFlush(flushFactor, flushWidth) ;

                foreach (var glyph in gliphRun)
                {
                    var letterPosition = glyph.Position;
                    var letterDef = glyph.Definition;
                    lastCharWidth = letterDef.Width * contentScaleFactorWidth;

                    letterPosition.X += flush;
                    letterPosition.Y = (nextFontPositionY - letterDef.YOffset) / contentScaleFactorHeight;

                    var tmpInfo = new LetterInfo();

                    tmpInfo.Definition = letterDef;
                    tmpInfo.Position = letterPosition;
                    tmpInfo.ContentSize.Width = letterDef.Width;
                    tmpInfo.ContentSize.Height = letterDef.Height;

                    if (lineGlyphIndex >= lettersInfo.Count)
                    {
                        lettersInfo.Add(tmpInfo);
                    }
                    else
                    {
                        lettersInfo[lineGlyphIndex] = tmpInfo;
                    }

                    lineGlyphIndex++;

                    lastCharAdvance         = (int)glyph.Definition.XAdvance;
                }

                // calculate our longest line which is used for calculating our ContentSize
                if (lineWidth > longestLine)
                    longestLine = lineWidth;

                nextFontPositionY -= LineHeight;
            }

            CCSize tmpSize;
            // If the last character processed has an xAdvance which is less that the width of the characters image, then we need
            // to adjust the width of the string to take this into account, or the character will overlap the end of the bounding
            // box
            if(lastCharAdvance < lastCharWidth)
            {
                tmpSize.Width = longestLine - lastCharAdvance + lastCharWidth;
            }
            else
            {
                tmpSize.Width = longestLine;
            }

            tmpSize.Height = totalHeight;

            if (labelDimensions.Height > 0)
            {
                tmpSize.Height = labelDimensions.Height * contentScaleFactorHeight;
            }

            // We use base here so we do not trigger an update internally.
            base.ContentSize = tmpSize / CCLabel.DefaultTexelToContentSizeRatios;

            lineList.Clear();

            CCRect uvRect;
            CCSprite letterSprite;

            for (int c = 0; c < Children.Count; c++) 
            {
                letterSprite = (CCSprite)Children[c];
                int tag = letterSprite.Tag;
                if(tag >= length)
                {
                    RemoveChild(letterSprite, true);
                }
                else if(tag >= 0)
                {
                    if (letterSprite != null)
                    {
                        uvRect = lettersInfo[tag].Definition.Subrect;
                        letterSprite.TextureRectInPixels = uvRect;
                        letterSprite.ContentSize = uvRect.Size;
                    }
                }
            }

            UpdateQuads();
            UpdateColor();

        }