# Mask and Gradient Maintenance Smoke Run this manual smoke from the repository root after changing gradient validation, gradient import/export, native background promotion, icon expansion, or mask rejection. It keeps XML in memory except for temporary SVG fixtures; do not turn it into a test framework or example deck. ```bash python3 - <<'PY' import math import re import sys import tempfile from pathlib import Path from xml.etree import ElementTree as ET scripts = Path("skills/ppt-master/scripts").resolve() sys.path.insert(0, str(scripts)) from pptx_to_svg.color_resolver import ColorPalette from pptx_to_svg.fill_to_svg import _angle_to_unit_endpoints, resolve_fill from svg_quality_checker import SVGQualityChecker from svg_to_pptx.drawingml.converter import ( SvgNativeConversionError, convert_svg_to_slide_shapes, ) from svg_to_pptx.drawingml.styles import build_gradient_fill from svg_to_pptx.drawingml.utils import ( parse_project_linear_gradient_coordinate, project_gradient_errors, project_mask_errors, ) SVG_NS = "http://www.w3.org/2000/svg" def svg(fragment): return ET.fromstring( f'{fragment}' ) valid = svg( """ """ ) assert not project_gradient_errors(valid) linear, radial = list(valid.find(f"{{{SVG_NS}}}defs")) linear_xml = build_gradient_fill(linear) radial_xml = build_gradient_fill(radial) assert '' in linear_xml assert '' in linear_xml assert '' in radial_xml assert ( '' in radial_xml ) radial.set("fx", "0.8") radial.set("fy", "0.2") focused_xml = build_gradient_fill(radial) assert ( '' in focused_xml ) native_gradient = ET.fromstring( f'' f'{focused_xml}' )[0] restored = resolve_fill(native_gradient, None) assert 'cx="0.5" cy="0.5" r="0.5" fx="0.8" fy="0.2"' in restored.defs[0] assert '' in ( build_gradient_fill(ET.fromstring(restored.defs[0])) ) radial.set("fx", "0") radial.set("fy", "0") outside_focus_errors = project_gradient_errors(valid) assert any( "must lie within the canonical circle" in error for error in outside_focus_errors ), outside_focus_errors try: build_gradient_fill(radial) except ValueError as exc: assert "must lie within the canonical circle" in str(exc) else: raise AssertionError("outside radial focus reached DrawingML") radial.set("fx", "0.8") radial.set("fy", "0.2") diagnostics = [] palette = ColorPalette( None, None, strict=False, diagnostic_sink=lambda code, message, fallback: diagnostics.append( (code, message, fallback) ), ) outside_native_xml = focused_xml.replace( 'l="80000" t="20000" r="20000" b="80000"', 'l="0" t="0" r="100000" b="100000"', ) outside_native_gradient = ET.fromstring( f'' f"{outside_native_xml}" )[0] normalized = resolve_fill(outside_native_gradient, palette) assert " fx=" not in normalized.defs[0] assert " fy=" not in normalized.defs[0] assert any( code == "path-gradient-focus-normalized" for code, _message, _fallback in diagnostics ) with tempfile.TemporaryDirectory(prefix="ppt-master-gradient-smoke-") as tmp: source = Path(tmp) / "gradient.svg" source.write_text( ET.tostring(valid, encoding="unicode"), encoding="utf-8", ) trace = [] slide_xml, *_ = convert_svg_to_slide_shapes(source, trace_out=trace) assert slide_xml.count("") == 1 assert "" in slide_xml assert trace[0]["summary"]["promoted_backgrounds"] == 1 assert any( event.get("decision") == "native-background" for event in trace[0]["events"] ) invalid_gradients = [ ( """ """, "requires at least two direct children", ), ( """ """, "offsets must be non-decreasing", ), ( """ """, "linear gradient axis must not collapse to one point", ), ] for definition, expected in invalid_gradients: errors = project_gradient_errors(svg(f"{definition}")) assert any(expected in error for error in errors), errors mask_cases = [ """""", """""", """""", ] for fragment in mask_cases: errors = project_mask_errors(svg(fragment)) assert any("unsupported SVG mask" in error for error in errors), errors checker = SVGQualityChecker() with tempfile.TemporaryDirectory(prefix="ppt-master-mask-smoke-") as tmp: for index, fragment in enumerate(mask_cases, start=1): source = Path(tmp) / f"mask-{index}.svg" source.write_text( ET.tostring(svg(fragment), encoding="unicode"), encoding="utf-8", ) checked = checker.check_file(str(source)) assert any("mask" in error.lower() for error in checked["errors"]) try: convert_svg_to_slide_shapes(source) except SvgNativeConversionError as exc: assert "invalid project mask" in str(exc) else: raise AssertionError(f"native export accepted {source.name}") with tempfile.TemporaryDirectory(prefix="ppt-master-icon-mask-smoke-") as tmp: project = Path(tmp) icon_dir = project / "icons" / "imported" icon_dir.mkdir(parents=True) (icon_dir / "masked.svg").write_text( f""" """, encoding="utf-8", ) source = project / "icon-mask.svg" source.write_text( ET.tostring( svg( """""" ), encoding="unicode", ), encoding="utf-8", ) checked = checker.check_file(str(source)) assert any( "Icon imported/masked" in error and "mask" in error.lower() for error in checked["errors"] ) try: convert_svg_to_slide_shapes(source) except SvgNativeConversionError as exc: assert "invalid project mask" in str(exc) else: raise AssertionError("native export accepted a masked icon") x1, y1, x2, y2 = _angle_to_unit_endpoints(30) assert any(value < 0 or value > 1 for value in (x1, y1, x2, y2)) for value in (x1, y1, x2, y2): assert math.isclose( parse_project_linear_gradient_coordinate(str(value)), value, abs_tol=1e-9, ) roundtrip = svg( f""" """ ) assert not project_gradient_errors(roundtrip) roundtrip_gradient = roundtrip.find( f"{{{SVG_NS}}}defs/{{{SVG_NS}}}linearGradient" ) angle = int( re.search( r'