File size: 6,564 Bytes
83e35a7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
"""
PDF Generator for Edited Comics
Generates PDF from comic with user edits preserved
"""

import os
from reportlab.lib.pagesizes import A4
from reportlab.pdfgen import canvas
from reportlab.lib.utils import ImageReader
from PIL import Image, ImageDraw, ImageFont
import json

class ComicPDFGenerator:
    """Generate PDF from edited comic data"""
    
    def __init__(self):
        self.page_width = A4[0]
        self.page_height = A4[1]
        self.margin = 20
        
    def generate_pdf(self, pages_data, edited_bubbles, output_path="output/comic_edited.pdf"):
        """
        Generate PDF with edited text and positions
        
        Args:
            pages_data: Original comic pages data
            edited_bubbles: List of edited bubble data (text, position)
            output_path: Output PDF path
        """
        
        # Create PDF
        c = canvas.Canvas(output_path, pagesize=A4)
        
        bubble_index = 0
        
        for page_num, page in enumerate(pages_data):
            if page_num > 0:
                c.showPage()
            
            # Add page title
            c.setFont("Helvetica-Bold", 16)
            c.drawString(self.margin, self.page_height - 30, f"Page {page_num + 1}")
            
            # Calculate panel layout
            panels_per_page = len(page['panels'])
            if panels_per_page <= 4:
                cols, rows = 2, 2
            else:
                cols, rows = 3, 2
            
            panel_width = (self.page_width - self.margin * 2 - 10 * (cols - 1)) / cols
            panel_height = (self.page_height - 100 - 10 * (rows - 1)) / rows
            
            # Draw panels
            for i, panel in enumerate(page['panels']):
                row = i // cols
                col = i % cols
                
                x = self.margin + col * (panel_width + 10)
                y = self.page_height - 60 - (row + 1) * (panel_height + 10)
                
                # Draw panel image
                img_path = os.path.join('frames/final', panel['image'])
                if os.path.exists(img_path):
                    img = Image.open(img_path)
                    img_reader = ImageReader(img)
                    c.drawImage(img_reader, x, y, width=panel_width, height=panel_height, preserveAspectRatio=True)
                
                # Draw border
                c.setStrokeColorRGB(0, 0, 0)
                c.setLineWidth(2)
                c.rect(x, y, panel_width, panel_height)
                
                # Draw bubbles for this panel
                for bubble in page.get('bubbles', []):
                    if bubble_index < len(edited_bubbles):
                        edited_bubble = edited_bubbles[bubble_index]
                        
                        # Use edited text and position
                        text = edited_bubble.get('text', bubble['dialog'])
                        
                        # Calculate bubble position
                        if edited_bubble.get('left') and edited_bubble.get('top'):
                            # Convert CSS position to PDF coordinates
                            bubble_x = x + self._parse_position(edited_bubble['left'], panel_width)
                            bubble_y = y + panel_height - self._parse_position(edited_bubble['top'], panel_height) - 30
                        else:
                            # Use default position
                            bubble_x = x + bubble['bubble_offset_x']
                            bubble_y = y + panel_height - bubble['bubble_offset_y'] - 30
                        
                        # Draw speech bubble
                        self._draw_speech_bubble(c, bubble_x, bubble_y, text)
                        
                    bubble_index += 1
        
        # Save PDF
        c.save()
        return output_path
    
    def _parse_position(self, css_value, max_value):
        """Convert CSS position (e.g., '50px') to numeric value"""
        if isinstance(css_value, str) and css_value.endswith('px'):
            return float(css_value[:-2])
        return 0
    
    def _draw_speech_bubble(self, canvas, x, y, text):
        """Draw a speech bubble with text"""
        # Measure text
        canvas.setFont("Helvetica-Bold", 10)
        text_width = canvas.stringWidth(text, "Helvetica-Bold", 10)
        
        # Wrap text if needed
        words = text.split()
        lines = []
        current_line = []
        max_width = 150
        
        for word in words:
            test_line = ' '.join(current_line + [word])
            if canvas.stringWidth(test_line, "Helvetica-Bold", 10) > max_width:
                if current_line:
                    lines.append(' '.join(current_line))
                    current_line = [word]
                else:
                    lines.append(word)
            else:
                current_line.append(word)
        
        if current_line:
            lines.append(' '.join(current_line))
        
        # Calculate bubble size
        bubble_width = min(max_width + 20, 180)
        bubble_height = len(lines) * 15 + 20
        
        # Draw bubble background
        canvas.setFillColorRGB(1, 1, 1)
        canvas.setStrokeColorRGB(0, 0, 0)
        canvas.setLineWidth(2)
        
        # Rounded rectangle for bubble
        canvas.roundRect(x, y, bubble_width, bubble_height, 10, fill=1, stroke=1)
        
        # Draw text
        canvas.setFillColorRGB(0, 0, 0)
        text_y = y + bubble_height - 15
        for line in lines:
            canvas.drawString(x + 10, text_y, line)
            text_y -= 15
    
    def generate_from_html(self, html_path, edited_data, output_path="output/comic_edited.pdf"):
        """
        Alternative: Generate PDF from edited HTML
        This would require parsing the HTML and extracting positions
        """
        # This is a placeholder for HTML-based PDF generation
        # In practice, you might use tools like wkhtmltopdf or Playwright
        pass


def generate_edited_pdf(request_data):
    """
    Generate PDF from edit request
    
    Args:
        request_data: Dict with edited bubble data
    """
    generator = ComicPDFGenerator()
    
    # Load original pages data
    with open('output/pages.json', 'r') as f:
        pages_data = json.load(f)
    
    # Get edited bubbles
    edited_bubbles = request_data.get('bubbles', [])
    
    # Generate PDF
    output_path = generator.generate_pdf(pages_data, edited_bubbles)
    
    return output_path