help@rskworld.in +91 93305 39277
RSK World
  • Home
  • Development
    • Web Development
    • Mobile Apps
    • Software
    • Games
    • Project
  • Technologies
    • Data Science
    • AI Development
    • Cloud Development
    • Blockchain
    • Cyber Security
    • Dev Tools
    • Testing Tools
  • About
  • Contact

Theme Settings

Color Scheme
Display Options
Font Size
100%
Back to Project
RSK World
python-pattern-generator
/
__pycache__
RSK World
python-pattern-generator
Python Number Pattern Generator - 22 Pattern Types + Fractals + Mathematical Algorithms + GUI & Web Interface + REST API + Educational Design
__pycache__
  • main.cpython-313.pyc39.4 KB
  • patterns.cpython-313.pyc30.1 KB
svg_export.py
svg_export.py
Raw Download
Find: Go to:
"""
SVG Export Module for Python Number Pattern Generator
Author: Molla Samser (Founder, RSK World)
Designer & Tester: Rima Khatun
Website: https://rskworld.in
Year: 2026
Description: Export patterns as scalable vector graphics
"""

from typing import Dict, List, Any, Optional, Tuple
from datetime import datetime
import re


class SVGExporter:
    """SVG export functionality for patterns"""

    def __init__(self):
        """Initialize SVG exporter"""
        self.font_family = "monospace"
        self.font_size = 14
        self.char_width = self.font_size * 0.6  # Approximate character width
        self.line_height = self.font_size * 1.2
        self.padding = 20

    def export_pattern(self, pattern: str, metadata: Optional[Dict[str, Any]] = None,
                      theme: str = "dark") -> str:
        """Export pattern as SVG

        Args:
            pattern: The pattern string to export
            metadata: Optional metadata for the pattern
            theme: Color theme ("dark", "light", or "color")

        Returns:
            SVG string representation
        """
        lines = pattern.split('\n')
        if not lines:
            return self._create_empty_svg()

        # Calculate dimensions
        max_line_length = max(len(line.rstrip()) for line in lines)
        width = max_line_length * self.char_width + 2 * self.padding
        height = len(lines) * self.line_height + 2 * self.padding

        # Create SVG
        svg_parts = [
            '<?xml version="1.0" encoding="UTF-8"?>',
            f'<svg width="{width}" height="{height}" xmlns="http://www.w3.org/2000/svg">',
            self._get_svg_styles(theme),
            f'<rect width="100%" height="100%" fill="{self._get_background_color(theme)}"/>'
        ]

        # Add pattern title if metadata available
        if metadata:
            title = metadata.get('display_name', 'Pattern')
            svg_parts.append(
                f'<text x="{self.padding}" y="{self.padding}" '
                f'font-family="{self.font_family}" font-size="{self.font_size}" '
                f'fill="{self._get_text_color(theme)}" font-weight="bold">{title}</text>'
            )

        # Add pattern content
        y_offset = self.padding + (self.line_height if metadata else 0)

        for i, line in enumerate(lines):
            y = y_offset + i * self.line_height
            self._add_line_to_svg(svg_parts, line, self.padding, y, theme)

        # Add metadata footer
        if metadata:
            footer_y = height - self.padding + self.font_size
            footer_text = f"Generated by {metadata.get('generator', 'Pattern Generator')} - {datetime.now().strftime('%Y-%m-%d %H:%M')}"
            svg_parts.append(
                f'<text x="{self.padding}" y="{footer_y}" '
                f'font-family="{self.font_family}" font-size="{self.font_size * 0.7}" '
                f'fill="{self._get_text_color(theme, alpha=0.7)}">{footer_text}</text>'
            )

        svg_parts.append('</svg>')

        return '\n'.join(svg_parts)

    def _add_line_to_svg(self, svg_parts: List[str], line: str, x: float, y: float, theme: str):
        """Add a line of text to SVG with syntax highlighting"""
        current_x = x

        # Process each character
        i = 0
        while i < len(line):
            char = line[i]

            # Check for number sequences
            if char.isdigit():
                # Collect consecutive digits
                num_start = i
                while i < len(line) and line[i].isdigit():
                    i += 1
                number = line[num_start:i]

                # Add number with special styling
                svg_parts.append(
                    f'<text x="{current_x}" y="{y}" '
                    f'font-family="{self.font_family}" font-size="{self.font_size}" '
                    f'fill="{self._get_number_color(theme)}" font-weight="bold">{number}</text>'
                )
                current_x += len(number) * self.char_width
            else:
                # Regular character
                color = self._get_symbol_color(char, theme)
                svg_parts.append(
                    f'<text x="{current_x}" y="{y}" '
                    f'font-family="{self.font_family}" font-size="{self.font_size}" '
                    f'fill="{color}">{char}</text>'
                )
                current_x += self.char_width
                i += 1

    def _get_svg_styles(self, theme: str) -> str:
        """Get SVG style definitions"""
        return f'''
        <defs>
            <style type="text/css">
                text {{
                    font-family: {self.font_family};
                    dominant-baseline: hanging;
                }}
            </style>
        </defs>
        '''

    def _get_background_color(self, theme: str) -> str:
        """Get background color for theme"""
        colors = {
            "dark": "#1a1a1a",
            "light": "#ffffff",
            "color": "#f8f9fa"
        }
        return colors.get(theme, "#1a1a1a")

    def _get_text_color(self, theme: str, alpha: float = 1.0) -> str:
        """Get text color for theme"""
        colors = {
            "dark": "#00ff41",
            "light": "#000000",
            "color": "#2c3e50"
        }
        base_color = colors.get(theme, "#00ff41")

        if alpha < 1.0:
            # Convert hex to rgba
            if base_color.startswith('#'):
                r = int(base_color[1:3], 16)
                g = int(base_color[3:5], 16)
                b = int(base_color[5:7], 16)
                return f"rgba({r}, {g}, {b}, {alpha})"

        return base_color

    def _get_number_color(self, theme: str) -> str:
        """Get color for numbers"""
        colors = {
            "dark": "#00ff41",
            "light": "#007bff",
            "color": "#e74c3c"
        }
        return colors.get(theme, "#00ff41")

    def _get_symbol_color(self, char: str, theme: str) -> str:
        """Get color for symbols based on character type"""
        if theme == "color":
            if char in ['+', '-', '*', '/', '=']:
                return "#27ae60"  # Math operators - green
            elif char in ['(', ')', '[', ']', '{', '}']:
                return "#f39c12"  # Brackets - orange
            elif char in ['|', '\\', '/']:
                return "#9b59b6"  # Lines - purple
            elif char in ['█', '▓', '▒', '░']:
                return "#e74c3c"  # Block characters - red
            else:
                return "#2c3e50"  # Default - dark blue

        # For dark/light themes, use consistent colors
        return self._get_text_color(theme)

    def export_animated_svg(self, frames: List[str], metadata: Optional[Dict[str, Any]] = None,
                           frame_duration: float = 0.5) -> str:
        """Export animated SVG with multiple frames

        Args:
            frames: List of pattern frames for animation
            metadata: Pattern metadata
            frame_duration: Duration between frames in seconds

        Returns:
            Animated SVG string
        """
        if not frames:
            return self._create_empty_svg()

        # Use first frame to calculate dimensions
        first_svg = self.export_pattern(frames[0], metadata)
        # Extract width and height from first SVG
        width_match = re.search(r'width="([^"]+)"', first_svg)
        height_match = re.search(r'height="([^"]+)"', first_svg)

        if not width_match or not height_match:
            return first_svg

        width = width_match.group(1)
        height = height_match.group(1)

        # Create animated SVG
        svg_parts = [
            '<?xml version="1.0" encoding="UTF-8"?>',
            f'<svg width="{width}" height="{height}" xmlns="http://www.w3.org/2000/svg">',
            '<defs>',
            f'<style type="text/css">',
            f'    text {{ font-family: {self.font_family}; dominant-baseline: hanging; }}',
            f'    .frame {{ display: none; }}',
            f'    .frame.active {{ display: block; }}',
            f'</style>',
            '</defs>',
            '<rect width="100%" height="100%" fill="#1a1a1a"/>'
        ]

        # Add all frames
        for i, frame in enumerate(frames):
            frame_svg = self.export_pattern(frame, None, "dark")
            # Extract just the text elements from frame SVG
            text_elements = re.findall(r'<text[^>]*>.*?</text>', frame_svg, re.DOTALL)
            frame_group = f'<g class="frame" id="frame-{i}">' + ''.join(text_elements) + '</g>'
            svg_parts.append(frame_group)

        # Add animation script
        total_duration = len(frames) * frame_duration
        svg_parts.append(f'''
        <script type="application/ecmascript">
        <![CDATA[
            var currentFrame = 0;
            var totalFrames = {len(frames)};
            var frameDuration = {frame_duration * 1000}; // Convert to milliseconds

            function showFrame(frameIndex) {{
                // Hide all frames
                for (var i = 0; i < totalFrames; i++) {{
                    var frame = document.getElementById('frame-' + i);
                    if (frame) {{
                        frame.classList.remove('active');
                    }}
                }}

                // Show current frame
                var currentFrameElement = document.getElementById('frame-' + frameIndex);
                if (currentFrameElement) {{
                    currentFrameElement.classList.add('active');
                }}
            }}

            function animate() {{
                showFrame(currentFrame);
                currentFrame = (currentFrame + 1) % totalFrames;
            }}

            // Start animation
            showFrame(0);
            setInterval(animate, frameDuration);
        ]]>
        </script>
        ''')

        svg_parts.append('</svg>')

        return '\n'.join(svg_parts)

    def _create_empty_svg(self) -> str:
        """Create empty SVG for error cases"""
        return '''<?xml version="1.0" encoding="UTF-8"?>
<svg width="400" height="200" xmlns="http://www.w3.org/2000/svg">
    <rect width="100%" height="100%" fill="#1a1a1a"/>
    <text x="20" y="50" font-family="monospace" font-size="16" fill="#00ff41">
        No pattern data available
    </text>
</svg>'''


