/// <summary> /// Render a path /// </summary> /// <param name="stroke">The stroke style to draw border</param> /// <param name="fill">The fill style to render inner region</param> /// <param name="path">The path geometry</param> /// <remarks>The stroke and the fill can both be a null reference (Nothing in Visual Basic). If the stroke is null, no stroke is performed. If the fill is null, no fill is performed.</remarks> public void DrawPath(Fill fill, DrawingPath path) { if (preparationRequired) Prepare(); #region detemin current scale factor double sizeScale = 1.0; if (currentTransform != null) { sizeScale = (currentTransform.ScaleXFactor > currentTransform.ScaleYFactor) ? currentTransform.ScaleXFactor : currentTransform.ScaleYFactor; } #endregion // this need scale factor before generate double[][] coordinates = mPathGenerator.Generate(path, 1.0); //transform input coordinates //render the inner region if (fill != null) { rasterizer = GetRasterizer(fill.Paint); rasterizer.Paint = fill; rasterizer.Begin(); if ((transformRequired)) { if ((rasterizer is TranformableRasterizer)) { // set transform matrix to current transformable matrix ((TranformableRasterizer)rasterizer).SetTransformMatrix(currentTransform); } for (int coordinateIndex = 0; coordinateIndex < coordinates.Length; coordinateIndex++) { rasterizer.AddPolygon( TransformCoordinates(coordinates[coordinateIndex]), coordinates[coordinateIndex].Length / 2, 0); } } else { // set paint before using approach 2 for (int coordinateIndex = 0; coordinateIndex < coordinates.Length; coordinateIndex++) { rasterizer.AddPolygon(coordinates[coordinateIndex], coordinates[coordinateIndex].Length / 2, 0); } } rasterizer.Finish(); } }
DrawingPath GetPath() { //create path DrawingPath path = new DrawingPath(); path.MoveTo(200, 100); path.CurveTo(200, 350, 340, 30, 360, 200); path.CurveTo(200, 100, 40, 200, 60, 30); return path; }
private void btnDrawPath_Click(object sender, EventArgs e) { //create a new drawing context PixelsBuffer buffer = new PixelsBuffer(400, 400); IDrawer drawer = new Drawer(buffer); drawer.Clear(Colors.White); //create fill for drawing Fill fill = Fills.MistyRose; //create path DrawingPath path = new DrawingPath(); path.MoveTo(200, 100); path.CurveTo(200, 350, 340, 30, 360, 200); path.CurveTo(200, 100, 40, 200, 60, 30); //draw content drawer.Rotate(15); drawer.Scale(0.3, 0.3); drawer.DrawPath(fill, path); //show to screen DisplayBuffer(buffer); }
/// <summary> /// Generate polygon from path /// </summary> /// <param name="path">path</param> /// <param name="averageScale">average scale of transform, this to decrease number of point generate for curve ...</param> /// <returns></returns> public double[][] Generate(DrawingPath path, double averageScale) { RawPolygonList polygonList = new RawPolygonList(); DrawingPathCommand[] commands = path.Commands; double[] coordinates = path.Coordinates; int commandCount = path.CommandCount; int coordinateCount = path.CoordinateCount; int coordinateIndex = 0; //foreach(PathCommand command in commands) for (int commandIndex = 0; commandIndex < commandCount; commandIndex++) { switch (commands[commandIndex]) { case DrawingPathCommand.MoveTo: case DrawingPathCommand.NewFigure: #region move to if (path.Commands[commandIndex + 1] == DrawingPathCommand.ArcTo) { coordinateIndex += 2; break; } polygonList.MoveTo(coordinates[coordinateIndex++], coordinates[coordinateIndex++]); break; #endregion case DrawingPathCommand.NewFigureAndCloseLast: #region close last and new figure // close last polygonList.CloseCurrentPolygon(); // move to polygonList.MoveTo(coordinates[coordinateIndex++], coordinates[coordinateIndex++]); break; #endregion case DrawingPathCommand.LineTo: #region line to polygonList.LineTo(coordinates[coordinateIndex++], coordinates[coordinateIndex++]); #endregion break; case DrawingPathCommand.ArcTo: #region arc to BuildArc(polygonList, coordinates[coordinateIndex - 2], // start x coordinates[coordinateIndex - 1], // start y coordinates[coordinateIndex++], // radius x coordinates[coordinateIndex++], // radius y coordinates[coordinateIndex++], // angle coordinates[coordinateIndex++] == DrawingPath.IsLargeArc, // is large arc coordinates[coordinateIndex++] == DrawingPath.IsSweepLeftSide, // is sweep left side coordinates[coordinateIndex++], // dest x coordinates[coordinateIndex++], // dest y averageScale); #endregion break; case DrawingPathCommand.CurveTo: #region curve to BuildCurve(polygonList, coordinates[coordinateIndex - 2], // start x coordinates[coordinateIndex - 1], // start y coordinates[coordinateIndex++], // control point 1 x coordinates[coordinateIndex++], // control point 1 y coordinates[coordinateIndex++], // control point 2 x coordinates[coordinateIndex++], // control point 2 y coordinates[coordinateIndex++], // end x coordinates[coordinateIndex++], // end y averageScale); #endregion break; case DrawingPathCommand.QuadraticTo: #region quadratic bezier BuildQuadratic(polygonList, coordinates[coordinateIndex - 2], // start x coordinates[coordinateIndex - 1], // start y coordinates[coordinateIndex++], // control point x coordinates[coordinateIndex++], // control point y coordinates[coordinateIndex++], // end x coordinates[coordinateIndex++], // end y averageScale); #endregion break; } } // finish generation polygonList.Finish(); return polygonList.RawDatas; }
/// <summary> /// Add a path to current path by transforming data from source path /// NOTES: Currently this method does not support Arc commands from source path /// </summary> /// <param name="path">The source path to copy from</param> public void AddPath(DrawingPath path, Matrix3x3 matrix) { // using array .copy only ReserveSpace(path.CommandCount, path.CoordinateCount); // change private fields currentFirstCommandIndex = CommandCount + path.currentFirstCommandIndex; currentFirstCoordinateIndex = CoordinateCount + path.currentFirstCoordinateIndex; currentFirstX = path.currentFirstX; currentFirstY = path.currentFirstY; // copy command Array.Copy(path.Commands, 0, Commands, CommandCount, path.CommandCount); CommandCount += path.CommandCount; // copy coordinates //Array.Copy(path.Coordinates, 0, Coordinates, CoordinateCount, path.CoordinateCount); //CoordinateCount += path.CoordinateCount; double sx = matrix.Sx; double sy = matrix.Sy; double shx = matrix.Shx; double shy = matrix.Shy; double tx = matrix.Tx; double ty = matrix.Ty; //double tmp = x; //x = tmp * Sx + y * Shx + Tx; //y = tmp * Shy + y * Sy + Ty; double[] pathCoodinates = path.Coordinates; for (int cooridnateIndex = 0; cooridnateIndex < path.CoordinateCount; cooridnateIndex += 2) { Coordinates[CoordinateCount++] = pathCoodinates[cooridnateIndex] * sx + pathCoodinates[cooridnateIndex + 1] * shx + tx; Coordinates[CoordinateCount++] = pathCoodinates[cooridnateIndex] * shy + pathCoodinates[cooridnateIndex + 1] * sy + ty; } }
/// <summary> /// Append a path to current path /// </summary> /// <param name="path">The source path to copy from</param> public void AddPath(DrawingPath path) { // using array .copy only ReserveSpace(path.CommandCount, path.CoordinateCount); // change private fields currentFirstCommandIndex = CommandCount + path.currentFirstCommandIndex; currentFirstCoordinateIndex = CoordinateCount + path.currentFirstCoordinateIndex; currentFirstX = path.currentFirstX; currentFirstY = path.currentFirstY; // copy command Array.Copy(path.Commands, 0, Commands, CommandCount, path.CommandCount); CommandCount += path.CommandCount; // copy coordinates Array.Copy(path.Coordinates, 0, Coordinates, CoordinateCount, path.CoordinateCount); CoordinateCount += path.CoordinateCount; }