/** * Copy constructor. * @param source another GraphicsState object */ public GraphicsState(GraphicsState source) { // note: all of the following are immutable, with the possible exception of font // so it is safe to copy them as-is ctm = source.ctm; characterSpacing = source.characterSpacing; wordSpacing = source.wordSpacing; horizontalScaling = source.horizontalScaling; leading = source.leading; font = source.font; fontSize = source.fontSize; renderMode = source.renderMode; rise = source.rise; knockout = source.knockout; colorSpaceFill = source.colorSpaceFill; colorSpaceStroke = source.colorSpaceStroke; fillColor = source.fillColor; strokeColor = source.strokeColor; lineWidth = source.lineWidth; lineCapStyle = source.lineCapStyle; lineJoinStyle = source.lineJoinStyle; miterLimit = source.miterLimit; if (source.lineDashPattern != null) { lineDashPattern = new LineDashPattern(source.lineDashPattern.DashArray, source.lineDashPattern.DashPhase); } }
private static Path ApplyDashPattern(Path path, LineDashPattern lineDashPattern) { HashSet2 <int> modifiedSubpaths = new HashSet2 <int>(path.ReplaceCloseWithLine()); Path dashedPath = new Path(); int currentSubpath = 0; foreach (Subpath subpath in path.Subpaths) { IList <Point2D> subpathApprox = subpath.GetPiecewiseLinearApproximation(); if (subpathApprox.Count > 1) { dashedPath.MoveTo((float)subpathApprox[0].GetX(), (float)subpathApprox[0].GetY()); float remainingDist = 0; bool remainingIsGap = false; for (int i = 1; i < subpathApprox.Count; ++i) { Point2D nextPoint = null; if (remainingDist != 0) { nextPoint = GetNextPoint(subpathApprox[i - 1], subpathApprox[i], remainingDist); remainingDist = ApplyDash(dashedPath, subpathApprox[i - 1], subpathApprox[i], nextPoint, remainingIsGap); } while ((Util.Compare(remainingDist, 0) == 0) && !dashedPath.CurrentPoint.Equals(subpathApprox[i])) { LineDashPattern.DashArrayElem currentElem = lineDashPattern.Next(); nextPoint = GetNextPoint(nextPoint ?? subpathApprox[i - 1], subpathApprox[i], currentElem.Value); remainingDist = ApplyDash(dashedPath, subpathApprox[i - 1], subpathApprox[i], nextPoint, currentElem.IsGap); remainingIsGap = currentElem.IsGap; } } // If true, then the line closing the subpath was explicitly added (see Path.ReplaceCloseWithLine). // This causes a loss of a visual effect of line join style parameter, so in this clause // we simply add overlapping dash (or gap, no matter), which continues the last dash and equals to // the first dash (or gap) of the path. if (modifiedSubpaths.Contains(currentSubpath)) { lineDashPattern.Reset(); LineDashPattern.DashArrayElem currentElem = lineDashPattern.Next(); Point2D nextPoint = GetNextPoint(subpathApprox[0], subpathApprox[1], currentElem.Value); ApplyDash(dashedPath, subpathApprox[0], subpathApprox[1], nextPoint, currentElem.IsGap); } } // According to PDF spec. line dash pattern should be restarted for each new subpath. lineDashPattern.Reset(); ++currentSubpath; } return(dashedPath); }
/** * @param fillingRule If the path is contour, pass any value. */ private Path FilterCurrentPath(Matrix ctm, bool stroke, int fillingRule, float lineWidth, int lineCapStyle, int lineJoinStyle, float miterLimit, LineDashPattern lineDashPattern) { Path path = new Path(unfilteredCurrentPath.Subpaths); if (stroke) { return(filter.FilterStrokePath(path, ctm, lineWidth, lineCapStyle, lineJoinStyle, miterLimit, lineDashPattern)); } else { return(filter.FilterFillPath(path, ctm, fillingRule)); } }
public virtual Path RenderPath(PathPaintingRenderInfo renderInfo) { // If previous clipping is empty, then we shouldn't compute the new one // because their intersection is empty. if (newClippingPath.IsEmpty()) { currentStrokePath = new Path(); currentFillPath = currentStrokePath; return(newClippingPath); } bool stroke = (renderInfo.Operation & PathPaintingRenderInfo.STROKE) != 0; bool fill = (renderInfo.Operation & PathPaintingRenderInfo.FILL) != 0; float lineWidth = renderInfo.LineWidth; int lineCapStyle = renderInfo.LineCapStyle; int lineJoinStyle = renderInfo.LineJoinStyle; float miterLimit = renderInfo.MiterLimit; LineDashPattern lineDashPattern = renderInfo.LineDashPattern; if (stroke) { currentStrokePath = FilterCurrentPath(renderInfo.Ctm, true, -1, lineWidth, lineCapStyle, lineJoinStyle, miterLimit, lineDashPattern); } if (fill) { currentFillPath = FilterCurrentPath(renderInfo.Ctm, false, renderInfo.Rule, lineWidth, lineCapStyle, lineJoinStyle, miterLimit, lineDashPattern); } if (clipPath) { if (fill && renderInfo.Rule == clippingRule) { newClippingPath = currentFillPath; } else { newClippingPath = FilterCurrentPath(renderInfo.Ctm, false, clippingRule, lineWidth, lineCapStyle, lineJoinStyle, miterLimit, lineDashPattern); } } unfilteredCurrentPath = new Path(); return(newClippingPath); }
private static bool IsZeroDash(LineDashPattern lineDashPattern) { PdfArray dashArray = lineDashPattern.DashArray; float total = 0; // We should only iterate over the numbers specifying lengths of dashes for (int i = 0; i < dashArray.Size; i += 2) { float currentDash = dashArray.GetAsNumber(i).FloatValue; // Should be nonnegative according to spec. if (currentDash < 0) { currentDash = 0; } total += currentDash; } return(Util.compare(total, 0) == 0); }
public virtual Path RenderPath(PathPaintingRenderInfo renderInfo) { bool stroke = (renderInfo.Operation & PathPaintingRenderInfo.STROKE) != 0; bool fill = (renderInfo.Operation & PathPaintingRenderInfo.FILL) != 0; float lineWidth = renderInfo.LineWidth; int lineCapStyle = renderInfo.LineCapStyle; int lineJoinStyle = renderInfo.LineJoinStyle; float miterLimit = renderInfo.MiterLimit; LineDashPattern lineDashPattern = renderInfo.LineDashPattern; if (stroke) { currentStrokePath = FilterCurrentPath(renderInfo.Ctm, true, -1, lineWidth, lineCapStyle, lineJoinStyle, miterLimit, lineDashPattern); } if (fill) { currentFillPath = FilterCurrentPath(renderInfo.Ctm, false, renderInfo.Rule, lineWidth, lineCapStyle, lineJoinStyle, miterLimit, lineDashPattern); } if (clipPath) { if (fill && renderInfo.Rule == clippingRule) { newClippingPath = currentFillPath; } else { newClippingPath = FilterCurrentPath(renderInfo.Ctm, false, clippingRule, lineWidth, lineCapStyle, lineJoinStyle, miterLimit, lineDashPattern); } } unfilteredCurrentPath = new Path(); return(newClippingPath); }
protected internal Path FilterStrokePath(Path sourcePath, Matrix ctm, float lineWidth, int lineCapStyle, int lineJoinStyle, float miterLimit, LineDashPattern lineDashPattern) { Path path = sourcePath; JoinType joinType = GetJoinType(lineJoinStyle); EndType endType = GetEndType(lineCapStyle); if (lineDashPattern != null && !lineDashPattern.IsSolid()) { path = ApplyDashPattern(path, lineDashPattern); } ClipperOffset offset = new ClipperOffset(miterLimit, PdfCleanUpProcessor.ArcTolerance * PdfCleanUpProcessor.FloatMultiplier); IList <Subpath> degenerateSubpaths = AddPath(offset, path, joinType, endType); PolyTree resultTree = new PolyTree(); offset.Execute(ref resultTree, lineWidth * PdfCleanUpProcessor.FloatMultiplier / 2); Path offsetedPath = ConvertToPath(resultTree); if (degenerateSubpaths.Count > 0) { if (endType == EndType.etOpenRound) { IList <Subpath> circles = ConvertToCircles(degenerateSubpaths, lineWidth / 2); offsetedPath.AddSubpaths(circles); } else if (endType == EndType.etOpenSquare && lineDashPattern != null) { IList <Subpath> squares = ConvertToSquares(degenerateSubpaths, lineWidth, sourcePath); offsetedPath.AddSubpaths(squares); } } return(FilterFillPath(offsetedPath, ctm, PathPaintingRenderInfo.NONZERO_WINDING_RULE)); }
public SetLineDashPattern(decimal[] array, int phase) { Pattern = new LineDashPattern(phase, array); }
/** * Setter for the line dash pattern. * @param lineDashPattern New line dash pattern. * @since 5.5.6 */ public virtual void SetLineDashPattern(LineDashPattern lineDashPattern) { this.lineDashPattern = new LineDashPattern(lineDashPattern.DashArray, lineDashPattern.DashPhase); }
/** * Copy constructor. * @param source another GraphicsState object */ public GraphicsState(GraphicsState source){ // note: all of the following are immutable, with the possible exception of font // so it is safe to copy them as-is ctm = source.ctm; characterSpacing = source.characterSpacing; wordSpacing = source.wordSpacing; horizontalScaling = source.horizontalScaling; leading = source.leading; font = source.font; fontSize = source.fontSize; renderMode = source.renderMode; rise = source.rise; knockout = source.knockout; colorSpaceFill = source.colorSpaceFill; colorSpaceStroke = source.colorSpaceStroke; fillColor = source.fillColor; strokeColor = source.strokeColor; lineWidth = source.lineWidth; lineCapStyle = source.lineCapStyle; lineJoinStyle = source.lineJoinStyle; miterLimit = source.miterLimit; if (source.lineDashPattern != null) { lineDashPattern = new LineDashPattern(source.lineDashPattern.DashArray, source.lineDashPattern.DashPhase); } }
public void SetLineDashPattern(LineDashPattern pattern) { GetCurrentState().LineDashPattern = pattern; }
protected internal virtual Path FilterStrokePath(Path path, Matrix ctm, float lineWidth, int lineCapStyle, int lineJoinStyle, float miterLimit, LineDashPattern lineDashPattern) { JoinType joinType = GetJoinType(lineJoinStyle); EndType endType = GetEndType(lineCapStyle); if (lineDashPattern != null) { if (IsZeroDash(lineDashPattern)) { return(new Path()); } if (!IsSolid(lineDashPattern)) { path = ApplyDashPattern(path, lineDashPattern); } } ClipperOffset offset = new ClipperOffset(miterLimit, PdfCleanUpProcessor.ArcTolerance * PdfCleanUpProcessor.FloatMultiplier); AddPath(offset, path, joinType, endType); PolyTree resultTree = new PolyTree(); offset.Execute(ref resultTree, lineWidth * PdfCleanUpProcessor.FloatMultiplier / 2); return(FilterFillPath(ConvertToPath(resultTree), ctm, PathPaintingRenderInfo.NONZERO_WINDING_RULE)); }
private static bool IsSolid(LineDashPattern lineDashPattern) { return(lineDashPattern.DashArray.IsEmpty()); }