예제 #1
0
        /// <summary>
        /// Applies right alignment to the text on the linebox
        /// </summary>
        /// <param name="g"></param>
        /// <param name="lineBox"></param>
        private static void ApplyRightAlignment(Graphics g, CssLineBox line)
        {
            if (line.Words.Count == 0)
            {
                return;
            }


            CssBoxWord lastWord = line.Words[line.Words.Count - 1];
            float      right    = line.OwnerBox.ActualRight - line.OwnerBox.ActualPaddingRight - line.OwnerBox.ActualBorderRightWidth;
            float      diff     = right - lastWord.Right - lastWord.LastMeasureOffset.X - lastWord.OwnerBox.ActualBorderRightWidth - lastWord.OwnerBox.ActualPaddingRight;


            if (diff <= 0)
            {
                return;
            }

            //if (line.OwnerBox.Direction == CssConstants.Rtl)
            //{

            //}

            foreach (CssBoxWord word in line.Words)
            {
                word.Left += diff;
            }

            foreach (CssBox b in line.Rectangles.Keys)
            {
                RectangleF r = b.Rectangles[line];
                b.Rectangles[line] = new RectangleF(r.X + diff, r.Y, r.Width, r.Height);
            }
        }
예제 #2
0
        private static void ApplyCenterAlignment(Graphics g, CssLineBox line)
        {
            if (line.Words.Count == 0)
            {
                return;
            }
            CssBoxWord item              = line.Words[line.Words.Count - 1];
            float      actualRight       = line.OwnerBox.ActualRight - line.OwnerBox.ActualPaddingRight - line.OwnerBox.ActualBorderRightWidth;
            float      right             = actualRight - item.Right;
            PointF     lastMeasureOffset = item.LastMeasureOffset;
            float      x = right - lastMeasureOffset.X - item.OwnerBox.ActualBorderRightWidth - item.OwnerBox.ActualPaddingRight;

            x = x / 2f;
            if (x <= 0f)
            {
                return;
            }
            foreach (CssBoxWord word in line.Words)
            {
                CssBoxWord left = word;
                left.Left = left.Left + x;
            }
            foreach (CssBox key in line.Rectangles.Keys)
            {
                RectangleF rectangleF = key.Rectangles[line];
                key.Rectangles[line] = new RectangleF(rectangleF.X + x, rectangleF.Y, rectangleF.Width, rectangleF.Height);
            }
        }
 private void CutWord()
 {
     if (this._curword.Text.Length > 0)
     {
         this.Words.Add(this._curword);
     }
     this._curword = new CssBoxWord(this.Box);
 }
 private void CutWord()
 {
     if (_curword.Text.Length > 0)
     {
         Words.Add(_curword);
     }
     _curword = new CssBoxWord(Box);
 }
