/// <summary>
        /// Calculates the matrix to transform the content by to fit into the specified viewport dimensions
        /// </summary>
        public static SvgMatrix CalculateViewboxFit(this ISvgFitToViewbox fitToViewbox, float viewportWidth, float viewportHeight)
        {
            CalculateViewboxFit(fitToViewbox, viewportWidth, viewportHeight, out var scaleX, out var scaleY, out var offsetX, out var offsetY);
            var translateMatrix = SvgMatrix.CreateTranslate(offsetX, offsetY);
            var scaleMatrix     = SvgMatrix.CreateScale(scaleX, scaleY);

            return(SvgMatrix.Multiply(translateMatrix, scaleMatrix));
        }
Пример #2
0
        private bool PushViewportMatrixIfValid(ISvgFitToViewbox fitToViewbox, float viewportWidth, float viewportHeight)
        {
            if (viewportWidth <= 0 || viewportHeight <= 0)
            {
                return(false);
            }
            var matrix = fitToViewbox.CalculateViewboxFit(viewportWidth, viewportHeight);

            PushMatrix(matrix);
            return(true);
        }
Пример #3
0
        private PageElement EstablishViewportThen <TArg>(ISvgFitToViewbox fitToViewbox, float viewportWidth, float viewportHeight, Func <TArg, PageElement> transform, TArg arg)
        {
            ClippingGroup result = null;
            var           matrix = CurrentMatrix;

            if (PushViewportMatrixIfValid(fitToViewbox, viewportWidth, viewportHeight))
            {
                SvgMatrix.Multiply(matrix, 0, 0, out var xMin, out var yMin);
                SvgMatrix.Multiply(matrix, viewportWidth, viewportHeight, out var xMax, out var yMax);
                result = new ClippingGroup(xMin, yMin, xMax, yMax, transform(arg));
                PopMatrix();
            }
            return(result);
        }
        /// <summary>
        /// Calculates the scale and offset values to transform the content by to fit into the specified viewport dimensions
        /// </summary>
        public static void CalculateViewboxFit(this ISvgFitToViewbox fitToViewbox, float viewportWidth, float viewportHeight, out float scaleX, out float scaleY, out float offsetX, out float offsetY)
        {
            if (fitToViewbox == null)
            {
                throw new ArgumentNullException(nameof(fitToViewbox));
            }
            var viewBox = fitToViewbox.ViewBox ?? new SvgRect(0, 0, viewportWidth, viewportHeight);

            var preserveAspectRatio = fitToViewbox.PreserveAspectRatio;
            var meetOrSliceFlag     = preserveAspectRatio?.MeetOrSlice ?? SvgPreserveAspectRatioMeetOrSlice.Meet;
            var alignFlag           = preserveAspectRatio?.Align ?? SvgPreserveAspectRatioAlign.XMidYMid;

            scaleX = viewportWidth / viewBox.Width;
            scaleY = viewportHeight / viewBox.Height;
            float uniformScale;

            switch (meetOrSliceFlag)
            {
            case SvgPreserveAspectRatioMeetOrSlice.Meet:
                uniformScale = Math.Min(scaleX, scaleY);
                break;

            case SvgPreserveAspectRatioMeetOrSlice.Slice:
                uniformScale = Math.Max(scaleX, scaleY);
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            if (alignFlag != SvgPreserveAspectRatioAlign.None)
            {
                scaleX = scaleY = uniformScale;
            }

            var xMin = -viewBox.X;
            var yMin = -viewBox.Y;
            var xMid = xMin + (viewportWidth - viewBox.Width * scaleX) * 0.5f;
            var yMid = yMin + (viewportHeight - viewBox.Height * scaleY) * 0.5f;
            var xMax = xMin + (viewportWidth - viewBox.Width * scaleX);
            var yMax = yMin + (viewportHeight - viewBox.Height * scaleY);

            switch (alignFlag)
            {
            case SvgPreserveAspectRatioAlign.None:
                offsetX = offsetY = 0;
                break;

            case SvgPreserveAspectRatioAlign.XMinYMin:
                offsetX = xMin;
                offsetY = yMin;
                break;

            case SvgPreserveAspectRatioAlign.XMidYMin:
                offsetX = xMid;
                offsetY = yMin;
                break;

            case SvgPreserveAspectRatioAlign.XMaxYMin:
                offsetX = xMax;
                offsetY = yMin;
                break;

            case SvgPreserveAspectRatioAlign.XMinYMid:
                offsetX = xMin;
                offsetY = yMid;
                break;

            case SvgPreserveAspectRatioAlign.XMidYMid:
                offsetX = xMid;
                offsetY = yMid;
                break;

            case SvgPreserveAspectRatioAlign.XMaxYMid:
                offsetX = xMax;
                offsetY = yMid;
                break;

            case SvgPreserveAspectRatioAlign.XMinYMax:
                offsetX = xMin;
                offsetY = yMax;
                break;

            case SvgPreserveAspectRatioAlign.XMidYMax:
                offsetX = xMid;
                offsetY = yMax;
                break;

            case SvgPreserveAspectRatioAlign.XMaxYMax:
                offsetX = xMax;
                offsetY = yMax;
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
        }