/// <summary> /// Parse polyline /// </summary> private static GraphicPathGeometry ParsePolyline(XElement path) { XAttribute dAttr = path.Attribute("points"); GraphicPathGeometry geometry = new GraphicPathGeometry(); var pointParser = new DoubleListParser(); var points = pointParser.ParsePointList(dAttr.Value); if (points.Count > 1) { var move = new GraphicMoveSegment { StartPoint = points[0] }; geometry.Segments.Add(move); move.IsClosed = false; for (int i = 1; i < points.Count; i++) { var lineTo = new GraphicLineSegment { To = points[i] }; geometry.Segments.Add(lineTo); } } return(geometry); }
public override void Execute(EpsInterpreter interpreter) { var operandStack = interpreter.OperandStack; var y = operandStack.PopRealValue(); var x = operandStack.PopRealValue(); GraphicsState graphicState = interpreter.GraphicState; if (graphicState.CurrentGeometry == null) { graphicState.CurrentGeometry = new GraphicPathGeometry(); } var point = MatrixUtilities.TransformPoint(x, y, graphicState.CurrentTransformationMatrix); var move = new GraphicMoveSegment { StartPoint = point }; graphicState.CurrentGeometry.Segments.Add(move); graphicState.LastMove = move; graphicState.CurrentPoint = new Point(x, y); }
private void AddRectangle(GraphicPathGeometry geometry, double x, double y, double width, double height, Matrix ctm) { var point1 = MatrixUtilities.TransformPoint(x, y, ctm); var point2 = MatrixUtilities.TransformPoint(x + width, y + height, ctm); var move = new GraphicMoveSegment { StartPoint = point1 }; geometry.Segments.Add(move); var lineTo = new GraphicLineSegment { To = new Point(point2.X, point1.Y) }; geometry.Segments.Add(lineTo); lineTo = new GraphicLineSegment { To = new Point(point2.X, point2.Y) }; geometry.Segments.Add(lineTo); lineTo = new GraphicLineSegment { To = new Point(point1.X, point2.Y) }; geometry.Segments.Add(lineTo); move.IsClosed = true; }
private List <GraphicPathSegment> TransformSegments(List <GraphicPathSegment> segments) { var transformedSegments = new List <GraphicPathSegment>(); foreach (var segment in segments) { switch (segment) { case GraphicMoveSegment graphicMove: { var normalizedMove = new GraphicMoveSegment(); transformedSegments.Add(normalizedMove); normalizedMove.StartPoint = MatrixUtilities.TransformPoint(graphicMove.StartPoint, transformMatrix); normalizedMove.IsClosed = graphicMove.IsClosed; break; } case GraphicLineSegment graphicLineTo: { var normalizedLineTo = new GraphicLineSegment(); transformedSegments.Add(normalizedLineTo); normalizedLineTo.To = MatrixUtilities.TransformPoint(graphicLineTo.To, transformMatrix); break; } case GraphicCubicBezierSegment graphicCubicBezier: { var normalizedCubicBezier = new GraphicCubicBezierSegment(); transformedSegments.Add(normalizedCubicBezier); normalizedCubicBezier.ControlPoint1 = MatrixUtilities.TransformPoint(graphicCubicBezier.ControlPoint1, transformMatrix); normalizedCubicBezier.ControlPoint2 = MatrixUtilities.TransformPoint(graphicCubicBezier.ControlPoint2, transformMatrix); normalizedCubicBezier.EndPoint = MatrixUtilities.TransformPoint(graphicCubicBezier.EndPoint, transformMatrix); break; } case GraphicQuadraticBezierSegment graphicQuadraticBezier: { var normalizedQuadraticBezier = new GraphicQuadraticBezierSegment(); transformedSegments.Add(normalizedQuadraticBezier); normalizedQuadraticBezier.ControlPoint = MatrixUtilities.TransformPoint(graphicQuadraticBezier.ControlPoint, transformMatrix); normalizedQuadraticBezier.EndPoint = MatrixUtilities.TransformPoint(graphicQuadraticBezier.EndPoint, transformMatrix); break; } default: break; } } return(transformedSegments); }
/// <summary> /// Normalizes the specified graphic path. /// </summary> private GraphicPathGeometry NormalizeGeometry(GraphicPathGeometry graphicPathGeometry) { GraphicPathGeometry normalizedGeometry = new GraphicPathGeometry(); normalizedGeometry.FillRule = graphicPathGeometry.FillRule; foreach (var pathElement in graphicPathGeometry.Segments) { switch (pathElement) { case GraphicMoveSegment graphicMove: { var normalizedMove = new GraphicMoveSegment(); normalizedGeometry.Segments.Add(normalizedMove); normalizedMove.StartPoint = NormalizePoint(graphicMove.StartPoint); normalizedMove.IsClosed = graphicMove.IsClosed; break; } case GraphicLineSegment graphicLineTo: { var normalizedLineTo = new GraphicLineSegment(); normalizedGeometry.Segments.Add(normalizedLineTo); normalizedLineTo.To = NormalizePoint(graphicLineTo.To); break; } case GraphicCubicBezierSegment graphicCubicBezier: { var normalizedCubicBezier = new GraphicCubicBezierSegment(); normalizedGeometry.Segments.Add(normalizedCubicBezier); normalizedCubicBezier.ControlPoint1 = NormalizePoint(graphicCubicBezier.ControlPoint1); normalizedCubicBezier.ControlPoint2 = NormalizePoint(graphicCubicBezier.ControlPoint2); normalizedCubicBezier.EndPoint = NormalizePoint(graphicCubicBezier.EndPoint); break; } case GraphicQuadraticBezierSegment graphicQuadraticBezier: { var normalizedQuadraticBezier = new GraphicQuadraticBezierSegment(); normalizedGeometry.Segments.Add(normalizedQuadraticBezier); normalizedQuadraticBezier.ControlPoint = NormalizePoint(graphicQuadraticBezier.ControlPoint); normalizedQuadraticBezier.EndPoint = NormalizePoint(graphicQuadraticBezier.EndPoint); break; } } } return(normalizedGeometry); }
/// <summary> /// Create an ellipse path with absolute points from the definition with /// relative values (radius) /// </summary> public static GraphicPathGeometry EllipseToGeometry(Point center, double radiusX, double radiusY) { Point[] points = new Point[pointCount]; radiusX = Math.Abs(radiusX); radiusY = Math.Abs(radiusY); // Set the X coordinates double mid = radiusX * arcAsBezier; points[0].X = points[1].X = points[11].X = points[12].X = center.X + radiusX; points[2].X = points[10].X = center.X + mid; points[3].X = points[9].X = center.X; points[4].X = points[8].X = center.X - mid; points[5].X = points[6].X = points[7].X = center.X - radiusX; // Set the Y coordinates mid = radiusY * arcAsBezier; points[2].Y = points[3].Y = points[4].Y = center.Y + radiusY; points[1].Y = points[5].Y = center.Y + mid; points[0].Y = points[6].Y = points[12].Y = center.Y; points[7].Y = points[11].Y = center.Y - mid; points[8].Y = points[9].Y = points[10].Y = center.Y - radiusY; var geometry = new GraphicPathGeometry(); var move = new GraphicMoveSegment { StartPoint = points[0] }; move.IsClosed = true; geometry.Segments.Add(move); // i == 0, 3, 6, 9 for (int i = 0; i < 12; i += 3) { var bezier = new GraphicCubicBezierSegment(); geometry.Segments.Add(bezier); bezier.ControlPoint1 = points[i + 1]; bezier.ControlPoint2 = points[i + 2]; bezier.EndPoint = points[i + 3]; } return(geometry); }
public static void CreateArc(EpsInterpreter interpreter, bool sweepDirection) { var operandStack = interpreter.OperandStack; GraphicsState graphicState = interpreter.GraphicState; var angle2 = operandStack.PopRealValue(); var angle1 = operandStack.PopRealValue(); var r = operandStack.PopRealValue(); var y = operandStack.PopRealValue(); var x = operandStack.PopRealValue(); // be aware the segment converter returns coordinates in user space var(segments, startPoint, currentPoint) = ArcToPathSegmentConverter.ArcToPathSegments(new Point(x, y), r, angle1, angle2, sweepDirection); if (graphicState.CurrentGeometry == null) { graphicState.CurrentGeometry = new GraphicPathGeometry(); var point = MatrixUtilities.TransformPoint(startPoint, graphicState.CurrentTransformationMatrix); var move = new GraphicMoveSegment { StartPoint = point }; graphicState.CurrentGeometry.Segments.Add(move); graphicState.LastMove = move; } else { var point = MatrixUtilities.TransformPoint(startPoint, graphicState.CurrentTransformationMatrix); var lineSegment = new GraphicLineSegment { To = point }; graphicState.CurrentGeometry.Segments.Add(lineSegment); } var transformVisual = new TransformVisual(); var transformedSegments = transformVisual.TransformSegments(segments, graphicState.CurrentTransformationMatrix); graphicState.CurrentGeometry.Segments.AddRange(transformedSegments); graphicState.CurrentPoint = currentPoint; }
/// <summary> /// Start a new figure /// </summary> public void BeginFigure(Point startPoint, bool isFilled, bool isClosed) { // 2 Moves in a row don't make sense -> remove the first var num = currentPath.Segments.Count; if (num > 0) { if (currentPath.Segments[num - 1] is GraphicMoveSegment) { currentPath.Segments.RemoveAt(num - 1); } } var move = new GraphicMoveSegment { StartPoint = startPoint }; currentPath.Segments.Add(move); lastMove = move; }
/// <summary> /// Parse a line /// </summary> private static GraphicPathGeometry ParseLine(XElement path) { var x1 = GetDoubleAttr(path, "x1"); var y1 = GetDoubleAttr(path, "y1"); var x2 = GetDoubleAttr(path, "x2"); var y2 = GetDoubleAttr(path, "y2"); GraphicPathGeometry geometry = new GraphicPathGeometry(); var move = new GraphicMoveSegment { StartPoint = new Point(x1, y1) }; move.IsClosed = false; geometry.Segments.Add(move); var lineTo = new GraphicLineSegment { To = new Point(x2, y2) }; geometry.Segments.Add(lineTo); return(geometry); }
/// <summary> /// Parse a line /// </summary> private GraphicPathGeometry ParseLine(XElement path) { var x1 = GetLengthPercentAttr(path, "x1", PercentBaseSelector.ViewBoxWidth); var y1 = GetLengthPercentAttr(path, "y1", PercentBaseSelector.ViewBoxHeight); var x2 = GetLengthPercentAttr(path, "x2", PercentBaseSelector.ViewBoxWidth); var y2 = GetLengthPercentAttr(path, "y2", PercentBaseSelector.ViewBoxHeight); GraphicPathGeometry geometry = new GraphicPathGeometry(); var move = new GraphicMoveSegment { StartPoint = new Point(x1, y1) }; move.IsClosed = false; geometry.Segments.Add(move); var lineTo = new GraphicLineSegment { To = new Point(x2, y2) }; geometry.Segments.Add(lineTo); return(geometry); }
/// <summary> /// Convert a geometry to graphic geometry /// </summary> private static void ConvertToGraphicGeometry(GraphicPathGeometry graphicPathGeometry, Geometry geometry, Matrix fontTransformation) { switch (geometry) { case GeometryGroup group: { foreach (var child in group.Children) { ConvertToGraphicGeometry(graphicPathGeometry, child, fontTransformation); } break; } case PathGeometry path: { foreach (var figure in path.Figures) { var points = TransformPoint(figure.StartPoint, fontTransformation); var move = new GraphicMoveSegment { StartPoint = points }; move.IsClosed = figure.IsClosed; graphicPathGeometry.Segments.Add(move); foreach (var segment in figure.Segments) { switch (segment) { case LineSegment line: { var point = TransformPoint(line.Point, fontTransformation); var lineTo = new GraphicLineSegment { To = point }; graphicPathGeometry.Segments.Add(lineTo); break; } case BezierSegment bezier: { var gbezier = new GraphicCubicBezierSegment(); graphicPathGeometry.Segments.Add(gbezier); gbezier.ControlPoint1 = TransformPoint(bezier.Point1, fontTransformation); gbezier.ControlPoint2 = TransformPoint(bezier.Point2, fontTransformation); gbezier.EndPoint = TransformPoint(bezier.Point3, fontTransformation); break; } case PolyLineSegment polyLine: { foreach (var point in polyLine.Points) { var gpoint = TransformPoint(point, fontTransformation); var lineTo = new GraphicLineSegment { To = gpoint }; graphicPathGeometry.Segments.Add(lineTo); } break; } case PolyBezierSegment polyBezier: { for (int i = 0; i < polyBezier.Points.Count; i += 3) { var gbezier = new GraphicCubicBezierSegment(); graphicPathGeometry.Segments.Add(gbezier); gbezier.ControlPoint1 = TransformPoint(polyBezier.Points[i], fontTransformation); gbezier.ControlPoint2 = TransformPoint(polyBezier.Points[i + 1], fontTransformation); gbezier.EndPoint = TransformPoint(polyBezier.Points[i + 2], fontTransformation); } break; } } } } break; } } }
/// <summary> /// Convert a geometry to graphic paths /// </summary> void ConvertToGraphicPath(List <GraphicPath> pdfGraphicsPaths, Geometry geometry) { GraphicPath currentPath = null; switch (geometry) { case GeometryGroup group: { foreach (var child in group.Children) { ConvertToGraphicPath(pdfGraphicsPaths, child); } break; } case CombinedGeometry combined: { break; } case EllipseGeometry ellipse: { break; } case LineGeometry line: { break; } case RectangleGeometry rectangle: { break; } case System.Windows.Media.StreamGeometry stream: { break; } case PathGeometry path: { foreach (var figure in path.Figures) { if (currentPath == null) { currentPath = new GraphicPath(); switch (fontState.RenderingMode) { case FontRenderingMode.Fill: currentPath.FillBrush = currentGraphicsState.FillBrush.GetBrush(null, null); break; case FontRenderingMode.Stroke: currentPath.StrokeBrush = currentGraphicsState.StrokeBrush.GetBrush(null, null); currentPath.StrokeThickness = currentGraphicsState.LineWidth; break; case FontRenderingMode.FillAndStroke: currentPath.FillBrush = currentGraphicsState.FillBrush.GetBrush(null, null); currentPath.StrokeBrush = currentGraphicsState.StrokeBrush.GetBrush(null, null); currentPath.StrokeThickness = currentGraphicsState.LineWidth; break; } pdfGraphicsPaths.Add(currentPath); } var xs = figure.StartPoint.X; var ys = figure.StartPoint.Y; var points = TransformPoint(xs, ys); var move = new GraphicMoveSegment { StartPoint = points }; move.IsClosed = figure.IsClosed; currentPath.Geometry.Segments.Add(move); foreach (var segment in figure.Segments) { switch (segment) { case LineSegment line: { var x = line.Point.X; var y = line.Point.Y; var point = TransformPoint(x, y); var lineTo = new GraphicLineSegment { To = point }; currentPath.Geometry.Segments.Add(lineTo); break; } case BezierSegment bezier: { var gbezier = new GraphicCubicBezierSegment(); currentPath.Geometry.Segments.Add(gbezier); var x = bezier.Point1.X; var y = bezier.Point1.Y; gbezier.ControlPoint1 = TransformPoint(x, y); x = bezier.Point2.X; y = bezier.Point2.Y; gbezier.ControlPoint2 = TransformPoint(x, y); x = bezier.Point3.X; y = bezier.Point3.Y; gbezier.EndPoint = TransformPoint(x, y); break; } case ArcSegment arc: break; case PolyLineSegment polyLine: { foreach (var point in polyLine.Points) { var x = point.X; var y = point.Y; var gpoint = TransformPoint(x, y); var lineTo = new GraphicLineSegment { To = gpoint }; currentPath.Geometry.Segments.Add(lineTo); } break; } case PolyBezierSegment polyBezier: { for (int i = 0; i < polyBezier.Points.Count; i += 3) { var gbezier = new GraphicCubicBezierSegment(); currentPath.Geometry.Segments.Add(gbezier); var x = polyBezier.Points[i].X; var y = polyBezier.Points[i].Y; gbezier.ControlPoint1 = TransformPoint(x, y); x = polyBezier.Points[i + 1].X; y = polyBezier.Points[i + 1].Y; gbezier.ControlPoint2 = TransformPoint(x, y); x = polyBezier.Points[i + 2].X; y = polyBezier.Points[i + 2].Y; gbezier.EndPoint = TransformPoint(x, y); } break; } case PolyQuadraticBezierSegment polyQuadratic: break; case QuadraticBezierSegment quadraticBezier: break; default: break; } } } break; } } }
private const double arcAsBezier = 0.5522847498307933984; // =( \/2 - 1)*4/3 /// <summary> /// Create a rectangle with absolute points from the rectangle /// definition with relative values (width, height) /// </summary> public static GraphicPathGeometry RectToGeometry(Rect rect, double radiusX, double radiusY) { GraphicPathGeometry geometry = new GraphicPathGeometry(); if (!DoubleUtilities.IsZero(radiusX) && !DoubleUtilities.IsZero(radiusY)) { var points = GetRectPointList(rect, radiusX, radiusY); var move = new GraphicMoveSegment { StartPoint = points[0] }; move.IsClosed = true; geometry.Segments.Add(move); var bezier = new GraphicCubicBezierSegment(); geometry.Segments.Add(bezier); bezier.ControlPoint1 = points[1]; bezier.ControlPoint2 = points[2]; bezier.EndPoint = points[3]; var lineTo = new GraphicLineSegment { To = points[4] }; geometry.Segments.Add(lineTo); bezier = new GraphicCubicBezierSegment(); geometry.Segments.Add(bezier); bezier.ControlPoint1 = points[5]; bezier.ControlPoint2 = points[6]; bezier.EndPoint = points[7]; lineTo = new GraphicLineSegment { To = points[8] }; geometry.Segments.Add(lineTo); bezier = new GraphicCubicBezierSegment(); geometry.Segments.Add(bezier); bezier.ControlPoint1 = points[9]; bezier.ControlPoint2 = points[10]; bezier.EndPoint = points[11]; lineTo = new GraphicLineSegment { To = points[12] }; geometry.Segments.Add(lineTo); bezier = new GraphicCubicBezierSegment(); geometry.Segments.Add(bezier); bezier.ControlPoint1 = points[13]; bezier.ControlPoint2 = points[14]; bezier.EndPoint = points[15]; } else { var points = GetRectPointList(rect); var move = new GraphicMoveSegment { StartPoint = points[0] }; move.IsClosed = true; geometry.Segments.Add(move); var lineTo = new GraphicLineSegment { To = points[1] }; geometry.Segments.Add(lineTo); lineTo = new GraphicLineSegment { To = points[2] }; geometry.Segments.Add(lineTo); lineTo = new GraphicLineSegment { To = points[3] }; geometry.Segments.Add(lineTo); } return(geometry); }
/// <summary> /// Parse a single PDF page /// </summary> public GraphicGroup Run(PdfDictionary form, CSequence sequence, GraphicsState graphicsState) { this.returnGraphicGroup = new GraphicGroup(); graphicGroup = returnGraphicGroup; graphicsStateStack = new Stack <GraphicsState>(); fontState = new FontState(); textVectorizer = new TextVectorizer(); currentGraphicsState = graphicsState; Init(form); InitColor(); Point currentPoint = new Point(0, 0); GraphicMoveSegment lastMove = null; ResetCurrentGeometry(); for (int index = 0; index < sequence.Count; index++) { var contentOperator = sequence[index] as COperator; switch (contentOperator.OpCode.OpCodeName) { // path construction operators // rectangle case OpCodeName.re: { if (currentGeometry == null) { currentGeometry = new GraphicPathGeometry(); } var x = PdfUtilities.GetDouble(contentOperator.Operands[0]); var y = PdfUtilities.GetDouble(contentOperator.Operands[1]); var width = PdfUtilities.GetDouble(contentOperator.Operands[2]); var height = PdfUtilities.GetDouble(contentOperator.Operands[3]); var point1 = MatrixUtilities.TransformPoint(x, y, currentGraphicsState.CurrentTransformationMatrix); var point2 = MatrixUtilities.TransformPoint(x + width, y + height, currentGraphicsState.CurrentTransformationMatrix); var move = new GraphicMoveSegment { StartPoint = point1 }; currentGeometry.Segments.Add(move); var lineTo = new GraphicLineSegment { To = new Point(point2.X, point1.Y) }; currentGeometry.Segments.Add(lineTo); lineTo = new GraphicLineSegment { To = new Point(point2.X, point2.Y) }; currentGeometry.Segments.Add(lineTo); lineTo = new GraphicLineSegment { To = new Point(point1.X, point2.Y) }; currentGeometry.Segments.Add(lineTo); move.IsClosed = true; lastMove = move; currentPoint = point1; break; } // move to case OpCodeName.m: { if (currentGeometry == null) { currentGeometry = new GraphicPathGeometry(); } var x = PdfUtilities.GetDouble(contentOperator.Operands[0]); var y = PdfUtilities.GetDouble(contentOperator.Operands[1]); var point = MatrixUtilities.TransformPoint(x, y, currentGraphicsState.CurrentTransformationMatrix); var move = new GraphicMoveSegment { StartPoint = point }; currentGeometry.Segments.Add(move); lastMove = move; currentPoint = point; break; } // line to case OpCodeName.l: { var x = PdfUtilities.GetDouble(contentOperator.Operands[0]); var y = PdfUtilities.GetDouble(contentOperator.Operands[1]); var point = MatrixUtilities.TransformPoint(x, y, currentGraphicsState.CurrentTransformationMatrix); var lineTo = new GraphicLineSegment { To = point }; currentGeometry.Segments.Add(lineTo); currentPoint = point; break; } // cubic bezier case OpCodeName.c: { var bezier = new GraphicCubicBezierSegment(); currentGeometry.Segments.Add(bezier); var x = PdfUtilities.GetDouble(contentOperator.Operands[0]); var y = PdfUtilities.GetDouble(contentOperator.Operands[1]); bezier.ControlPoint1 = MatrixUtilities.TransformPoint(x, y, currentGraphicsState.CurrentTransformationMatrix); x = PdfUtilities.GetDouble(contentOperator.Operands[2]); y = PdfUtilities.GetDouble(contentOperator.Operands[3]); bezier.ControlPoint2 = MatrixUtilities.TransformPoint(x, y, currentGraphicsState.CurrentTransformationMatrix); x = PdfUtilities.GetDouble(contentOperator.Operands[4]); y = PdfUtilities.GetDouble(contentOperator.Operands[5]); bezier.EndPoint = MatrixUtilities.TransformPoint(x, y, currentGraphicsState.CurrentTransformationMatrix); currentPoint = bezier.EndPoint; break; } // quadratic bezier case OpCodeName.v: { var bezier = new GraphicCubicBezierSegment(); currentGeometry.Segments.Add(bezier); bezier.ControlPoint1 = currentPoint; var x = PdfUtilities.GetDouble(contentOperator.Operands[0]); var y = PdfUtilities.GetDouble(contentOperator.Operands[1]); bezier.ControlPoint2 = MatrixUtilities.TransformPoint(x, y, currentGraphicsState.CurrentTransformationMatrix); x = PdfUtilities.GetDouble(contentOperator.Operands[2]); y = PdfUtilities.GetDouble(contentOperator.Operands[3]); bezier.EndPoint = MatrixUtilities.TransformPoint(x, y, currentGraphicsState.CurrentTransformationMatrix); currentPoint = bezier.EndPoint; break; } // quadratic bezier case OpCodeName.y: { var bezier = new GraphicCubicBezierSegment(); currentGeometry.Segments.Add(bezier); var x = PdfUtilities.GetDouble(contentOperator.Operands[0]); var y = PdfUtilities.GetDouble(contentOperator.Operands[1]); bezier.ControlPoint1 = MatrixUtilities.TransformPoint(x, y, currentGraphicsState.CurrentTransformationMatrix); x = PdfUtilities.GetDouble(contentOperator.Operands[2]); y = PdfUtilities.GetDouble(contentOperator.Operands[3]); bezier.ControlPoint2 = MatrixUtilities.TransformPoint(x, y, currentGraphicsState.CurrentTransformationMatrix); bezier.EndPoint = bezier.ControlPoint2; currentPoint = bezier.EndPoint; break; } // path painting operators // end the path without filling and stroking case OpCodeName.n: { ResetCurrentGeometry(); break; } // set clipping path case OpCodeName.W: case OpCodeName.Wx: { currentGraphicsState.ClippingPath = currentGeometry; graphicGroup = new GraphicGroup(); graphicGroup.Clip = currentGeometry; returnGraphicGroup.Children.Add(graphicGroup); break; } // close path case OpCodeName.h: lastMove.IsClosed = true; break; // close and fill the path case OpCodeName.s: { lastMove.IsClosed = true; var path = GetCurrentPathFilled(); graphicGroup.Children.Add(path); ResetCurrentGeometry(); break; } // stroke the path case OpCodeName.S: { var path = GetCurrentPathStroked(); graphicGroup.Children.Add(path); ResetCurrentGeometry(); break; } // close, fill and stroke the path case OpCodeName.b: case OpCodeName.bx: { lastMove.IsClosed = true; var path = GetCurrentPathFilledAndStroked(); graphicGroup.Children.Add(path); ResetCurrentGeometry(); break; } // fill and stroke the path case OpCodeName.B: { var path = GetCurrentPathFilledAndStroked(); currentGeometry.FillRule = GraphicFillRule.NoneZero; graphicGroup.Children.Add(path); ResetCurrentGeometry(); break; } // fill and stroke the path case OpCodeName.Bx: { var path = GetCurrentPathFilledAndStroked(); currentGeometry.FillRule = GraphicFillRule.NoneZero; currentGeometry.FillRule = GraphicFillRule.EvenOdd; graphicGroup.Children.Add(path); ResetCurrentGeometry(); break; } // fill the path case OpCodeName.F: case OpCodeName.f: { var path = GetCurrentPathFilled(); currentGeometry.FillRule = GraphicFillRule.NoneZero; graphicGroup.Children.Add(path); ResetCurrentGeometry(); break; } // fill the path case OpCodeName.fx: { var path = GetCurrentPathFilled(); currentGeometry.FillRule = GraphicFillRule.EvenOdd; graphicGroup.Children.Add(path); ResetCurrentGeometry(); break; } // set color space for stroking operations case OpCodeName.CS: { var colorSpaceName = ((CName)contentOperator.Operands[0]).Name; currentGraphicsState.StrokeColorSpace = colorSpaceManager.GetColorSpace(colorSpaceName); break; } // set color space for nonstroking operations case OpCodeName.cs: { var colorSpaceName = ((CName)contentOperator.Operands[0]).Name; currentGraphicsState.ColorSpace = colorSpaceManager.GetColorSpace(colorSpaceName); break; } // set /DeviceRGB and non-stroked color case OpCodeName.rg: { currentGraphicsState.ColorSpace = colorSpaceManager.GetColorSpace(PdfKeys.DeviceRGB); currentGraphicsState.FillBrush = currentGraphicsState.ColorSpace.GetBrushDescriptor(contentOperator.Operands, currentGraphicsState.CurrentTransformationMatrix, currentGraphicsState.FillAlpha.Current); break; } // set /DeviceCMYK and non-stroked color case OpCodeName.k: { currentGraphicsState.ColorSpace = colorSpaceManager.GetColorSpace(PdfKeys.DeviceCMYK); currentGraphicsState.FillBrush = currentGraphicsState.ColorSpace.GetBrushDescriptor(contentOperator.Operands, currentGraphicsState.CurrentTransformationMatrix, currentGraphicsState.FillAlpha.Current); break; } // set /DeviceGray and non-stroked color case OpCodeName.g: { currentGraphicsState.ColorSpace = colorSpaceManager.GetColorSpace(PdfKeys.DeviceGray); currentGraphicsState.FillBrush = currentGraphicsState.ColorSpace.GetBrushDescriptor(contentOperator.Operands, currentGraphicsState.CurrentTransformationMatrix, currentGraphicsState.FillAlpha.Current); break; } // non-stroked color case OpCodeName.sc: { currentGraphicsState.FillBrush = currentGraphicsState.ColorSpace.GetBrushDescriptor(contentOperator.Operands, currentGraphicsState.CurrentTransformationMatrix, currentGraphicsState.FillAlpha.Current); break; } // ICC based non-stroked color case OpCodeName.scn: { currentGraphicsState.FillBrush = currentGraphicsState.ColorSpace.GetBrushDescriptor(contentOperator.Operands, currentGraphicsState.CurrentTransformationMatrix, currentGraphicsState.FillAlpha.Current); break; } // ICC based stroked color case OpCodeName.SCN: { currentGraphicsState.StrokeBrush = currentGraphicsState.StrokeColorSpace.GetBrushDescriptor(contentOperator.Operands, currentGraphicsState.CurrentTransformationMatrix, currentGraphicsState.StrokeAlpha.Current); break; } // set /DeviceRGB and stroked color case OpCodeName.RG: { currentGraphicsState.StrokeColorSpace = colorSpaceManager.GetColorSpace(PdfKeys.DeviceRGB); currentGraphicsState.StrokeBrush = currentGraphicsState.StrokeColorSpace.GetBrushDescriptor(contentOperator.Operands, currentGraphicsState.CurrentTransformationMatrix, currentGraphicsState.StrokeAlpha.Current); break; } // set /DeviceGray and stroked color case OpCodeName.G: { currentGraphicsState.StrokeColorSpace = colorSpaceManager.GetColorSpace(PdfKeys.DeviceGray); currentGraphicsState.StrokeBrush = currentGraphicsState.StrokeColorSpace.GetBrushDescriptor(contentOperator.Operands, currentGraphicsState.CurrentTransformationMatrix, currentGraphicsState.StrokeAlpha.Current); break; } // set /DeviceCMYK and stroked color case OpCodeName.K: { currentGraphicsState.StrokeColorSpace = colorSpaceManager.GetColorSpace(PdfKeys.DeviceCMYK); currentGraphicsState.StrokeBrush = currentGraphicsState.StrokeColorSpace.GetBrushDescriptor(contentOperator.Operands, currentGraphicsState.CurrentTransformationMatrix, currentGraphicsState.StrokeAlpha.Current); break; } // set stroked color case OpCodeName.SC: { currentGraphicsState.StrokeBrush = currentGraphicsState.StrokeColorSpace.GetBrushDescriptor(contentOperator.Operands, currentGraphicsState.CurrentTransformationMatrix, currentGraphicsState.StrokeAlpha.Current); break; } // shading case OpCodeName.sh: { var graphicPath = new GraphicPath(); var shadingDescriptor = shadingManager.GetShading(contentOperator.Operands); graphicPath.Geometry = currentGraphicsState.ClippingPath; graphicPath.FillBrush = shadingDescriptor.GetBrush(currentGraphicsState.CurrentTransformationMatrix, currentGraphicsState.ClippingPath.Bounds, currentGraphicsState.FillAlpha.Current, currentGraphicsState.SoftMask); graphicPath.ColorPrecision = shadingDescriptor.ColorPrecision; graphicGroup.Children.Add(graphicPath); break; } // begin text case OpCodeName.BT: { fontState.TextLineMatrix = Matrix.Identity; fontState.TextMatrix = Matrix.Identity; break; } // set current font case OpCodeName.Tf: { var fontName = ((CName)contentOperator.Operands[0]).Name; fontState.FontSize = PdfUtilities.GetDouble(contentOperator.Operands[1]); fontState.FontDescriptor = fontManager.GetFont(fontName); break; } // set rendering mode case OpCodeName.Tr: { fontState.RenderingMode = PdfUtilities.GetRenderingMode(contentOperator.Operands[0]); break; } // set font transformation matrix case OpCodeName.Tm: { var matrix = PdfUtilities.GetMatrix(contentOperator.Operands); fontState.TextMatrix = matrix; fontState.TextLineMatrix = matrix; break; } // translate line matrix case OpCodeName.Td: { var x = PdfUtilities.GetDouble(contentOperator.Operands[0]); var y = PdfUtilities.GetDouble(contentOperator.Operands[1]); // for some unknown reason the simple next statement doesn't // work, do it in small steps instead //fontState.TextLineMatrix.TranslatePrepend(x, y); var m = fontState.TextLineMatrix; m.TranslatePrepend(x, y); fontState.TextLineMatrix = m; fontState.TextMatrix = fontState.TextLineMatrix; break; } case OpCodeName.TD: { var x = PdfUtilities.GetDouble(contentOperator.Operands[0]); var y = PdfUtilities.GetDouble(contentOperator.Operands[1]); //fontState.TextLineMatrix.Translate(x, y); var m = fontState.TextLineMatrix; m.TranslatePrepend(x, y); fontState.TextLineMatrix = m; fontState.Leading = -y; fontState.TextMatrix = fontState.TextLineMatrix; break; } case OpCodeName.TL: { fontState.Leading = PdfUtilities.GetDouble(contentOperator.Operands[0]); break; } case OpCodeName.Tx: { var m = fontState.TextLineMatrix; m.TranslatePrepend(0, -fontState.Leading); fontState.TextLineMatrix = m; fontState.TextMatrix = fontState.TextLineMatrix; break; } case OpCodeName.QuoteSingle: { break; } case OpCodeName.QuoteDbl: { break; } // a single string case OpCodeName.Tj: { var text = (CString)contentOperator.Operands[0]; var textGraphic = textVectorizer.Vectorize(text.Value, currentGraphicsState, fontState); graphicGroup.Children.AddRange(textGraphic); break; } // multiple strings plus formatting case OpCodeName.TJ: { var array = (CArray)contentOperator.Operands[0]; HandleMultipleTextCommand(array); break; } // graphics state operators // push state onto the stack case OpCodeName.q: { var clone = currentGraphicsState.Clone(); graphicsStateStack.Push(clone); break; } // pop state from the stack case OpCodeName.Q: { currentGraphicsState = graphicsStateStack.Pop(); break; } // current transform matrix case OpCodeName.cm: { var matrix = PdfUtilities.GetMatrix(contentOperator.Operands); currentGraphicsState.TransformationMatrix *= matrix; break; } case OpCodeName.J: { currentGraphicsState.LineCap = GetLineCap(((CInteger)contentOperator.Operands[0]).Value); break; } case OpCodeName.j: { currentGraphicsState.LineJoin = GetLineJoin(((CInteger)contentOperator.Operands[0]).Value); break; } case OpCodeName.M: { currentGraphicsState.MiterLimit = PdfUtilities.GetDouble(contentOperator.Operands[0]); break; } case OpCodeName.d: { SetDashPattern(contentOperator.Operands); break; } // line width case OpCodeName.w: { currentGraphicsState.LineWidth = MatrixUtilities.TransformScale(PdfUtilities.GetDouble(contentOperator.Operands[0]), currentGraphicsState.CurrentTransformationMatrix); break; } // set parameters in the current graphic state of the given state name case OpCodeName.gs: { var name = contentOperator.Operands[0] as CName; extendedStatesManager.SetExtendedGraphicState(currentGraphicsState, fontState, name.Name); break; } case OpCodeName.Do: { var xObjectName = ((CName)contentOperator.Operands[0]).Name; RunXObject(xObjectName); break; } default: break; } } return(this.returnGraphicGroup); }
/// <summary> /// Convert a path made of PSD bezier records to GraphicPath objects /// </summary> private void ReadBezier(BezierDescriptor[] psdBeziers, GraphicPath graphicPath, Size size) { bool closePath = false; Point firstPoint = new Point(); Point lastControlPoint = new Point(); Point firstControlPoint = new Point(); bool isFirstKnot = false; foreach (var psdBezier in psdBeziers) { switch (psdBezier) { case BezierSubpathRecord bezierSubpathRecord: { if (closePath) { var bezier = new GraphicCubicBezierSegment(); graphicPath.Geometry.Segments.Add(bezier); bezier.ControlPoint1 = lastControlPoint; bezier.ControlPoint2 = firstControlPoint; bezier.EndPoint = firstPoint; } isFirstKnot = true; closePath = bezierSubpathRecord.IsClosed; break; } case BezierKnot bezierKnot: { if (isFirstKnot) { isFirstKnot = false; firstPoint = new Point(bezierKnot.Point2X * size.Width, bezierKnot.Point2Y * size.Height); var move = new GraphicMoveSegment { StartPoint = firstPoint }; move.IsClosed = closePath; graphicPath.Geometry.Segments.Add(move); lastControlPoint = new Point(bezierKnot.Point3X * size.Width, bezierKnot.Point3Y * size.Height); firstControlPoint = new Point(bezierKnot.Point1X * size.Width, bezierKnot.Point1Y * size.Height); } else { var bezier = new GraphicCubicBezierSegment(); graphicPath.Geometry.Segments.Add(bezier); bezier.ControlPoint1 = lastControlPoint; bezier.ControlPoint2 = new Point(bezierKnot.Point1X * size.Width, bezierKnot.Point1Y * size.Height); bezier.EndPoint = new Point(bezierKnot.Point2X * size.Width, bezierKnot.Point2Y * size.Height); lastControlPoint = new Point(bezierKnot.Point3X * size.Width, bezierKnot.Point3Y * size.Height); } break; } default: break; } } if (closePath) { var bezier = new GraphicCubicBezierSegment(); graphicPath.Geometry.Segments.Add(bezier); bezier.ControlPoint1 = lastControlPoint; bezier.ControlPoint2 = firstControlPoint; bezier.EndPoint = firstPoint; } }