/// <summary> /// Methods produces DXF string for text of the Flowchart object /// </summary> /// <param name="co">Flowchart object to extract text from</param> /// <param name="po">Parent object if any exist</param> /// <param name="rect">Object's rectangle if applicable</param> /// <returns>true if successful otherwise false</returns> public bool AddText(object co, object po, RectangleF rect) { PointF[] pF = null; MindFusion.FlowChartX.Text.Layout tl = null; MindFusion.FlowChartX.Text.LayoutOptions lo; MindFusion.FlowChartX.Text.DrawTextHint dhint = null; MindFusion.FlowChartX.Text.PlainText text = null; System.Drawing.SolidBrush br = null; int tlen = 0; GraphicsPath gr = null; Color crText = Color.Transparent; string strText = ""; long TextID = 0; RectangleF boundrect = RectangleF.Empty; Font oFont = null; StringFormat sformat = null; float Rotation = 0; bool bOk = false; try { gr = new GraphicsPath(FillMode.Winding); if ( co is Box ) // if chart object is Box { Box oBox = co as Box; if ( oBox == null ) return false; strText = oBox.PlainText; crText = oBox.TextColor; TextID = oBox.ZIndex; boundrect = oBox.BoundingRect; oFont = oBox.Font; sformat = oBox.TextFormat; Rotation = oBox.RotationAngle; if (!m_ExportTextAsMultiline) { TextBox2Path(oBox,0,ref gr); pF = (PointF[])gr.PathPoints.Clone(); } } else if ( co is Table.Cell ) // if chart object is cell in the table { Table.Cell oCell = co as Table.Cell; if ( oCell == null ) return false; Table oTable = po as Table; if ( oTable == null ) return false; if ( rect == RectangleF.Empty ) return false; strText = oCell.PlainText; crText = oCell.TextColor; TextID = NextID(); oFont = oTable.Font; sformat = oCell.TextFormat; Rotation = 0; if (!m_ExportTextAsMultiline) { TextRect2Path(rect,ref gr); pF = (PointF[])gr.PathPoints.Clone(); } boundrect = rect; } else if ( co is Arrow ) // If chart object is arrow { Arrow oArrow = co as Arrow; if ( oArrow == null ) return false; strText = oArrow.Text; crText = oArrow.TextColor; TextID = oArrow.ZIndex; oFont = oArrow.Font; sformat = m_FlowChart.TextFormat; rect = getTextRect(System.Drawing.Graphics.FromHwnd(GetActiveWindow()), oArrow.Style , oArrow.TextStyle, oArrow.ControlPoints, oArrow.TextColor,oArrow.SegmentCount, oArrow.Text, oArrow.Font, RectangleF.Empty, ref Rotation); boundrect = rect; if (!m_ExportTextAsMultiline) { rect.Width+=1; rect.Height+=1; boundrect = rect; if (Rotation!=0) Rotation = 360 -Rotation; TextRect2Path(rect,ref gr); pF = (PointF[])gr.PathPoints.Clone(); } } else if ( co is Table ) // If chart object is table itself { Table oTable = co as Table; if ( oTable == null ) return false; strText = oTable.CaptionPlainText; crText = oTable.CaptionColor; TextID = NextID(); rect = new RectangleF(oTable.BoundingRect.X, oTable.BoundingRect.Y, oTable.BoundingRect.Width, oTable.CaptionHeight); boundrect = rect; oFont = oTable.Font; sformat = oTable.CaptionFormat; Rotation = 0; if (!m_ExportTextAsMultiline) { TextRect2Path(rect,ref gr); pF = (PointF[])gr.PathPoints.Clone(); } } else return false; // Preparing for text processing if ( strText == "" ) return true; if ( oFont == null ) oFont = m_FlowChart.Font; // If 'Multiline' text mode enabled calling method directly if ( m_ExportTextAsMultiline ) return AddText(TextID,boundrect, strText, crText, oFont , sformat, true, Rotation, false); if ( gr!=null ) gr.Dispose(); // If not 'Multiline' isn't allowed processing text word-by word tl = new MindFusion.FlowChartX.Text.Layout(); br = new System.Drawing.SolidBrush(crText); lo = new MindFusion.FlowChartX.Text.LayoutOptions(); dhint = new MindFusion.FlowChartX.Text.DrawTextHint(System.Drawing.Graphics.FromHwnd(GetActiveWindow()), oFont, br ,sformat, false , null, boundrect, crText, TextID*100, TextID, Rotation ); lo.Alignment = sformat.Alignment; lo.LineAlignment = sformat.LineAlignment; text = new MindFusion.FlowChartX.Text.PlainText(); text.Setup(strText, System.Drawing.Graphics.FromHwnd(GetActiveWindow()) , oFont); tlen = text.PlainText.Length; tl.LayoutInPolygon( text, docToLocal(pF, boundrect),lo); tl.Draw(0,0,new MindFusion.FlowChartX.Text.RenderTextCallback(___TextCallback),dhint); } catch ( Exception ex ) { bOk = false; m_status = ex.Message; Trace.WriteLine(String.Format("{0} error {1}\n","AddText",ex.Message)); } return bOk; }
/// <summary> /// Draws a previously laid-out text at a specified offset. /// </summary> public void Draw(float xOff, float yOff, RenderTextCallback renderCallback, DrawTextHint hint) { if (GetHLines(_totalLines) == null) throw new Exception("Draw invoked on a non-laid-out text."); if (GetHLines(_totalLines).Count == 0) return; bool styled = (_text is StyledText); // Original brush and font System.Drawing.Brush brushOriginal = hint.Brush; Font fontOriginal = hint.Font; // We now have the starting line and the number // of total lines to layout the text in. Go for it int iword = 0; for (int i = _startLine; i < _startLine + _totalLines; i++) { PointList hLine = GetHLines(_totalLines)[i] as PointList; for (int j = 0; j < hLine.Count; j += 2) { PointF pt1 = hLine[j]; PointF pt2 = hLine[j + 1]; RectangleF rc = new RectangleF( _bounds.X + xOff + pt1.X, _bounds.Y + yOff + pt1.Y, pt2.X - pt1.X, pt2.Y - pt1.Y); bool newLine = false; int newword = FitTextInRect(iword, rc, ref newLine); if (newword > iword) { // Calculate the total width of the words // which are about to be rendered, but skip // the whitespaces at the front and the rear int ifront = iword; int irear = newword - 1; while (ifront < newword && _text.Words[ifront].IsWhitespace) ifront++; while (irear >= ifront && _text.Words[irear].IsWhitespace) irear--; int w; float total = 0; for (w = ifront; w <= irear; w++) total += _text.Words[w].Width; // Adjust the left side of the destination // rectangle according to the specified alignment switch (_options.Alignment) { case StringAlignment.Near: // Do nothing break; case StringAlignment.Center: rc.X = rc.X + (rc.Width - total) / 2; break; case StringAlignment.Far: rc.X = rc.Right - total; break; } // Render the words in the range [ifront, irear] for (w = ifront; w <= irear; w++) { Word word = _text.Words[w]; if (!_fits && hint.AddEllipsis && styled) { if (i == _startLine + _totalLines - 1) { if (j == hLine.Count - 2) { if (w == irear) { // Append the last word with ellipsis StyledText.StyledWord sword = word as StyledText.StyledWord; StyledText.StyledWord newWord = null; int chars = sword.Value.Length; float width = sword.Width; do { newWord = new StyledText.StyledWord( sword.Value.Substring(0, chars) + "...", sword.Format, sword.Color); newWord.UpdateMeasures(hint.Graphics, hint.Font); chars--; } while (chars > 0 && newWord.Width > width); word = newWord; } } } } if (!word.IsLineBreak && !word.IsWhitespace) { if (styled) { // In case of styled text formatting, // apply fonts and colors StyledText.StyledWord sword = word as StyledText.StyledWord; hint.Font = sword.CreateFont(hint.Font); hint.Brush = sword.CreateBrush(hint.Brush); rc.Y += sword.YOffset; } // Add 10 to width and height becaus GDI+ stupid // and clips the text renderCallback(word.Value, new RectangleF( rc.X, rc.Y, word.Width + 10, rc.Height + 10), hint); if (styled) { // Restore font and brush StyledText.StyledWord sword = word as StyledText.StyledWord; sword.DisposeFont(hint.Font); sword.DisposeBrush(hint.Brush); hint.Font = fontOriginal; hint.Brush = brushOriginal; rc.Y -= sword.YOffset; } } rc.X += _text.Words[w].Width; } iword = newword; } if (newLine) break; } } }
/// <summary> /// Styled text rendering callback. /// </summary> private void DrawText(string text, RectangleF dest, DrawTextHint hint) { // Render formatted text hint.Graphics.DrawString(text, hint.Font, hint.Brush, dest, hint.Format); }
/// <summary> /// Draws a previously laid-out text at a specified offset. /// </summary> public void Draw(float xOff, float yOff, RenderTextCallback renderCallback, DrawTextHint hint) { if (GetHLines(_totalLines) == null) { throw new Exception("Draw invoked on a non-laid-out text."); } if (GetHLines(_totalLines).Count == 0) { return; } bool styled = (_text is StyledText); // Original brush and font System.Drawing.Brush brushOriginal = hint.Brush; Font fontOriginal = hint.Font; // We now have the starting line and the number // of total lines to layout the text in. Go for it int iword = 0; for (int i = _startLine; i < _startLine + _totalLines; i++) { PointList hLine = GetHLines(_totalLines)[i] as PointList; for (int j = 0; j < hLine.Count; j += 2) { PointF pt1 = hLine[j]; PointF pt2 = hLine[j + 1]; RectangleF rc = new RectangleF( _bounds.X + xOff + pt1.X, _bounds.Y + yOff + pt1.Y, pt2.X - pt1.X, pt2.Y - pt1.Y); bool newLine = false; int newword = FitTextInRect(iword, rc, ref newLine); if (newword > iword) { // Calculate the total width of the words // which are about to be rendered, but skip // the whitespaces at the front and the rear int ifront = iword; int irear = newword - 1; while (ifront < newword && _text.Words[ifront].IsWhitespace) { ifront++; } while (irear >= ifront && _text.Words[irear].IsWhitespace) { irear--; } int w; float total = 0; for (w = ifront; w <= irear; w++) { total += _text.Words[w].Width; } // Adjust the left side of the destination // rectangle according to the specified alignment switch (_options.Alignment) { case StringAlignment.Near: // Do nothing break; case StringAlignment.Center: rc.X = rc.X + (rc.Width - total) / 2; break; case StringAlignment.Far: rc.X = rc.Right - total; break; } // Render the words in the range [ifront, irear] for (w = ifront; w <= irear; w++) { Word word = _text.Words[w]; if (!_fits && hint.AddEllipsis && styled) { if (i == _startLine + _totalLines - 1) { if (j == hLine.Count - 2) { if (w == irear) { // Append the last word with ellipsis StyledText.StyledWord sword = word as StyledText.StyledWord; StyledText.StyledWord newWord = null; int chars = sword.Value.Length; float width = sword.Width; do { newWord = new StyledText.StyledWord( sword.Value.Substring(0, chars) + "...", sword.Format, sword.Color); newWord.UpdateMeasures(hint.Graphics, hint.Font); chars--; }while (chars > 0 && newWord.Width > width); word = newWord; } } } } if (!word.IsLineBreak && !word.IsWhitespace) { if (styled) { // In case of styled text formatting, // apply fonts and colors StyledText.StyledWord sword = word as StyledText.StyledWord; hint.Font = sword.CreateFont(hint.Font); hint.Brush = sword.CreateBrush(hint.Brush); rc.Y += sword.YOffset; } // Add 10 to width and height becaus GDI+ stupid // and clips the text renderCallback(word.Value, new RectangleF( rc.X, rc.Y, word.Width + 10, rc.Height + 10), hint); if (styled) { // Restore font and brush StyledText.StyledWord sword = word as StyledText.StyledWord; sword.DisposeFont(hint.Font); sword.DisposeBrush(hint.Brush); hint.Font = fontOriginal; hint.Brush = brushOriginal; rc.Y -= sword.YOffset; } } rc.X += _text.Words[w].Width; } iword = newword; } if (newLine) { break; } } } }