Пример #1
0
        /// <summary>Sets up this renderer so that it's ready to start packing child elements of
        /// a given element into lines.</summary>
        /// <param name="renderable">The parent render data whose children will be packed.</param>
        public LineBoxMeta BeginLines(RenderableData renderable, VirtualElements virts, LayoutBox box, bool autoWidth)
        {
            // Get CS:
            ComputedStyle cs = renderable.computedStyle;

            LineBoxMeta lineZone;

            InfiniText.FontFace face = box.FontFace;

            // Update line height:

            // Line height:
            Css.Value lineHeightValue = cs.LineHeightX;

            float cssLineHeight;

            if (lineHeightValue.IsType(typeof(Css.Keywords.Normal)))
            {
                // Get from the metrics font now:
                cssLineHeight = box.FontFace.BaselineToBaseline * box.FontSize;
            }
            else if (
                lineHeightValue.Type != Css.ValueType.RelativeNumber &&
                lineHeightValue.GetType() != typeof(Css.Units.DecimalUnit)
                )
            {
                // E.g. line-height:14px, but not line-height:1. It's just as-is:
                cssLineHeight = lineHeightValue.GetRawDecimal();
            }
            else
            {
                // Some multiple of the font size:
                cssLineHeight = lineHeightValue.GetRawDecimal() * box.FontSize;
            }

            // Check if it's a block context:
            if (box.DisplayMode == DisplayMode.Inline && LastBlockBox != null)
            {
                // Anything else uses the nearest parent block element as the max.
                lineZone = new InlineBoxMeta(LastBlockBox, TopOfStackSafe, box, renderable);

                // Put up the 'strut':
                lineZone.LineHeight = cssLineHeight;
                box.Baseline        = box.FontSize * face.Descender;
            }
            else
            {
                lineZone      = LastBlockBox = new BlockBoxMeta(TopOfStackSafe, box, renderable);
                lineZone.MaxX = box.InnerWidth;

                if (virts != null && virts.Has(ComputedStyle.VerticalScrollPriority))
                {
                    lineZone.MaxX -= 14;

                    if (lineZone.MaxX < 0)
                    {
                        lineZone.MaxX = 0;
                    }
                }

                bool left = (cs.DrawDirectionX == DirectionMode.RTL);
                lineZone.GoingLeftwards = left;

                // H-align:
                int hAlign = cs.HorizontalAlignX;

                if (hAlign == HorizontalAlignMode.Auto)
                {
                    if (left)
                    {
                        hAlign = HorizontalAlignMode.Right;
                    }
                    else
                    {
                        hAlign = HorizontalAlignMode.Left;
                    }
                }

                if (hAlign == HorizontalAlignMode.Left)
                {
                    // Ok how it is (left by default).
                    hAlign = 0;
                }

                lineZone.HorizontalAlign = hAlign;
            }

            // Apply whitespace mode:
            lineZone.WhiteSpace = cs.WhiteSpaceX;

            // Apply line height:
            lineZone.CssLineHeight = cssLineHeight;

            // Update vertical-align:
            Css.Value vAlign = cs.Resolve(Css.Properties.VerticalAlign.GlobalProperty);

            // Get the complete value:
            float vAlignValue = vAlign.GetDecimal(renderable, Css.Properties.VerticalAlign.GlobalProperty);

            // If it's a keyword..
            if (vAlign is Css.CssKeyword)
            {
                // It's a mode:
                lineZone.VerticalAlign       = (int)vAlignValue;
                lineZone.VerticalAlignOffset = 0f;
            }
            else
            {
                // It's a baseline offset:
                lineZone.VerticalAlign       = VerticalAlignMode.Baseline;
                lineZone.VerticalAlignOffset = vAlignValue;
            }

            box.ContentWidth  = 0;
            box.ContentHeight = 0;

            return(lineZone);
        }
        /// <summary>Runs before reflow.</summary>
        public override void UpdateCss(Renderman renderer)
        {
            // Clear the blocks:
            FirstBox = null;
            LastBox  = null;

            // Get the text renderer (or create it):
            Css.TextRenderingProperty text = RequireTextProperty();

            // Get computed style:
            ComputedStyle cs = computedStyle;

            // Get the first box as it contains the fontface/ size:
            LayoutBox box = cs.FirstBox;

            // Colour too:
            Color fontColour = cs.Resolve(Css.Properties.ColorProperty.GlobalProperty).GetColour(this, Css.Properties.ColorProperty.GlobalProperty);

            // Colour:
            text.BaseColour = fontColour;

            // Font size update:
            float fontSize = box.FontSize;

            text.FontSize = fontSize;

            // Spacing:
            float wordSpacing   = cs.ResolveDecimal(Css.Properties.WordSpacing.GlobalProperty);
            float letterSpacing = cs.ResolveDecimal(Css.Properties.LetterSpacing.GlobalProperty);

            // If word spacing is not 'normal', remove 1em from it (Note that letter spacing is always additive):
            if (wordSpacing == -1f)
            {
                wordSpacing = 0f;
            }
            else
            {
                wordSpacing -= fontSize;
            }

            text.WordSpacing   = wordSpacing;
            text.LetterSpacing = letterSpacing;

            // Decoration:
            int decoration = cs.ResolveInt(Css.Properties.TextDecorationLine.GlobalProperty);

            if (decoration == 0)
            {
                // Remove a line if we have one:
                text.TextLine = null;
            }
            else
            {
                // Got a line!
                if (text.TextLine == null)
                {
                    text.TextLine = new TextDecorationInfo(decoration);
                }

                // Get the colour:
                Css.Value lineColour = cs.Resolve(Css.Properties.TextDecorationColor.GlobalProperty);

                if (lineColour == null || lineColour.IsType(typeof(Css.Keywords.CurrentColor)))
                {
                    // No override:
                    text.TextLine.ColourOverride = false;
                }
                else
                {
                    // Set the colour:
                    text.TextLine.SetColour(lineColour.GetColour(this, Css.Properties.TextDecorationColor.GlobalProperty));
                }
            }

            // Get the font face:
            text.FontToDraw = box.FontFace;

            // Overflow-wrap mode (only active for 'break-word' which is just '1'):
            text.OverflowWrapActive = (cs.ResolveInt(Css.Properties.OverflowWrap.GlobalProperty) == 1);

            // Check if the text is 'dirty'.
            // If it is, that means we'll need to rebuild the TextRenderingProperty's Glyph array.

            if (text.Dirty)
            {
                // Setup text now:
                // (Resets text.Characters based on all the text related CSS properties like variant etc).
                text.LoadCharacters((Node as RenderableTextNode).characterData_, this);
            }

            if (text.Characters == null || text.AllEmpty)
            {
                text.FontSize = 0f;
                return;
            }
        }