예제 #5
0
 internal void ReportExistanceOf(CssBoxWord word)
 {
     if (!this.Words.Contains(word))
     {
         this.Words.Add(word);
     }
     if (!this.RelatedBoxes.Contains(word.OwnerBox))
     {
         this.RelatedBoxes.Add(word.OwnerBox);
     }
 }
        /// <summary>
        /// Splits the text on words using rules of the specified box
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        public void SplitWords()
        {
            if (string.IsNullOrEmpty(Text))
            {
                return;
            }

            _curword = new CssBoxWord(Box);

            bool onspace = IsSpace(Text[0]);

            for (int i = 0; i < Text.Length; i++)
            {
                if (IsSpace(Text[i]))
                {
                    if (!onspace)
                    {
                        CutWord();
                    }

                    if (IsLineBreak(Text[i]))
                    {
                        _curword.AppendChar('\n');
                        CutWord();
                    }
                    else if (IsTab(Text[i]))
                    {
                        _curword.AppendChar('\t');
                        CutWord();
                    }
                    else
                    {
                        _curword.AppendChar(' ');
                    }

                    onspace = true;
                }
                else
                {
                    if (onspace)
                    {
                        CutWord();
                    }
                    _curword.AppendChar(Text[i]);

                    onspace = false;
                }
            }

            CutWord();
        }
        /// <summary>
        /// Sets the baseline of the words of the specified box to certain height
        /// </summary>
        /// <param name="g">Device info</param>
        /// <param name="b">box to check words</param>
        /// <param name="baseline">baseline</param>
        internal void SetBaseLine(Graphics g, CssBox b, float baseline)
        {
            //TODO: Aqui me quede, checar poniendo "by the" con un font-size de 3em
            List <CssBoxWord> ws = WordsOf(b);

            if (!Rectangles.ContainsKey(b))
            {
                return;
            }

            RectangleF r = Rectangles[b];

            //Save top of words related to the top of rectangle
            float gap = 0f;

            if (ws.Count > 0)
            {
                gap = ws[0].Top - r.Top;
            }
            else
            {
                CssBoxWord firstw = b.FirstWordOccourence(b, this);

                if (firstw != null)
                {
                    gap = firstw.Top - r.Top;
                }
            }

            //New top that words will have
            //float newtop = baseline - (Height - OwnerBox.FontDescent - 3); //OLD
            float newtop = baseline - GetBaseLineHeight(b, g); //OLD

            if (b.ParentBox != null &&
                b.ParentBox.Rectangles.ContainsKey(this) &&
                r.Height < b.ParentBox.Rectangles[this].Height)
            {
                //Do this only if rectangle is shorter than parent's
                float      recttop = newtop - gap;
                RectangleF newr    = new RectangleF(r.X, recttop, r.Width, r.Height);
                Rectangles[b] = newr;
                b.OffsetRectangle(this, gap);
            }
            foreach (CssBoxWord w in ws)
            {
                if (!w.IsImage)
                {
                    w.Top = newtop;
                }
            }
        }
        public void SplitWords()
        {
            if (string.IsNullOrEmpty(this.Text))
            {
                return;
            }
            this._curword = new CssBoxWord(this.Box);
            bool flag = this.IsSpace(this.Text[0]);

            for (int i = 0; i < this.Text.Length; i++)
            {
                if (!this.IsSpace(this.Text[i]))
                {
                    if (flag)
                    {
                        this.CutWord();
                    }
                    this._curword.AppendChar(this.Text[i]);
                    flag = false;
                }
                else
                {
                    if (!flag)
                    {
                        this.CutWord();
                    }
                    if (this.IsLineBreak(this.Text[i]))
                    {
                        this._curword.AppendChar('\n');
                        this.CutWord();
                    }
                    else if (!this.IsTab(this.Text[i]))
                    {
                        this._curword.AppendChar(' ');
                    }
                    else
                    {
                        this._curword.AppendChar('\t');
                        this.CutWord();
                    }
                    flag = true;
                }
            }
            this.CutWord();
        }
예제 #9
0
 private static void FlowBox(Graphics g, CssBox blockbox, CssBox box, float maxright, float linespacing, float startx, ref CssLineBox line, ref float curx, ref float cury, ref float maxbottom)
 {
     box.FirstHostingLineBox = line;
     foreach (CssBox cssBox in box.Boxes)
     {
         float actualMarginLeft        = cssBox.ActualMarginLeft + cssBox.ActualBorderLeftWidth + cssBox.ActualPaddingLeft;
         float actualMarginRight       = cssBox.ActualMarginRight + cssBox.ActualBorderRightWidth + cssBox.ActualPaddingRight;
         float actualBorderTopWidth    = cssBox.ActualBorderTopWidth;
         float actualPaddingTop        = cssBox.ActualPaddingTop;
         float actualBorderBottomWidth = cssBox.ActualBorderBottomWidth;
         float single = cssBox.ActualPaddingTop;
         cssBox.RectanglesReset();
         cssBox.MeasureWordsSize(g);
         curx = curx + actualMarginLeft;
         if (cssBox.Words.Count <= 0)
         {
             CssLayoutEngine.FlowBox(g, blockbox, cssBox, maxright, linespacing, startx, ref line, ref curx, ref cury, ref maxbottom);
         }
         else
         {
             foreach (CssBoxWord word in cssBox.Words)
             {
                 if (cssBox.WhiteSpace != "nowrap" && curx + word.Width + actualMarginRight > maxright || word.IsLineBreak)
                 {
                     curx = startx;
                     cury = maxbottom + linespacing;
                     line = new CssLineBox(blockbox);
                     if (word.IsImage || word.Equals(cssBox.FirstWord))
                     {
                         curx = curx + actualMarginLeft;
                     }
                 }
                 line.ReportExistanceOf(word);
                 word.Left = curx;
                 word.Top  = cury;
                 curx      = word.Right;
                 maxbottom = Math.Max(maxbottom, word.Bottom);
                 CssLayoutEngine._lastTreatedWord = word;
             }
         }
         curx = curx + actualMarginRight;
     }
     box.LastHostingLineBox = line;
 }
