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; }
/// <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); }
/// <summary> /// Create lineto path /// </summary> public void LineTo(Point point, bool isStroked, bool isSmoothJoin) { var lineTo = new GraphicLineSegment { To = point }; currentPath.Segments.Add(lineTo); }
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); }
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; }
public override void Execute(EpsInterpreter interpreter) { var operandStack = interpreter.OperandStack; var y = operandStack.PopRealValue(); var x = operandStack.PopRealValue(); GraphicsState graphicState = interpreter.GraphicState; var ctm = graphicState.CurrentTransformationMatrix; var point = MatrixUtilities.TransformPoint(x, y, ctm); var lineTo = new GraphicLineSegment { To = point }; graphicState.CurrentGeometry.Segments.Add(lineTo); graphicState.CurrentPoint = new Point(x, y); }
/// <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; } } }
/// <summary> /// Convert an arc definition to a series of bezier segments. /// Don't set the start point so that the arc can be part /// of a bigger segment list (path). /// </summary> public static List <GraphicPathSegment> ArcToPathSegments(Point startPoint, Point endPoint, Size size, double rotationAngle, bool isLargeArc, bool sweepDirection) { double radiusX = size.Width; double radiusY = size.Height; // start point double x1 = startPoint.X; double y1 = startPoint.Y; // end point double x2 = endPoint.X; double y2 = endPoint.Y; double dx = x1 - x2; double dy = y1 - y2; double d = Diagonal(dx, dy); if (d < Epsilon || radiusX < Epsilon || radiusY < Epsilon) { // The arc degenerates to a line var lineSegments = new List <GraphicPathSegment>(); var line = new GraphicLineSegment(); line.To = endPoint; lineSegments.Add(line); return(lineSegments); } // x rotation angle double rotationAngleRad = rotationAngle / 180.0 * Math.PI; double sinRotationAngle = Math.Sin(rotationAngleRad); double cosRotationAngle = Math.Cos(rotationAngleRad); // Convert to center point parameterization. // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes // 1) Compute x1', y1' double x1p = cosRotationAngle * dx / 2.0 + sinRotationAngle * dy / 2.0; double y1p = -sinRotationAngle * dx / 2.0 + cosRotationAngle * dy / 2.0; d = Sqr(x1p) / Sqr(radiusX) + Sqr(y1p) / Sqr(radiusY); if (d > 1) { d = Math.Sqrt(d); radiusX *= d; radiusY *= d; } // 2) Compute cx', cy' double s = 0.0; double sa = Sqr(radiusX) * Sqr(radiusY) - Sqr(radiusX) * Sqr(y1p) - Sqr(radiusY) * Sqr(x1p); double sb = Sqr(radiusX) * Sqr(y1p) + Sqr(radiusY) * Sqr(x1p); if (sa < 0.0) { sa = 0.0; } if (sb > 0.0) { s = Math.Sqrt(sa / sb); } if (isLargeArc == sweepDirection) { s = -s; } double cxp = s * radiusX * y1p / radiusY; double cyp = s * -radiusY * x1p / radiusX; // 3) Compute cx,cy from cx',cy' double cx = (x1 + x2) / 2.0 + cosRotationAngle * cxp - sinRotationAngle * cyp; double cy = (y1 + y2) / 2.0 + sinRotationAngle * cxp + cosRotationAngle * cyp; // 4) Calculate theta1, and delta theta. double ux = (x1p - cxp) / radiusX; double uy = (y1p - cyp) / radiusY; double vx = (-x1p - cxp) / radiusX; double vy = (-y1p - cyp) / radiusY; double initialAngle = VectorAngle(1.0, 0.0, ux, uy); double deltaAngle = VectorAngle(ux, uy, vx, vy); if (!sweepDirection && deltaAngle > 0) { deltaAngle -= 2 * Math.PI; } else if (sweepDirection && deltaAngle < 0) { deltaAngle += 2 * Math.PI; } Matrix matrix = new Matrix(cosRotationAngle, sinRotationAngle, -sinRotationAngle, cosRotationAngle, cx, cy); var(anglePerSegment, kappa, numberSegments) = GetSegmentData(deltaAngle); if (deltaAngle < 0.0) { kappa = -kappa; } var(segments, _, _) = CreateSegments(initialAngle, radiusX, radiusY, numberSegments, anglePerSegment, kappa, matrix); return(segments); }
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); }