/// <summary> /// Set the clipping of the group /// </summary> public static void SetClipPath(GraphicGroup group, Matrix currentTransformationMatrix, CssStyleCascade cssStyleCascade, Dictionary <string, XElement> globalDefinitions) { var clipPath = cssStyleCascade.GetPropertyFromTop("clip-path"); if (string.IsNullOrEmpty(clipPath)) { return; } if (!clipPath.StartsWith("url(", StringComparison.OrdinalIgnoreCase)) { return; } int endUri = clipPath.IndexOf(")", StringComparison.OrdinalIgnoreCase); var uri = clipPath.Substring(4, endUri - 4); uri = uri.Trim(); var id = uri.Substring(1); if (!globalDefinitions.ContainsKey(id)) { return; } var clipElem = globalDefinitions[id]; // richt now we support only a single path for the clip geometry var shapeElement = clipElem.Elements().First(); if (shapeElement == null) { return; } var clipGeometry = GeometryParser.Parse(shapeElement, currentTransformationMatrix); clipGeometry.FillRule = GraphicFillRule.NoneZero; var clipRule = cssStyleCascade.GetProperty("clip-rule"); if (!string.IsNullOrEmpty(clipRule)) { switch (clipRule) { case "evenodd": clipGeometry.FillRule = GraphicFillRule.EvenOdd; break; case "nonzero": clipGeometry.FillRule = GraphicFillRule.NoneZero; break; } } group.Clip = clipGeometry; }
public Group(Guid guid, String tag, Box box, bool visible, GraphicGroup graphicGroup) { this.guid = guid; this.tag = tag; this.box = box; this.visible = visible; this.graphicGroup = graphicGroup; }
public static void SetClip(EpsInterpreter interpreter, GraphicPathGeometry geometry) { interpreter.GraphicState.ClippingPath = geometry; var graphicGroup = new GraphicGroup(); interpreter.GraphicGroup = graphicGroup; interpreter.GraphicGroup.Clip = geometry; interpreter.ReturnGraphicGroup.Childreen.Add(graphicGroup); }
/// <summary> /// Parse all graphic elements /// </summary> private GraphicGroup ParseGroup(XNamespace ns, XElement groupElement, Matrix matrix) { var group = new GraphicGroup(); cssStyleCascade.PushStyles(groupElement); Matrix currentTransformationMatrix = matrix; var transform = cssStyleCascade.GetPropertyFromTop("transform"); if (!string.IsNullOrEmpty(transform)) { var transformMatrix = TransformMatrixParser.GetTransformMatrix(transform); currentTransformationMatrix = transformMatrix * currentTransformationMatrix; } Clipping.SetClipPath(group, currentTransformationMatrix, cssStyleCascade, globalDefinitions); group.Opacity = cssStyleCascade.GetDoubleFromTop("opacity", 1); var shapeParser = new ShapeParser(); foreach (var element in groupElement.Elements()) { switch (element.Name.LocalName) { case "defs": case "style": // already read, ignore break; case "g": case "svg": { var childGroup = ParseGroup(ns, element, currentTransformationMatrix); group.Childreen.Add(childGroup); break; } default: { var shape = shapeParser.Parse(element, ns, currentTransformationMatrix, cssStyleCascade, globalDefinitions); if (shape != null) { group.Childreen.Add(shape); } break; } } } cssStyleCascade.Pop(); return(group); }
/// <summary> /// Parse a single SVG shape /// </summary> public GraphicVisual Parse(XElement shape, XNamespace svgNamespace, Matrix currentTransformationMatrix, CssStyleCascade cssStyleCascade, Dictionary <string, XElement> globalDefinitions) { GraphicVisual graphicVisual = null; cssStyleCascade.PushStyles(shape); var transform = cssStyleCascade.GetPropertyFromTop("transform"); if (!string.IsNullOrEmpty(transform)) { var transformMatrix = TransformMatrixParser.GetTransformMatrix(transform); currentTransformationMatrix = transformMatrix * currentTransformationMatrix; } var geometry = GeometryParser.Parse(shape, currentTransformationMatrix); if (geometry != null) { var graphicPath = new GraphicPath(); graphicPath.Geometry = geometry; graphicVisual = graphicPath; this.svgNamespace = svgNamespace; this.globalDefinitions = globalDefinitions; this.currentTransformationMatrix = currentTransformationMatrix; this.cssStyleCascade = cssStyleCascade; SetFillAndStroke(shape, graphicPath); if (Clipping.IsClipPathSet(cssStyleCascade)) { // shapes don't support clipping, create a group around it var group = new GraphicGroup(); graphicVisual = group; group.Childreen.Add(graphicPath); Clipping.SetClipPath(group, currentTransformationMatrix, cssStyleCascade, globalDefinitions); } cssStyleCascade.Pop(); } return(graphicVisual); }
/// <summary> /// Parse the given file /// </summary> GraphicVisual IFileParser.Parse(string filename) { colorManager = new ColorSpaceManager(); var group = new GraphicGroup(); using (PsdDocument document = PsdDocument.Create(filename)) { Size size = new Size(document.Width, document.Height); PrepareIccProfile(document); ParseLayers(document, size, group); } CommonHelper.CleanUpTempDir(); return(group); }
/// <summary> /// Initialize all about graphic /// </summary> private void InitGraphic() { ReturnGraphicGroup = new GraphicGroup(); GraphicGroup = ReturnGraphicGroup; graphicsStateStack = new Stack <GraphicsState>(); GraphicState = new GraphicsState(); GraphicState.TransformationMatrix = Matrix.Identity; GraphicState.ColorSpace = ColorSpaceActivator.CreateColorSpace(this, EpsKeys.DeviceGray); var values = new List <Operand> { new RealOperand(0) }; // black GraphicState.FillBrush = GraphicState.ColorSpace.GetBrushDescriptor(values, GraphicState.CurrentTransformationMatrix); }
/// <summary> /// Parse the given file and convert it to a list of graphic paths /// </summary> GraphicVisual IFileParser.Parse(string filename) { var group = new GraphicGroup(); PdfDocument inputDocument = PdfReader.Open(filename); for (int i = 0; i < inputDocument.Pages.Count; i++) { var page = inputDocument.Pages[i]; var geometry = Parse(page); group.Childreen.Add(geometry); } var visual = OptimizeVisual.Optimize(group); CommonHelper.CleanUpTempDir(); return(visual); }
/// <summary> /// Parse all graphic elements /// </summary> private GraphicGroup ParseChildren(XElement groupElement, Matrix matrix) { var group = new GraphicGroup(); foreach (var element in groupElement.Elements()) { if (!PresentationAttribute.IsElementVisible(element) || !PresentationAttribute.IsElementDisplayed(element)) { continue; } GraphicVisual graphicVisual = ParseElement(element, matrix); if (graphicVisual != null) { group.Children.Add(graphicVisual); } } return(group); }
/// <summary> /// Builds the selected drawing recursively /// </summary> private GraphicVisual BuildSelectedGeometry(GraphicVisual visual, List <GraphicPath> selectedPaths) { GraphicVisual graphicVisual = null; switch (visual) { case GraphicGroup group: { var graphicGroup = new GraphicGroup(); graphicVisual = graphicGroup; graphicGroup.Opacity = group.Opacity; graphicGroup.Clip = group.Clip; foreach (var childVisual in group.Children) { var selectedGeometry = BuildSelectedGeometry(childVisual, selectedPaths); if (selectedGeometry != null) { graphicGroup.Children.Add(selectedGeometry); } } break; } case GraphicPath graphicPath: { if (selectedPaths.Contains(graphicPath)) { graphicVisual = graphicPath; } break; } } return(graphicVisual); }
/// <summary> /// The transformation engine /// </summary> /// <returns></returns> private GraphicVisual Transform(GraphicVisual visual) { GraphicVisual graphicGeometry = null; switch (visual) { case GraphicGroup group: { var graphicGroup = new GraphicGroup(); graphicGeometry = graphicGroup; graphicGroup.Opacity = group.Opacity; if (group.Clip != null) { graphicGroup.Clip = TransformGeometry(group.Clip); } foreach (var childVisual in group.Children) { var normalizedVisual = Transform(childVisual); graphicGroup.Children.Add(normalizedVisual); } break; } case GraphicPath graphicPath: { var transformedPath = new GraphicPath(); graphicGeometry = transformedPath; transformedPath.Geometry = TransformGeometry(graphicPath.Geometry); SetShapeAttributes(graphicPath, transformedPath); break; } } return(graphicGeometry); }
/// <summary> /// Parse a single SVG shape /// </summary> public GraphicVisual Parse(XElement shape, Matrix currentTransformationMatrix) { GraphicVisual graphicVisual = null; cssStyleCascade.PushStyles(shape); var transformMatrix = cssStyleCascade.GetTransformMatrixFromTop(); currentTransformationMatrix = transformMatrix * currentTransformationMatrix; var geometry = geometryParser.Parse(shape, currentTransformationMatrix); if (geometry != null) { var graphicPath = new GraphicPath(); graphicPath.Geometry = geometry; graphicVisual = graphicPath; brushParser.SetFillAndStroke(shape, graphicPath, currentTransformationMatrix); if (clipping.IsClipPathSet()) { // shapes don't support clipping, create a group around it var group = new GraphicGroup(); graphicVisual = group; group.Children.Add(graphicPath); clipping.SetClipPath(group, currentTransformationMatrix); } } cssStyleCascade.Pop(); return(graphicVisual); }
/// <summary> /// Parse all layers recursively /// </summary> void ParseLayers(IPsdLayer layer, Size size, GraphicGroup group) { if (!layer.IsVisible) { return; } if (layer.Childreen.Length > 0) { foreach (var child in layer.Childreen) { ParseLayers(child, size, group); } } else { var graphicPath = ParseLayer(layer, size); if (graphicPath != null) { group.Childreen.Add(graphicPath); } } }
/// <summary> /// Parse a text /// </summary> private GraphicVisual ParseText(XElement textElement, Matrix currentTransformationMatrix) { GraphicGroup graphicGroup = new GraphicGroup(); var colorBlocks = new List <ColorBlock>(); var positionBlocks = new List <PositionBlock>(); var position = new CharacterPositions(); var textColorBlock = new ColorBlock(); colorBlocks.Add(textColorBlock); textColorBlock.Characters = new List <PositionBlockCharacter>(); textColorBlock.AdjustFillGlobal = true; textColorBlock.AdjustStrokeGlobal = true; var xList = GetLengthPercentList(textElement, "x", PercentBaseSelector.ViewBoxWidth); if (xList == null) { xList = new List <double> { 0.0 }; } var dxList = GetLengthPercentList(textElement, "dx", PercentBaseSelector.ViewBoxWidth); position.X.SetParentValues(xList, dxList); var yList = GetLengthPercentList(textElement, "y", PercentBaseSelector.ViewBoxHeight); if (yList == null) { yList = new List <double> { 0.0 }; } var dyList = GetLengthPercentList(textElement, "dy", PercentBaseSelector.ViewBoxHeight); position.Y.SetParentValues(yList, dyList); var fontSize = GetFontSize(); var typeface = GetTypeface(); var textAnchor = GetTextAnchor(); var rotation = new ParentChildPriorityList(); rotation.ParentValues = GetRotate(textElement); var textOpacity = cssStyleCascade.GetNumberPercentFromTop("opacity", 1); var textFillOpacity = cssStyleCascade.GetNumberPercentFromTop("fill-opacity", 1); var textStrokeOpacity = cssStyleCascade.GetNumberPercentFromTop("stroke-opacity", 1); if (false && !textElement.HasElements) { var geometry = ParseTextGeometry(textElement, currentTransformationMatrix); var graphicPath = new GraphicPath(); graphicPath.Geometry = geometry; graphicPath.Geometry.FillRule = GraphicFillRule.NoneZero; brushParser.SetFillAndStroke(textElement, graphicPath, currentTransformationMatrix); return(graphicPath); } XNode node = textElement.FirstNode; bool beginOfLine = true; while (node != null) { var nextNode = node.NextNode; var hasSuccessor = nextNode != null; switch (node) { case XElement embededElement: { if (!PresentationAttribute.IsElementVisible(embededElement)) { continue; } switch (embededElement.Name.LocalName) { case "tspan": { var tspanElement = embededElement; var isTspanDisplayed = PresentationAttribute.IsElementDisplayed(tspanElement); cssStyleCascade.PushStyles(tspanElement); var xChildList = GetLengthPercentList(tspanElement, "x", PercentBaseSelector.ViewBoxWidth); var dxChildList = GetLengthPercentList(tspanElement, "dx", PercentBaseSelector.ViewBoxWidth); position.X.SetChildValues(xChildList, dxChildList); var yChildList = GetLengthPercentList(tspanElement, "y", PercentBaseSelector.ViewBoxHeight); var dyChildList = GetLengthPercentList(tspanElement, "dy", PercentBaseSelector.ViewBoxHeight); position.Y.SetChildValues(yChildList, dyChildList); var hasOwnFill = ExistsAttributeOnTop("fill"); var hasOwnStroke = ExistsAttributeOnTop("stroke"); var tspanFontSize = GetFontSize(); var tspanTypeface = GetTypeface(); var tspanAnchor = GetTextAnchor(); rotation.ChildValues = GetRotate(tspanElement); var charBlock = Vectorize(positionBlocks, tspanElement.Value, tspanAnchor, position, beginOfLine, hasSuccessor, tspanTypeface, tspanFontSize, rotation, currentTransformationMatrix); rotation.ChildValues = null; position.X.SetChildValues(null, null); position.Y.SetChildValues(null, null); if (isTspanDisplayed) { ColorBlock colorBlock; if (hasOwnFill || hasOwnStroke) { colorBlock = new ColorBlock(); colorBlocks.Add(colorBlock); colorBlock.Characters = charBlock; colorBlock.AdjustFillGlobal = !hasOwnFill; colorBlock.AdjustStrokeGlobal = !hasOwnStroke; } else { colorBlock = textColorBlock; textColorBlock.Characters.AddRange(charBlock); } for (int i = 0; i < charBlock.Count; i++) { var path = new GraphicPath(); colorBlock.Paths.Add(path); brushParser.SetFillAndStroke(tspanElement, path, currentTransformationMatrix, textOpacity, textFillOpacity, textStrokeOpacity); } } cssStyleCascade.Pop(); } break; case "textpath": { break; } } break; } case XText textContentElement: { var charBlock = Vectorize(positionBlocks, textContentElement.Value, textAnchor, position, beginOfLine, hasSuccessor, typeface, fontSize, rotation, currentTransformationMatrix); textColorBlock.Characters.AddRange(charBlock); for (int i = 0; i < charBlock.Count; i++) { var path = new GraphicPath(); textColorBlock.Paths.Add(path); brushParser.SetFillAndStroke(textElement, path, currentTransformationMatrix); } break; } } beginOfLine = false; node = nextNode; } AdjustPosition(positionBlocks); if (GetTextLength(textElement, out double textLength)) { textLength = MatrixUtilities.TransformScale(textLength, currentTransformationMatrix); AdjustLength(positionBlocks, textLength, GetTextAdjust(textElement)); } UpdateColorBlockPathGeometry(colorBlocks); AdjustGradients(colorBlocks); foreach (var block in colorBlocks) { graphicGroup.Children.AddRange(block.Paths); } if (clipping.IsClipPathSet()) { clipping.SetClipPath(graphicGroup, currentTransformationMatrix); } return(graphicGroup); }
/// <summary> /// Run the interpreter and dispose everything /// </summary> private bool Run(StreamReader stream, List <IDisposable> disposables, int postscriptVersion, out GraphicGroup graph) { bool success = true; graph = null; try { var interpreter = new EpsInterpreter(); graph = interpreter.Run(stream, postscriptVersion); } catch { success = false; } finally { foreach (var disposable in disposables) { disposable.Dispose(); } } return(success); }
/// <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); }