예제 #10
0
        internal void SetBaseLine(Graphics g, CssBox b, float baseline)
        {
            List <CssBoxWord> cssBoxWords = this.WordsOf(b);

            if (!this.Rectangles.ContainsKey(b))
            {
                return;
            }
            RectangleF item = this.Rectangles[b];
            float      top  = 0f;

            if (cssBoxWords.Count <= 0)
            {
                CssBoxWord cssBoxWord = b.FirstWordOccourence(b, this);
                if (cssBoxWord != null)
                {
                    top = cssBoxWord.Top - item.Top;
                }
            }
            else
            {
                top = cssBoxWords[0].Top - item.Top;
            }
            float single = baseline - this.GetBaseLineHeight(b, g);

            if (b.ParentBox != null && b.ParentBox.Rectangles.ContainsKey(this) && item.Height < b.ParentBox.Rectangles[this].Height)
            {
                float      single1    = single - top;
                RectangleF rectangleF = new RectangleF(item.X, single1, item.Width, item.Height);
                this.Rectangles[b] = rectangleF;
                b.OffsetRectangle(this, top);
            }
            foreach (CssBoxWord cssBoxWord1 in cssBoxWords)
            {
                if (cssBoxWord1.IsImage)
                {
                    continue;
                }
                cssBoxWord1.Top = single;
            }
        }
예제 #11
0
        /// <summary>
        /// Recursively flows the content of the box using the inline model
        /// </summary>
        /// <param name="g">Device Info</param>
        /// <param name="blockbox">Blockbox that contains the text flow</param>
        /// <param name="box">Current box to flow its content</param>
        /// <param name="maxright">Maximum reached right</param>
        /// <param name="linespacing">Space to use between rows of text</param>
        /// <param name="startx">x starting coordinate for when breaking lines of text</param>
        /// <param name="line">Current linebox being used</param>
        /// <param name="curx">Current x coordinate that will be the left of the next word</param>
        /// <param name="cury">Current y coordinate that will be the top of the next word</param>
        /// <param name="maxbottom">Maximum bottom reached so far</param>
        private static void FlowBox(Graphics g, CssBox blockbox, CssBox box, float maxright, float linespacing, float startx, ref CssLineBox line, ref float curx, ref float cury, ref float maxbottom)
        {
            box.FirstHostingLineBox = line;

            foreach (CssBox b in box.Boxes)
            {
                float leftspacing   = b.ActualMarginLeft + b.ActualBorderLeftWidth + b.ActualPaddingLeft;
                float rightspacing  = b.ActualMarginRight + b.ActualBorderRightWidth + b.ActualPaddingRight;
                float topspacing    = b.ActualBorderTopWidth + b.ActualPaddingTop;
                float bottomspacing = b.ActualBorderBottomWidth + b.ActualPaddingTop;

                b.RectanglesReset();
                b.MeasureWordsSize(g);

                curx += leftspacing;

                if (b.Words.Count > 0)
                {
                    #region Flow words

                    foreach (CssBoxWord word in b.Words)
                    {
                        //curx += word.SpacesBeforeWidth;

                        if ((b.WhiteSpace != CssConstants.Nowrap && curx + word.Width + rightspacing > maxright) ||
                            word.IsLineBreak)
                        {
                            #region Break line

                            curx = startx;
                            cury = maxbottom + linespacing;

                            line = new CssLineBox(blockbox);

                            if (word.IsImage || word.Equals(b.FirstWord))
                            {
                                curx += leftspacing;
                            }

                            #endregion
                        }

                        line.ReportExistanceOf(word);

                        word.Left = curx;                             // -word.LastMeasureOffset.X + 1;
                        word.Top  = cury;                             // - word.LastMeasureOffset.Y;

                        curx      = word.Right;                       // +word.SpacesAfterWidth;
                        maxbottom = Math.Max(maxbottom, word.Bottom); //+ (word.IsImage ? topspacing + bottomspacing : 0));

                        _lastTreatedWord = word;
                    }

                    #endregion
                }
                else
                {
                    FlowBox(g, blockbox, b, maxright, linespacing, startx, ref line, ref curx, ref cury, ref maxbottom);
                }

                curx += rightspacing;
            }

            box.LastHostingLineBox = line;
        }