class PDFExporter:
    """PDF export functionality (placeholder for future implementation)"""

    def __init__(self):
        """Initialize PDF exporter"""
        self.available = False
        try:
            import reportlab
            self.available = True
        except ImportError:
            pass

    def is_available(self) -> bool:
        """Check if PDF export is available"""
        return self.available

    def export_pattern(self, pattern: str, metadata: Optional[Dict[str, Any]] = None,
                      filename: str = "pattern.pdf") -> bool:
        """Export pattern as PDF (not implemented yet)"""
        if not self.available:
            raise ImportError("PDF export requires reportlab library")

        # TODO: Implement PDF export using reportlab
        raise NotImplementedError("PDF export not yet implemented")


# Global instances
svg_exporter = SVGExporter()
pdf_exporter = PDFExporter()


def export_pattern_svg(pattern: str, metadata: Optional[Dict[str, Any]] = None,
                      theme: str = "dark") -> str:
    """Convenience function to export pattern as SVG"""
    return svg_exporter.export_pattern(pattern, metadata, theme)


def export_animated_svg(frames: List[str], metadata: Optional[Dict[str, Any]] = None,
                       frame_duration: float = 0.5) -> str:
    """Convenience function to export animated SVG"""
    return svg_exporter.export_animated_svg(frames, metadata, frame_duration)


