private void ApplyUserSpaceScaling(SvgDrawContext context) { if (!this.attributesAndStyles.ContainsKey(SvgConstants.Attributes.MARKER_UNITS) || SvgConstants.Values.STROKEWIDTH .Equals(this.attributesAndStyles.Get(SvgConstants.Attributes.MARKER_UNITS))) { String parentValue = this.GetParent().GetAttribute(SvgConstants.Attributes.STROKE_WIDTH); if (parentValue != null) { float strokeWidthScale; if (CssUtils.IsPercentageValue(parentValue)) { // If stroke width is a percentage value is always computed as a percentage of the normalized viewBox diagonal length. double rootViewPortHeight = context.GetRootViewPort().GetHeight(); double rootViewPortWidth = context.GetRootViewPort().GetWidth(); double viewBoxDiagonalLength = Math.Sqrt(rootViewPortHeight * rootViewPortHeight + rootViewPortWidth * rootViewPortWidth ); strokeWidthScale = CssUtils.ParseRelativeValue(parentValue, (float)viewBoxDiagonalLength); } else { strokeWidthScale = SvgCssUtils.ConvertPtsToPx(ParseFontRelativeOrAbsoluteLengthOnMarker(parentValue)); } context.GetCurrentCanvas().ConcatMatrix(AffineTransform.GetScaleInstance(strokeWidthScale, strokeWidthScale )); } } }
private void ApplyCoordinatesTranslation(SvgDrawContext context) { float xScale = 1; float yScale = 1; if (this.attributesAndStyles.ContainsKey(SvgConstants.Attributes.VIEWBOX)) { //Parse viewbox parameters stuff String viewBoxValues = attributesAndStyles.Get(SvgConstants.Attributes.VIEWBOX); IList <String> valueStrings = SvgCssUtils.SplitValueList(viewBoxValues); float[] viewBox = GetViewBoxValues(); xScale = context.GetCurrentViewPort().GetWidth() / viewBox[2]; yScale = context.GetCurrentViewPort().GetHeight() / viewBox[3]; } float moveX = DEFAULT_REF_X; if (this.attributesAndStyles.ContainsKey(SvgConstants.Attributes.REFX)) { String refX = this.attributesAndStyles.Get(SvgConstants.Attributes.REFX); if (CssUtils.IsPercentageValue(refX)) { moveX = CssUtils.ParseRelativeValue(refX, context.GetRootViewPort().GetWidth()); } else { moveX = ParseFontRelativeOrAbsoluteLengthOnMarker(refX); } //Apply scale moveX *= -1 * xScale; } float moveY = DEFAULT_REF_Y; if (this.attributesAndStyles.ContainsKey(SvgConstants.Attributes.REFY)) { String refY = this.attributesAndStyles.Get(SvgConstants.Attributes.REFY); if (CssUtils.IsPercentageValue(refY)) { moveY = CssUtils.ParseRelativeValue(refY, context.GetRootViewPort().GetHeight()); } else { moveY = ParseFontRelativeOrAbsoluteLengthOnMarker(refY); } moveY *= -1 * yScale; } AffineTransform translation = AffineTransform.GetTranslateInstance(moveX, moveY); if (!translation.IsIdentity()) { context.GetCurrentCanvas().ConcatMatrix(translation); } }
/// <summary> /// When in the svg element /// <c>overflow</c> /// is /// <c>visible</c> /// the corresponding formXObject /// should have a BBox (form XObject’s bounding box; see PDF 32000-1:2008 - 8.10.2 Form Dictionaries) /// that should cover the entire svg space (page in pdf) in order to be able to show parts of the element which are outside the current element viewPort. /// </summary> /// <remarks> /// When in the svg element /// <c>overflow</c> /// is /// <c>visible</c> /// the corresponding formXObject /// should have a BBox (form XObject’s bounding box; see PDF 32000-1:2008 - 8.10.2 Form Dictionaries) /// that should cover the entire svg space (page in pdf) in order to be able to show parts of the element which are outside the current element viewPort. /// To do this, we get the inverse matrix of all the current transformation matrix changes and apply it to the root viewPort. /// This allows you to get the root rectangle in the final coordinate system. /// </remarks> /// <param name="context">current context to get canvases and view ports</param> /// <param name="stream">stream to write a BBox</param> private static void WriteBBoxAccordingToVisibleOverflow(SvgDrawContext context, PdfStream stream) { IList <PdfCanvas> canvases = new List <PdfCanvas>(); int canvasesSize = context.Size(); for (int i = 0; i < canvasesSize; i++) { canvases.Add(context.PopCanvas()); } AffineTransform transform = new AffineTransform(); for (int i = canvases.Count - 1; i >= 0; i--) { PdfCanvas canvas = canvases[i]; Matrix matrix = canvas.GetGraphicsState().GetCtm(); transform.Concatenate(new AffineTransform(matrix.Get(0), matrix.Get(1), matrix.Get(3), matrix.Get(4), matrix .Get(6), matrix.Get(7))); context.PushCanvas(canvas); } try { transform = transform.CreateInverse(); } catch (NoninvertibleTransformException) { // Case with zero determiner (see PDF 32000-1:2008 - 8.3.4 Transformation Matrices - NOTE 3) // for example with a, b, c, d in cm equal to 0 stream.Put(PdfName.BBox, new PdfArray(new Rectangle(0, 0, 0, 0))); ILog logger = LogManager.GetLogger(typeof(AbstractBranchSvgNodeRenderer)); logger.Warn(SvgLogMessageConstant.UNABLE_TO_GET_INVERSE_MATRIX_DUE_TO_ZERO_DETERMINANT); return; } Point[] points = context.GetRootViewPort().ToPointsArray(); transform.Transform(points, 0, points, 0, points.Length); Rectangle bbox = Rectangle.CalculateBBox(JavaUtil.ArraysAsList(points)); stream.Put(PdfName.BBox, new PdfArray(bbox)); }