Example #1
0
 def rect_to_rect(cls, src: Rect, dst: Rect) -> "Affine2D":
     """ Return Affine2D set to scale and translate src Rect to dst Rect.
     The mapping completely fills dst, it does not preserve aspect ratio.
     """
     if src.empty():
         return cls.identity()
     if dst.empty():
         return cls(0, 0, 0, 0, 0, 0)
     sx = dst.w / src.w
     sy = dst.h / src.h
     tx = dst.x - src.x * sx
     ty = dst.y - src.y * sy
     return cls(sx, 0, 0, sy, tx, ty)
Example #2
0
    def rect_to_rect(
        cls,
        src: Rect,
        dst: Rect,
        preserveAspectRatio: str = "none",
    ) -> "Affine2D":
        """Return Affine2D set to scale and translate src Rect to dst Rect.
        By default the mapping completely fills dst, it does not preserve aspect ratio,
        unless the 'preserveAspectRatio' argument is used.
        See https://www.w3.org/TR/SVG/coords.html#PreserveAspectRatioAttribute for
        the list of values supported.
        """
        if src.empty():
            return cls.identity()
        if dst.empty():
            return cls(0, 0, 0, 0, 0, 0)

        # We follow the same process described in the SVG spec for computing the
        # equivalent scale + translation which maps from viewBox (src) to viewport (dst)
        # coordinates given the value of preserveAspectRatio.
        # https://www.w3.org/TR/SVG/coords.html#ComputingAViewportsTransform
        sx = dst.w / src.w
        sy = dst.h / src.h

        align, _, meetOrSlice = preserveAspectRatio.lower().strip().partition(
            " ")
        if (align not in cls._ALIGN_VALUES
                or meetOrSlice and meetOrSlice not in cls._MEET_OR_SLICE):
            raise ValueError(
                f"Invalid preserveAspectRatio: {preserveAspectRatio!r}")

        if align != "none":
            sx = sy = max(sx, sy) if "slice" in meetOrSlice else min(sx, sy)

        tx = dst.x - src.x * sx
        ty = dst.y - src.y * sy

        if "xmid" in align:
            tx += (dst.w - src.w * sx) / 2
        elif "xmax" in align:
            tx += dst.w - src.w * sx
        if "ymid" in align:
            ty += (dst.h - src.h * sy) / 2
        elif "ymax" in align:
            ty += dst.h - src.h * sy

        return cls(sx, 0, 0, sy, tx, ty)