def _apply_solid_paint(el: etree.Element, paint: PaintSolid): if etree.QName(el.tag).localname == "g": assert paint.color.opaque() == Color.fromstring( "black"), "Unexpected color choice" if paint.color.opaque() != Color.fromstring("black"): el.attrib["fill"] = paint.color.opaque().to_string() if paint.color.alpha != 1.0: el.attrib["opacity"] = _ntos(paint.color.alpha)
def _paint_glyph( debug_hint: str, config: FontConfig, picosvg: SVG, context: SVGTraverseContext, glyph_width: int, ) -> Paint: shape = context.shape() if shape.fill.startswith("url("): fill_el = picosvg.resolve_url(shape.fill, "*") try: glyph_paint = _GRADIENT_INFO[etree.QName(fill_el).localname]( config, fill_el, shape.bounding_box(), picosvg.view_box(), glyph_width, shape.opacity, ) except ValueError as e: raise ValueError( f"parse failed for {debug_hint}, {etree.tostring(fill_el)[:128]}" ) from e else: glyph_paint = PaintSolid( color=Color.fromstring(shape.fill, alpha=shape.opacity) ) return PaintGlyph(glyph=shape.as_path().d, paint=glyph_paint)
def _color_index_node(palette, color_index): color = Color.fromstring(palette[color_index.PaletteIndex].hex()) ci_alpha = color_index.Alpha.value node_id = f"{ci_alpha:.2f}.{color.opaque().to_string()}.{color.alpha:.2f}" return Node( node_id=node_id, node_label=color._replace(alpha=color.alpha * ci_alpha).to_string(), )
def _color_stop(stop_el): offset = stop_el.attrib.get("offset", "0") if offset.endswith("%"): offset = float(offset[:-1]) / 100 else: offset = float(offset) color = stop_el.attrib.get("stop-color", "black") if "stop-opacity" in stop_el.attrib: raise ValueError("<stop stop-opacity/> not supported") return ColorStop(stopOffset=offset, color=Color.fromstring(color))
def _paint(nsvg, shape): match = regex.match(r"^url[(]#([^)]+)[)]$", shape.fill) if shape.fill.startswith("url("): el = nsvg.resolve_url(shape.fill, "*") grad_type, grad_type_parser = _GRADIENT_INFO[etree.QName(el).localname] grad_args = _common_gradient_parts(el) grad_args.update(grad_type_parser(el)) return grad_type(**grad_args) return PaintSolid(color=Color.fromstring(shape.fill, alpha=shape.opacity))
class PaintSolid(Paint): format: ClassVar[int] = int(ot.PaintFormat.PaintSolid) color: Color = Color.fromstring("black") def colors(self): yield self.color def to_ufo_paint(self, colors): return { "Format": self.format, "PaletteIndex": colors.index(self.color.opaque()), "Alpha": self.color.alpha, }
def _paint( debug_hint: str, config: FontConfig, picosvg: SVG, shape: SVGPath, glyph_width: int ) -> Paint: if shape.fill.startswith("url("): el = picosvg.resolve_url(shape.fill, "*") try: return _GRADIENT_INFO[etree.QName(el).localname]( config, el, shape.bounding_box(), picosvg.view_box(), glyph_width, shape.opacity, ) except ValueError as e: raise ValueError( f"parse failed for {debug_hint}, {etree.tostring(el)[:128]}" ) from e return PaintSolid(color=Color.fromstring(shape.fill, alpha=shape.opacity))
def _paint(self, shape): upem = self.ufo.info.unitsPerEm if shape.fill.startswith("url("): el = self.picosvg.resolve_url(shape.fill, "*") grad_type, grad_type_parser = _GRADIENT_INFO[etree.QName( el).localname] grad_args = _common_gradient_parts(el, shape.opacity) try: grad_args.update( grad_type_parser(el, shape.bounding_box(), self.picosvg.view_box(), upem)) except ValueError as e: raise ValueError( f"parse failed for {self.filename}, {etree.tostring(el)[:128]}" ) from e return grad_type(**grad_args) return PaintSolid( color=Color.fromstring(shape.fill, alpha=shape.opacity))
def test_color_fromstring(color_string, expected_color): assert expected_color == Color.fromstring(color_string)
r1=round(paint.r1, prec), affine2x2=(tuple(round(v, prec) for v in paint.affine2x2) if paint.affine2x2 is not None else None), ) else: return paint @pytest.mark.parametrize( "svg_in, expected_paints", [ # solid ( "rect.svg", { PaintSolid(color=Color.fromstring("blue")), PaintSolid(color=Color.fromstring("blue", alpha=0.8)), }, ), # linear ( "linear_gradient_rect.svg", { PaintLinearGradient( stops=( ColorStop(stopOffset=0.1, color=Color.fromstring("blue")), ColorStop(stopOffset=0.9, color=Color.fromstring("cyan", 0.8)), ), p0=Point(200, 800),
def _color_stop(stop_el, shape_opacity=1.0) -> ColorStop: offset = number_or_percentage(stop_el.attrib.get("offset", "0")) color = Color.fromstring(stop_el.attrib.get("stop-color", "black")) opacity = number_or_percentage(stop_el.attrib.get("stop-opacity", "1")) color = color._replace(alpha=color.alpha * opacity * shape_opacity) return ColorStop(stopOffset=offset, color=color)
class ColorStop: stopOffset: float = 0.0 color: Color = Color.fromstring("black")
) color_glyph = ColorGlyph.create( _ufo(upem), "duck", 1, [0x0042], SVG.fromstring(svg_str) ) assert color_glyph.transform_for_font_space() == expected_transform @pytest.mark.parametrize( "svg_in, expected_paints", [ # solid ( "rect.svg", { PaintSolid(color=Color.fromstring("blue")), PaintSolid(color=Color.fromstring("blue", alpha=0.8)), }, ), # linear ( "linear_gradient_rect.svg", { PaintLinearGradient( stops=( ColorStop(stopOffset=0.1, color=Color.fromstring("blue")), ColorStop(stopOffset=0.9, color=Color.fromstring("cyan")), ) ) }, ),