/// <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); } }
private void CutWord() { if (_curword.Text.Length > 0) { Words.Add(_curword); } _curword = new CssBoxWord(Box); }
/// <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); } }
/// <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; } } }
/// <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> /// 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 CssBoxWordSplitter() { _words = new List <CssBoxWord>(); _curword = null; }