예제 #12
0
        internal void AppendChar(char c)
        {
            CssBoxWord cssBoxWord = this;

            cssBoxWord._word = string.Concat(cssBoxWord._word, c);
        }
 private CssBoxWordSplitter()
 {
     this._words   = new List <CssBoxWord>();
     this._curword = null;
 }
예제 #14
0
        /// <summary>
        /// Lets the linebox add the word an its box to their lists if necessary.
        /// </summary>
        /// <param name="word"></param>
        internal void ReportExistanceOf(CssBoxWord word)
        {
            if (!Words.Contains(word))
            {
                Words.Add(word);
            }

            if (!RelatedBoxes.Contains(word.OwnerBox))
            {
                RelatedBoxes.Add(word.OwnerBox);
            }
        }
예제 #15
0
 /// <summary>
 /// Gets the longest word (in width) inside the box, deeply.
 /// </summary>
 /// <param name="b"></param>
 /// <returns></returns>
 private void GetMinimumWidth_LongestWord(CssBox b, ref float maxw, ref CssBoxWord word)
 {
     if (b.Words.Count > 0)
     {
         foreach (CssBoxWord w in b.Words)
         {
             if (w.FullWidth > maxw)
             {
                 maxw = w.FullWidth;
                 word = w;
             }
         }
     }
     else
     {
         foreach(CssBox bb in b.Boxes)
             GetMinimumWidth_LongestWord(bb, ref maxw,ref word);
     }
 }
예제 #16
0
        /// <summary>
        /// Recursively flows the content of the box using the inline model
        /// </summary>
        /// <param name="g">Device Info</param>
        /// <param name="blockbox">Blockbox that contains the text flow</param>
        /// <param name="box">Current box to flow its content</param>
        /// <param name="maxright">Maximum reached right</param>
        /// <param name="linespacing">Space to use between rows of text</param>
        /// <param name="startx">x starting coordinate for when breaking lines of text</param>
        /// <param name="line">Current linebox being used</param>
        /// <param name="curx">Current x coordinate that will be the left of the next word</param>
        /// <param name="cury">Current y coordinate that will be the top of the next word</param>
        /// <param name="maxbottom">Maximum bottom reached so far</param>
        private static void FlowBox(Graphics g, CssBox blockbox, CssBox box, float maxright, float linespacing, float startx,ref CssLineBox line, ref float curx, ref float cury, ref float maxbottom)
        {
            box.FirstHostingLineBox = line;

            foreach (CssBox b in box.Boxes)
            {

                float leftspacing = b.ActualMarginLeft + b.ActualBorderLeftWidth + b.ActualPaddingLeft;
                float rightspacing = b.ActualMarginRight + b.ActualBorderRightWidth + b.ActualPaddingRight;
                float topspacing = b.ActualBorderTopWidth + b.ActualPaddingTop;
                float bottomspacing = b.ActualBorderBottomWidth + b.ActualPaddingTop;

                b.RectanglesReset();
                b.MeasureWordsSize(g);

                curx += leftspacing;

                if (b.Words.Count > 0)
                {
                    #region Flow words

                    foreach (CssBoxWord word in b.Words)
                    {
                        //curx += word.SpacesBeforeWidth;

                        if ((b.WhiteSpace != CssConstants.Nowrap && curx + word.Width + rightspacing > maxright) ||
                            word.IsLineBreak)
                        {
                            #region Break line

                            curx = startx;
                            cury = maxbottom + linespacing;

                            line = new CssLineBox(blockbox);

                            if (word.IsImage || word.Equals(b.FirstWord))
                            {
                                curx += leftspacing;
                            }

                            #endregion
                        }

                        line.ReportExistanceOf(word);

                        word.Left = curx;// -word.LastMeasureOffset.X + 1;
                        word.Top = cury;// - word.LastMeasureOffset.Y;

                        curx = word.Right;// +word.SpacesAfterWidth;
                        maxbottom = Math.Max(maxbottom, word.Bottom );//+ (word.IsImage ? topspacing + bottomspacing : 0));

                        _lastTreatedWord = word;
                    }

                    #endregion
                }
                else
                {
                    FlowBox(g, blockbox, b, maxright, linespacing, startx,ref line, ref curx, ref cury, ref maxbottom);
                }

                curx += rightspacing;
            }

            box.LastHostingLineBox = line;
        }
 private void CutWord()
 {
     if(_curword.Text.Length > 0)
         Words.Add(_curword);
     _curword = new CssBoxWord(Box);
 }
        /// <summary>
        /// Splits the text on words using rules of the specified box
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        public void SplitWords()
        {

            if (string.IsNullOrEmpty(Text)) return;

            _curword = new CssBoxWord(Box);

            bool onspace = IsSpace(Text[0]);

            for (int i = 0; i < Text.Length; i++)
            {
                if (IsSpace(Text[i]))
                {
                    if (!onspace) CutWord();

                    if (IsLineBreak(Text[i]))
                    {
                        _curword.AppendChar('\n');
                        CutWord();
                    }
                    else if (IsTab(Text[i]))
                    {
                        _curword.AppendChar('\t');
                        CutWord();
                    }
                    else
                    {
                        _curword.AppendChar(' ');
                    }

                    onspace = true;
                }
                else
                {
                    if (onspace) CutWord();
                    _curword.AppendChar(Text[i]);

                    onspace = false;
                }
            }

            CutWord();
        }
 private CssBoxWordSplitter()
 {
     _words   = new List <CssBoxWord>();
     _curword = null;
 }
 private CssBoxWordSplitter()
 {
     _words = new List<CssBoxWord>();
     _curword = null;
 }