if __name__ == '__main__':
    print("Python Number Pattern Generator - SVG Export Module")
    print("=" * 60)
    print("Developed by Molla Samser (RSK World)")
    print("Designed by Rima Khatun")
    print("Website: https://rskworld.in")
    print("Year: 2026")
    print("=" * 60)

    # Example usage
    from patterns import PatternAlgorithms

    algorithms = PatternAlgorithms()

    # Generate a pattern
    pattern = algorithms.pyramid(4, 1)
    metadata = {
        'display_name': 'Pyramid Pattern',
        'generator': 'Pattern Generator',
        'size': 4,
        'start_num': 1
    }

    # Export as SVG
    svg_content = export_pattern_svg(pattern, metadata, theme="dark")

    # Save to file
    with open('example_pattern.svg', 'w', encoding='utf-8') as f:
        f.write(svg_content)

    print("✅ SVG export example saved to 'example_pattern.svg'")
    print("💡 Open the SVG file in a web browser to view the pattern")

    # Check PDF availability
    if pdf_exporter.is_available():
        print("📄 PDF export is available")
    else:
        print("📄 PDF export requires: pip install reportlab")

    print("\n🎨 SVG Features:")
    print("  • Scalable vector graphics")
    print("  • Multiple color themes (dark, light, color)")
    print("  • Syntax highlighting for numbers and symbols")
    print("  • Animated SVG support for pattern evolution")
    print("  • Metadata inclusion in exported files")
375 lines•13.4 KB
python

About RSK World

Founded by Molla Samser, with Designer & Tester Rima Khatun, RSK World is your one-stop destination for free programming resources, source code, and development tools.

Founder: Molla Samser
Designer & Tester: Rima Khatun

Development

  • Game Development
  • Web Development
  • Mobile Development
  • AI Development
  • Development Tools

Legal

  • Terms & Conditions
  • Privacy Policy
  • Disclaimer

Contact Info

Nutanhat, Mongolkote
Purba Burdwan, West Bengal
India, 713147

+91 93305 39277

hello@rskworld.in
support@rskworld.in

© 2026 RSK World. All rights reserved.

Content used for educational purposes only. View Disclaimer