private static void DrawAdaptativeString(IFlxGraphics Canvas, TAdaptativeFormats AdaptativeFormats, string Text, Font AFont, Brush TextBrush, real x, real y) { int start = 0; foreach (TCharAndPos cp in AdaptativeFormats.Separators) { if (cp.Pos >= Text.Length) { break; //just a security measure. } string SubText = Text.Substring(start, cp.Pos - start); Canvas.DrawString(SubText, AFont, TextBrush, x, y); start = cp.Pos + 1; x += Canvas.MeasureString(SubText + Text[cp.Pos], AFont).Width; if (start - 1 < Text.Length && CharUtils.IsSurrogatePair(Text, start - 1)) { start++; } } if (start < Text.Length) { Canvas.DrawString(Text.Substring(start), AFont, TextBrush, x, y); } }
internal TXRichString(TRichString aString, bool aSplit, real aXExtent, real aYExtent, TAdaptativeFormats aAdaptFormat) { s = aString; Split = aSplit; XExtent = aXExtent; YExtent = aYExtent; AdaptFormat = aAdaptFormat; }
internal static void WriteText(ExcelFile Workbook, IFlxGraphics Canvas, TFontCache FontCache, real Zoom100, Font AFont, Color AFontColor, real x, real y, real SubOfs, TRichString OutText, real Alpha, real MaxDescent, TAdaptativeFormats AdaptativeFormats) { if (OutText.Length == 0) { return; } if (Alpha != 0) { Canvas.SaveTransform(); } try { if (Alpha != 0) { Canvas.Rotate(x, y, Alpha); } using (Brush TextBrush = new SolidBrush(AFontColor)) { if (OutText.RTFRunCount == 0) { if (AdaptativeFormats == null || AdaptativeFormats.Separators == null || AdaptativeFormats.Separators.Length == 0) //formats are only applied to non rich text cells. { Canvas.DrawString(OutText.Value, AFont, TextBrush, x, y + SubOfs); } else { DrawAdaptativeString(Canvas, AdaptativeFormats, OutText.Value, AFont, TextBrush, x, y + SubOfs); } } else { SizeF Result; string s1 = OutText.Value.Substring(0, OutText.RTFRun(0).FirstChar); if (s1.Length > 0) { Result = Canvas.MeasureString(s1, AFont, new TPointF(x, y)); Canvas.DrawString(s1, AFont, TextBrush, x, y + SubOfs - (MaxDescent - Canvas.FontDescent(AFont))); x += Result.Width; } for (int i = 0; i < OutText.RTFRunCount - 1; i++) { TFlxFont Fx = OutText.GetFont(OutText.RTFRun(i).FontIndex); TSubscriptData Sub = new TSubscriptData(Fx.Style); Font MyFont = FontCache.GetFont(Fx, Zoom100 * Sub.Factor); { using (Brush MyBrush = new SolidBrush(GetColor(Workbook, Fx.Color))) { int Start = OutText.RTFRun(i).FirstChar; if (Start >= OutText.Length) { Start = OutText.Length; } int Len = OutText.RTFRun(i + 1).FirstChar; if (Len >= OutText.Length) { Len = OutText.Length; } Len -= Start; string s2 = OutText.Value.Substring(Start, Len); Result = Canvas.MeasureString(s2, MyFont, new TPointF(x, y)); Canvas.DrawString(s2, MyFont, MyBrush, x, y + Sub.Offset(Canvas, MyFont) - (MaxDescent - Canvas.FontDescent(MyFont))); x += Result.Width; } } } TFlxFont Fy = OutText.GetFont(OutText.RTFRun(OutText.RTFRunCount - 1).FontIndex); TSubscriptData Suby = new TSubscriptData(Fy.Style); Font MyFont2 = FontCache.GetFont(Fy, Zoom100 * Suby.Factor); { using (Brush MyBrush = new SolidBrush(GetColor(Workbook, Fy.Color))) { int Start = OutText.RTFRun(OutText.RTFRunCount - 1).FirstChar; if (Start >= OutText.Length) { Start = OutText.Length; } string s3 = OutText.Value.Substring(Start); Result = Canvas.MeasureString(s3, MyFont2, new TPointF(x, y)); Canvas.DrawString(s3, MyFont2, MyBrush, x, y + Suby.Offset(Canvas, MyFont2) - (MaxDescent - Canvas.FontDescent(MyFont2))); } } } } } finally { if (Alpha != 0) { Canvas.ResetTransform(); } } }
private static void WriteJustText(ExcelFile Workbook, IFlxGraphics Canvas, TFontCache FontCache, real Zoom100, bool ReverseRightToLeftStrings, Font AFont, Color AFontColor, real y, real SubOfs, RectangleF CellRect, real Clp, TRichString OutText, real XExtent, real MaxDescent, bool Distributed, TAdaptativeFormats AdaptativeFormats) { List <TRichString> Words = new List <TRichString>(); OutText = GetVisualString(OutText, ReverseRightToLeftStrings); string s = OutText.Value; int p = 0; int p1 = 0; while ((p1 = s.IndexOf(' ', p)) >= 0) { Words.Add(OutText.Substring(p, p1 - p + 1)); p = p1 + 1; } if (p < s.Length) { Words.Add(OutText.Substring(p)); } real md; real wc = XExtent; // CalcTextExtent(AFont, OutText, out md).Width; real Spaces = 0; if (Words.Count - 1 > 0) { Spaces = (CellRect.Width - 2 - 2 * Clp - wc) / (Words.Count - 1); } real x = CellRect.Left + 1 + Clp; if (Words.Count == 1 && Distributed) //Center when it is one word { x = (CellRect.Left + CellRect.Right - 2 - 2 * Clp - wc) / 2; } for (int i = 0; i < Words.Count; i++) { TRichString wo = Words[i]; WriteText(Workbook, Canvas, FontCache, Zoom100, AFont, AFontColor, x, y, SubOfs, wo, 0, MaxDescent, AdaptativeFormats); x += RenderMetrics.CalcTextExtent(Canvas, FontCache, Zoom100, AFont, wo, out md).Width; if (Spaces > 0) { x += Spaces; } } }
internal static void CalcTextBox(IFlxGraphics Canvas, TFontCache FontCache, real Zoom100, RectangleF CellRect, real Clp, bool MultiLine, real Alpha, bool Vertical, TRichString OutText, Font AFont, TAdaptativeFormats AdaptativeFormats, out SizeF TextExtent, out TXRichStringList TextLines, out TFloatList MaxDescent) { TextExtent = new SizeF(0, 0); TextLines = new TXRichStringList(); MaxDescent = new TFloatList(); real MaxTextWidth; if (MultiLine || Vertical) { real Md; real TextHeight = RenderMetrics.CalcTextExtent(Canvas, FontCache, Zoom100, AFont, new TRichString("M"), out Md).Height; //not perfect since the rich string might have different fonts, but a good approx. MaxTextWidth = CalcMaxTextWidth(ref CellRect, Clp, Alpha, TextHeight); RenderMetrics.SplitText(Canvas, FontCache, Zoom100, OutText, AFont, MaxTextWidth, TextLines, out TextExtent, Vertical, MaxDescent, AdaptativeFormats); } else { TextLines.Add(new TXRichString(OutText, false, 0, 0, AdaptativeFormats)); real mdx = 0; TextExtent = RenderMetrics.CalcTextExtent(Canvas, FontCache, Zoom100, AFont, OutText, out mdx); TextLines[0].XExtent = TextExtent.Width; TextLines[0].YExtent = TextExtent.Height; MaxTextWidth = CalcMaxTextWidth(ref CellRect, Clp, Alpha, TextExtent.Height); MaxDescent.Add(mdx); } if (AdaptativeFormats != null && AdaptativeFormats.WildcardPos >= 0) { MaxTextWidth -= 2 * Clp; //Add some extra clipping so the text doesn't go through the line. if (Vertical) { } else { AddWildcard(Canvas, FontCache, Zoom100, AFont, MaxTextWidth, TextLines, ref TextExtent); } } }
internal static void SplitText(IFlxGraphics Canvas, TFontCache FontCache, real Zoom100, TRichString Text, Font AFont, real w, TXRichStringList TextLines, out SizeF TextExtent, bool Vertical, TFloatList MaxDescent, TAdaptativeFormats AdaptFormat) { TextLines.Clear(); MaxDescent.Clear(); int idx = 0; int fit = 0; TextExtent = new SizeF(0, 0); if (w <= 0 || Text.Value.Length <= 0) { return; } while (idx < Text.Value.Length) { int Enter = Text.Value.IndexOf((char)0x0A, idx); int MaxLength = Text.Value.Length - idx; if (Enter >= 0) { MaxLength = Enter - idx; } if (Vertical) { fit = 1; CharUtils.SameOrMore(Text.Value, idx, ref fit); } else { //Not a really efficient way, but... //First Guess. whole string. fit = MaxLength; real md; real wc = CalcTextExtent(Canvas, FontCache, Zoom100, AFont, Text.Substring(idx, fit), out md).Width; FitOneLine(Canvas, FontCache, Zoom100, Text, AFont, w, idx, ref fit, ref wc); if (fit <= 0) { fit = 1; //avoid infinite loop } CharUtils.SameOrMore(Text.Value, idx, ref fit); if (Text.Value.IndexOf(' ', idx, fit) >= 0) { int minfit = 1; CharUtils.SameOrMore(Text.Value, idx, ref minfit); while (fit > minfit && fit < MaxLength && Text.Value[idx + fit] != ' ') { fit--; } } while (fit < MaxLength && Text.Value[idx + fit] == ' ') { fit++; } //No need to adjust fit for surrogates. it will always be at the start of one. } //int Enter=Text.Value.IndexOf((char)0x0A, idx, fit); //if (Enter>0) fit=Enter-idx; int TextLen = Math.Min(MaxLength, fit); TextLines.Add(new TXRichString(Text.Substring(idx, TextLen), true, 0, 0, TAdaptativeFormats.CopyTo(AdaptFormat, idx, TextLen))); if (fit + idx < Text.Value.Length && Text.Value[idx + fit] == (char)0x0A) { TextLines[TextLines.Count - 1].Split = false; if (idx + fit < Text.Value.Length - 1) //An Enter at the end behaves different, it means we have a new empty line. { idx++; } } if (fit + idx >= Text.Value.Length) { TextLines[TextLines.Count - 1].Split = false; } idx += fit; //Recalculate dx real mdx = 0; TRichString sx = TextLines[TextLines.Count - 1].s; SizeF bSize = CalcTextExtent(Canvas, FontCache, Zoom100, AFont, sx, out mdx); if (bSize.Height == 0) { real mdx3; SizeF bSize3 = CalcTextExtent(Canvas, FontCache, Zoom100, AFont, new TRichString("M"), out mdx3); bSize.Height = bSize3.Height; } SizeF bSize2 = bSize; if (sx != null && sx.Length > 0 && sx.ToString()[sx.Length - 1] == ' ') //This is to right align line with spaces at the end. { real mdx2; bSize2 = CalcTextExtent(Canvas, FontCache, Zoom100, AFont, sx.RightTrim(), out mdx2); } TextLines[TextLines.Count - 1].XExtent = bSize2.Width; TextLines[TextLines.Count - 1].YExtent = bSize.Height; // not bSize2.Height; This might be even 0. MaxDescent.Add(mdx); if (TextExtent.Width < bSize.Width) { TextExtent.Width = bSize.Width; } TextExtent.Height += bSize.Height; } //while }