#!/usr/bin/env python3 """ SVG Deep Analysis Tool Deeper analysis of the original SVG structure to understand the exact pattern """ import re import sys from collections import defaultdict def extract_paths_with_details(svg_content, limit=50): """Extract detailed path information""" # More robust pattern for paths path_pattern = r'<(?:\w+:)?path\s+([^>]*)/?>' paths = [] for i, match in enumerate(re.finditer(path_pattern, svg_content, re.IGNORECASE)): if i >= limit: break attrs_str = match.group(1) # Parse all attributes attrs = {} for attr_match in re.finditer(r'(\w+(?:-\w+)*)="([^"]*)"', attrs_str): attrs[attr_match.group(1)] = attr_match.group(2) # Get d length d = attrs.get('d', '') attrs['_d_length'] = len(d) attrs['_d_preview'] = d[:100] + '...' if len(d) > 100 else d paths.append({ 'index': i, 'position': match.start(), 'attrs': attrs }) return paths def analyze_path_patterns(paths): """Analyze patterns in path definitions""" patterns = [] for i in range(0, min(len(paths), 20), 2): if i + 1 < len(paths): p1 = paths[i]['attrs'] p2 = paths[i + 1]['attrs'] same_d = p1.get('d', '') == paths[i+1]['attrs'].get('d', '') if '_d_length' not in p1 else p1.get('_d_length') == p2.get('_d_length') pattern = { 'pair': f"{i} & {i+1}", 'same_path_data': same_d, 'path1': { 'fill': p1.get('fill'), 'stroke': p1.get('stroke'), 'opacity': p1.get('opacity'), 'fill-opacity': p1.get('fill-opacity'), 'stroke-width': p1.get('stroke-width') }, 'path2': { 'fill': p2.get('fill'), 'stroke': p2.get('stroke'), 'opacity': p2.get('opacity'), 'fill-opacity': p2.get('fill-opacity'), 'stroke-width': p2.get('stroke-width') } } patterns.append(pattern) return patterns def find_group_structure(svg_content): """Analyze group nesting structure""" # Find all groups and their attributes group_pattern = r'<(?:\w+:)?g\s+([^>]*)>' groups = [] for match in re.finditer(group_pattern, svg_content, re.IGNORECASE): attrs_str = match.group(1) attrs = {} for attr_match in re.finditer(r'(\w+(?:-\w+)*)="([^"]*)"', attrs_str): attrs[attr_match.group(1)] = attr_match.group(2) groups.append({ 'position': match.start(), 'attrs': attrs }) return groups def main(): if len(sys.argv) < 2: print("Usage: python svg-deep-analysis.py ") sys.exit(1) filepath = sys.argv[1] with open(filepath, 'r') as f: content = f.read() print(f"\n{'='*70}") print(f"DEEP SVG ANALYSIS: {filepath}") print('='*70) # Analyze groups groups = find_group_structure(content) print(f"\nšŸ“ GROUPS ({len(groups)}):") for i, g in enumerate(groups[:10]): print(f" Group {i}: {g['attrs']}") # Analyze paths in detail paths = extract_paths_with_details(content, limit=30) print(f"\nšŸ“ FIRST 30 PATHS DETAILS:") for p in paths[:30]: attrs = p['attrs'] print(f"\n Path {p['index']}:") print(f" fill: {attrs.get('fill', 'NONE')}") print(f" stroke: {attrs.get('stroke', 'NONE')}") print(f" stroke-width: {attrs.get('stroke-width', 'NONE')}") print(f" opacity: {attrs.get('opacity', 'NONE')}") print(f" fill-opacity: {attrs.get('fill-opacity', 'NONE')}") print(f" d length: {attrs.get('_d_length')}") # Analyze patterns patterns = analyze_path_patterns(paths) print(f"\nšŸ” PATH PAIR PATTERNS (checking if paths come in fill+stroke pairs):") for p in patterns: print(f"\n {p['pair']}:") print(f" Same path data: {p['same_path_data']}") print(f" Path 1: fill={p['path1']['fill']}, stroke={p['path1']['stroke']}, opacity={p['path1']['opacity']}") print(f" Path 2: fill={p['path2']['fill']}, stroke={p['path2']['stroke']}, sw={p['path2']['stroke-width']}") # Look for image elements image_pattern = r'<(?:\w+:)?image\s+([^>]*)/?>' images = list(re.finditer(image_pattern, content, re.IGNORECASE)) print(f"\nšŸ–¼ļø IMAGES ({len(images)}):") for i, img in enumerate(images): attrs_str = img.group(1) # Extract key attrs x = re.search(r'x="([^"]*)"', attrs_str) y = re.search(r'y="([^"]*)"', attrs_str) w = re.search(r'width="([^"]*)"', attrs_str) h = re.search(r'height="([^"]*)"', attrs_str) mask = re.search(r'mask="([^"]*)"', attrs_str) print(f" Image {i} at position {img.start()}:") print(f" x={x.group(1) if x else 'N/A'}, y={y.group(1) if y else 'N/A'}") print(f" w={w.group(1) if w else 'N/A'}, h={h.group(1) if h else 'N/A'}") print(f" mask={mask.group(1) if mask else 'NONE'}") print("\n" + "="*70) print("DIAGNOSIS SUMMARY") print("="*70) print(""" Based on this analysis, the SVG structure is: 1. PATHS COME IN PAIRS: - First path: Colored FILL with low opacity (e.g., fill=#ff7d2e opacity=.03) This creates the "highlighter" effect - Second path: Same geometry with STROKE only (stroke=#000000 stroke-width=2) This creates a thin outline 2. ISSUE WITH CONVERTER: - We're treating filled paths and stroked paths separately - We should recognize these as a SINGLE stroke with: * color from the fill * stroke-width from the companion stroke path (or default to 2) * opacity from the fill-opacity or opacity 3. IMAGES: - Images appear EARLY in the document (as backgrounds) - Our converter outputs them LAST (covering content) FIX NEEDED: - Detect fill+stroke path pairs (same d attribute) - Merge them into single ColorRM item - Preserve element order (images first = background) """) if __name__ == '__main__': main()