Exemplo n.º 1
0
def normalize_flag_aspect(svg, viewbox_size, width, height, right_margin,
                          top_margin):
    apply_viewbox_preserve_aspect_ratio(svg)

    current_box = _bbox(tuple(s.bounding_box() for s in svg.shapes()))

    # Try to keep overall proportions for the flags that are considerably
    # narrower or wider than the standard aspect ratio.
    aspect = current_box.w / current_box.h
    aspect /= STD_ASPECT
    aspect = sqrt(aspect)  # Discount the effect
    if 0.9 <= aspect <= 1.1:
        aspect = 1.0
    else:
        print("Non-standard aspect ratio:", aspect)

    xmin = _x_aspect(right_margin, aspect, viewbox_size)
    ymin = _y_aspect(top_margin, aspect, viewbox_size)
    xmax = _x_aspect(right_margin + width, aspect, viewbox_size)
    ymax = _y_aspect(top_margin + height, aspect, viewbox_size)
    new_box = Rect(xmin, ymin, xmax - xmin, ymax - ymin)

    affine = Affine2D.rect_to_rect(current_box, new_box)

    _picosvg_transform(svg, affine)

    square_viewbox = Rect(0, 0, viewbox_size, viewbox_size)
    svg.svg_root.attrib["viewBox"] = " ".join(ntos(v) for v in square_viewbox)
    for attr_name in ("width", "height"):
        if attr_name in svg.svg_root.attrib:
            del svg.svg_root.attrib[attr_name]
Exemplo n.º 2
0
def apply_viewbox_preserve_aspect_ratio(svg):
    """If viewport != viewBox apply the resulting transform and remove viewBox.
    Takes 'preserveAspectRatio' into account.
    E.g. The Qatar flag (QA.svg) needs this treatment.
    """
    svg_root = svg.svg_root
    width = svg_root.attrib.get("width")
    height = svg_root.attrib.get("height")
    if width is not None and height is not None and "viewBox" in svg_root.attrib:
        # ignore absolute length units; we're only interested in the relative size
        # of viewport vs viewbox here
        width = SVG_UNITS_RE.sub("", width)
        height = SVG_UNITS_RE.sub("", height)
        viewport = Rect(0, 0, float(width), float(height))
        viewbox = svg.view_box()
        if viewport != viewbox:
            transform = Affine2D.rect_to_rect(
                viewbox,
                viewport,
                svg_root.attrib.get("preserveAspectRatio", "xMidYMid"),
            )
            _picosvg_transform(svg, transform)
            del svg_root.attrib["viewBox"]
            if "preserveAspectRatio" in svg_root.attrib:
                del svg_root.attrib["preserveAspectRatio"]
Exemplo n.º 3
0
def _get_gradient_transform(grad_el, shape_bbox, view_box, upem) -> Affine2D:
    transform = map_viewbox_to_font_emsquare(view_box, upem)

    gradient_units = grad_el.attrib.get("gradientUnits", "objectBoundingBox")
    if gradient_units == "objectBoundingBox":
        bbox_space = Rect(0, 0, 1, 1)
        bbox_transform = Affine2D.rect_to_rect(bbox_space, shape_bbox)
        transform = Affine2D.product(bbox_transform, transform)

    if "gradientTransform" in grad_el.attrib:
        gradient_transform = Affine2D.fromstring(
            grad_el.attrib["gradientTransform"])
        transform = Affine2D.product(gradient_transform, transform)

    return transform
Exemplo n.º 4
0
def _get_gradient_transform(
    config: FontConfig,
    grad_el: etree.Element,
    shape_bbox: Rect,
    view_box: Rect,
    glyph_width: int,
) -> Affine2D:
    transform = map_viewbox_to_font_space(
        view_box, config.ascender, config.descender, glyph_width, config.transform
    )

    gradient_units = grad_el.attrib.get("gradientUnits", "objectBoundingBox")
    if gradient_units == "objectBoundingBox":
        bbox_space = Rect(0, 0, 1, 1)
        bbox_transform = Affine2D.rect_to_rect(bbox_space, shape_bbox)
        transform = Affine2D.compose_ltr((bbox_transform, transform))

    if "gradientTransform" in grad_el.attrib:
        gradient_transform = Affine2D.fromstring(grad_el.attrib["gradientTransform"])
        transform = Affine2D.compose_ltr((gradient_transform, transform))

    return transform
Exemplo n.º 5
0
    def _unnest_svg(self, svg: etree.Element, parent_width: float,
                    parent_height: float) -> Tuple[etree.Element, ...]:
        x = float(svg.attrib.get("x", 0))
        y = float(svg.attrib.get("y", 0))
        width = float(svg.attrib.get("width", parent_width))
        height = float(svg.attrib.get("height", parent_height))

        viewport = viewbox = Rect(x, y, width, height)
        if "viewBox" in svg.attrib:
            viewbox = parse_view_box(svg.attrib["viewBox"])

        # first recurse to un-nest any nested nested SVGs
        self._swap_elements((el, self._unnest_svg(el, viewbox.w, viewbox.h))
                            for el in self._iter_nested_svgs(svg))

        g = etree.Element(f"{{{svgns()}}}g")
        g.extend(svg)

        if viewport != viewbox:
            preserve_aspect_ratio = svg.attrib.get("preserveAspectRatio",
                                                   "xMidYMid")
            transform = Affine2D.rect_to_rect(viewbox, viewport,
                                              preserve_aspect_ratio)
        else:
            transform = Affine2D.identity().translate(x, y)

        if "transform" in svg.attrib:
            transform = Affine2D.compose_ltr(
                (transform, Affine2D.fromstring(svg.attrib["transform"])))

        if transform != Affine2D.identity():
            g.attrib["transform"] = transform.tostring()

        # TODO Define a viewport-sized clipPath once transform+clip-path issue is fixed
        # https://github.com/googlefonts/picosvg/issues/200
        return (g, )
Exemplo n.º 6
0
 def _build_transformation(self, rect):
     return Affine2D.rect_to_rect(rect,
                                  Rect(0, 0, _SYMBOL_SIZE,
                                       _SYMBOL_SIZE)).translate(
                                           0, _SYMBOL_DY_MULTIPLE * rect.h)