예제 #21
0
        /// <summary>
        /// Assigns words its width and height
        /// </summary>
        /// <param name="g"></param>
        internal void MeasureWordsSize(Graphics g)
        {
            if (_wordsSizeMeasured) return;

            //Measure white space if not yet done
            if (float.IsNaN(_actualWordSpacing))
                MeasureWordSpacing(g);

            if (HtmlTag != null && HtmlTag.TagName.Equals("img", StringComparison.CurrentCultureIgnoreCase))
            {
                #region Measure image

                CssBoxWord word = new CssBoxWord(this, CssValue.GetImage(GetAttribute("src")));
                Words.Clear();
                Words.Add(word);

                #endregion
            }
            else
            {
                #region Measure text words

                bool lastWasSpace = false;

                foreach (CssBoxWord b in Words)
                {
                    bool collapse = CssBoxWordSplitter.CollapsesWhiteSpaces(this);
                    if (CssBoxWordSplitter.EliminatesLineBreaks(this)) b.ReplaceLineBreaksAndTabs();

                    if (b.IsSpaces)
                    {
                        b.Height = FontLineSpacing;

                        if (b.IsTab)
                        {
                            b.Width = ActualWordSpacing * 4; //TODO: Configure tab size
                        }
                        else if (b.IsLineBreak)
                        {
                            b.Width = 0;
                        }
                        else
                        {
                            if (!(lastWasSpace && collapse))
                            {
                                b.Width = ActualWordSpacing * (collapse ? 1 : b.Text.Length);
                            }
                        }

                        lastWasSpace = true;
                    }
                    else
                    {
                        string word = b.Text;

                        CharacterRange[] measurable = { new CharacterRange(0, word.Length) };
                        StringFormat sf = new StringFormat();

                        sf.SetMeasurableCharacterRanges(measurable);

                        Region[] regions = g.MeasureCharacterRanges(word, ActualFont,
                            new RectangleF(0, 0, float.MaxValue, float.MaxValue),
                            sf);

                        SizeF s = regions[0].GetBounds(g).Size;
                        PointF p = regions[0].GetBounds(g).Location;

                        b.LastMeasureOffset = new PointF(p.X, p.Y);
                        b.Width = s.Width;// +p.X;
                        b.Height = s.Height;// +p.Y;

                        lastWasSpace = false;
                    }
                }
                #endregion
            }

            _wordsSizeMeasured = true;
        }