/// <summary> /// Paints the graph. /// </summary> /// <param name="g">The graphic contents to paint to.</param> /// <param name="bForPrinting">Indicates if the painting is for printing purposes. Not used for the moment.</param> /// <remarks>The reference point (0,0) of the GraphDocument /// is the top left corner of the printable area (and not of the page area!). The hosting class has to translate the graphics origin /// to the top left corner of the printable area before calling this routine.</remarks> public void Paint(Graphics g, bool bForPrinting) { const int MaxFixupRetries = 10; if (System.Threading.Thread.CurrentThread == _paintThread) { throw new InvalidOperationException("DoPaint is called reentrant (i.e. from the same thread that is already executing DoPaint"); } lock (_paintLock) { if (!(null == _paintThread)) { throw new InvalidProgramException("We waited, thus _paintThread should be null"); } _paintThread = System.Threading.Thread.CurrentThread; // Suppress events that are fired during paint try { // First set the current thread's document culture _paintThread.CurrentCulture = GetPropertyValue(Altaxo.Settings.CultureSettings.PropertyKeyDocumentCulture, null).Culture; try { _isFixupInternalDataStructuresActive = true; for (int ithRetry = 1; ithRetry <= MaxFixupRetries; ++ithRetry) { try { _hasFixupChangedAnything = false; AdjustRootLayerPositionToFitIntoZeroOffsetRectangle(); RootLayer.FixupInternalDataStructures(); if (!_hasFixupChangedAnything) { break; } #if DEBUG if (ithRetry == MaxFixupRetries) { Current.Console.WriteLine("Warning: MaxFixupRetries exceeded during painting of graph {0}.", Name); } #endif } catch (Exception) { if (ithRetry == MaxFixupRetries) { throw; } } } } finally { _isFixupInternalDataStructuresActive = false; } var paintContext = new GdiPaintContext(); RootLayer.PaintPreprocessing(paintContext); RootLayer.Paint(g, paintContext); RootLayer.PaintPostprocessing(); } finally { _paintThread = null; } } // end of lock } // end of function DoPaint
/// <summary> /// Infrastructure. Don't use in your own projects. Will be called by PrintDocument during the printing process. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> public void EhPrintPage(object sender, PrintPageEventArgs e) { Graphics g = e.Graphics; var savedGraphics = g.Save(); float hx = e.PageSettings.HardMarginX; // in hundreths of inch float hy = e.PageSettings.HardMarginY; // in hundreths of inch var graphSize = (SizeF)_layers.Size; _printOptions.GetZoomAndStartLocation(e.PageBounds, e.MarginBounds, graphSize, out var zoom, out var startLocationOnPage, true); graphSize = graphSize.Scale(zoom); var startLocationInGraph = new PointF(0, 0); if (_printOptions.TilePages) { startLocationOnPage = e.MarginBounds.Location; // when tiling pages start always from margin bounds int columns = (int)Math.Ceiling(graphSize.Width / e.MarginBounds.Width); int rows = (int)Math.Ceiling(graphSize.Height / e.MarginBounds.Height); int col = _page % columns; int row = _page / columns; //startLocationInGraph = new PointF(col * e.MarginBounds.Width / zoom, row * e.MarginBounds.Height / zoom); startLocationOnPage.X -= col * e.MarginBounds.Width; startLocationOnPage.Y -= row * e.MarginBounds.Height; _page++; e.HasMorePages = _page < rows * columns; } if (_printOptions.PrintCropMarks) { float armLength = Math.Min(e.MarginBounds.Width, e.MarginBounds.Height) / 20.0f; DrawCross(g, new PointF(e.MarginBounds.Left, e.MarginBounds.Top), armLength); DrawCross(g, new PointF(e.MarginBounds.Right, e.MarginBounds.Top), armLength); DrawCross(g, new PointF(e.MarginBounds.Left, e.MarginBounds.Bottom), armLength); DrawCross(g, new PointF(e.MarginBounds.Right, e.MarginBounds.Bottom), armLength); } // DrawCrossedRectangle(g, e.MarginBounds); // from here on we have units of Points g.PageUnit = GraphicsUnit.Point; if (!IsPrintPreview) { g.TranslateTransform(-hx * 72 / 100.0f, -hy * 72 / 100.0f); } g.TranslateTransform(startLocationOnPage.X * 72 / 100.0f, startLocationOnPage.Y * 72 / 100.0f); g.ScaleTransform(zoom, zoom); var paintContext = new GdiPaintContext(); _layers.PaintPreprocessing(paintContext); _layers.Paint(g, paintContext); _layers.PaintPostprocessing(); g.Restore(savedGraphics); }