Reaperxxxx commited on
Commit
2008433
·
verified ·
1 Parent(s): 1912621

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +134 -68
app.py CHANGED
@@ -105,32 +105,64 @@ class TelegramChatGenerator:
105
  """Draw bubble with shadow and gradient effect"""
106
  x1, y1, x2, y2 = coords
107
 
108
- # Draw shadow first
109
- shadow_coords = (x1 + shadow_offset, y1 + shadow_offset,
110
- x2 + shadow_offset, y2 + shadow_offset)
111
- self.draw_rounded_rectangle(draw, shadow_coords, radius, (0, 0, 0, 30))
 
 
 
 
 
 
 
 
 
 
112
 
113
  # Draw main bubble
114
- self.draw_rounded_rectangle(draw, coords, radius, fill)
115
 
116
- # Add subtle highlight
117
- highlight_coords = (x1, y1, x2, y1 + 2)
118
- lighter_fill = tuple(min(255, c + 20) for c in fill)
119
- self.draw_rounded_rectangle(draw, highlight_coords, radius, lighter_fill)
 
120
 
121
  def draw_rounded_rectangle(self, draw, coords, radius, fill):
122
- """Draw a perfect rounded rectangle"""
123
  x1, y1, x2, y2 = coords
124
 
125
- # Main rectangles
126
- draw.rectangle([x1 + radius, y1, x2 - radius, y2], fill=fill)
127
- draw.rectangle([x1, y1 + radius, x2, y2 - radius], fill=fill)
128
-
129
- # Corner circles
130
- draw.ellipse([x1, y1, x1 + 2 * radius, y1 + 2 * radius], fill=fill)
131
- draw.ellipse([x2 - 2 * radius, y1, x2, y1 + 2 * radius], fill=fill)
132
- draw.ellipse([x1, y2 - 2 * radius, x1 + 2 * radius, y2], fill=fill)
133
- draw.ellipse([x2 - 2 * radius, y2 - 2 * radius, x2, y2], fill=fill)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
 
135
  def get_text_dimensions(self, text, font):
136
  """Get accurate text dimensions"""
@@ -177,6 +209,10 @@ class TelegramChatGenerator:
177
  padding = 50
178
  max_bubble_width = self.image_size - (padding * 2) - 60
179
 
 
 
 
 
180
  # Wrap text intelligently
181
  wrapped_message = self.wrap_text(message, self.font, max_bubble_width - 60)
182
  msg_width, msg_height = self.get_text_dimensions(wrapped_message, self.font)
@@ -194,88 +230,118 @@ class TelegramChatGenerator:
194
  reply_msg_w, reply_msg_h = self.get_text_dimensions(wrapped_reply, self.reply_font)
195
  reply_height = reply_username_h + reply_msg_h + 25
196
 
197
- # Calculate total bubble dimensions
198
  bubble_padding = 25
199
- bubble_width = min(max_bubble_width, max(350, msg_width + bubble_padding * 2))
200
- bubble_height = username_height + msg_height + bubble_padding * 2 + 30
 
201
 
202
  if reply_to:
203
  bubble_height += reply_height + 15
204
 
 
 
 
 
 
 
205
  # Center the bubble vertically in the square
206
- bubble_x = self.image_size - bubble_width - padding
207
- bubble_y = (self.image_size - bubble_height) // 2
 
 
 
 
 
 
208
 
209
  # Draw main bubble with shadow
210
- self.draw_advanced_bubble(
211
- draw,
212
- [bubble_x, bubble_y, bubble_x + bubble_width, bubble_y + bubble_height],
213
- radius=20,
214
- fill=self.bubble_color,
215
- shadow_offset=4
216
- )
 
217
 
218
  # Current position for content
219
  content_y = bubble_y + bubble_padding
220
 
221
  # Draw reply section if present
222
- if reply_to and replied_username:
223
  reply_y = content_y
224
- reply_bubble_height = reply_height + 10
225
 
226
- # Reply background
227
- self.draw_rounded_rectangle(
228
- draw,
229
- [bubble_x + 15, reply_y, bubble_x + bubble_width - 15, reply_y + reply_bubble_height],
230
- radius=12,
231
- fill=self.reply_bubble_color
232
- )
233
-
234
- # Blue accent line
235
- draw.rectangle([bubble_x + 20, reply_y + 5, bubble_x + 24, reply_y + reply_bubble_height - 5],
236
- fill=self.reply_line_color)
237
-
238
- # Reply content
239
- reply_content_x = bubble_x + 35
240
- reply_content_y = reply_y + 8
241
 
242
- # Reply username
243
- draw.text((reply_content_x, reply_content_y), replied_username,
244
- fill=self.reply_line_color, font=self.reply_font)
245
- reply_content_y += 20
246
-
247
- # Reply message
248
- for line in wrapped_reply.split('\n'):
249
- draw.text((reply_content_x, reply_content_y), line,
250
- fill=self.reply_text_color, font=self.reply_font)
251
- reply_content_y += 20
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
252
 
253
  content_y += reply_bubble_height + 15
254
 
255
  # Main message username
256
- draw.text((bubble_x + bubble_padding, content_y), username,
257
- fill=self.username_color, font=self.username_font)
258
- content_y += username_height + 10
 
259
 
260
  # Main message text with better spacing
261
  for line in wrapped_message.split('\n'):
262
- draw.text((bubble_x + bubble_padding, content_y), line,
263
- fill=self.text_color, font=self.font)
264
- content_y += 28
 
265
 
266
  # Add timestamp
267
  current_time = datetime.now().strftime("%H:%M")
268
  time_bbox = self.time_font.getbbox(current_time)
269
  time_width = time_bbox[2] - time_bbox[0]
270
 
271
- draw.text((bubble_x + bubble_width - time_width - bubble_padding,
272
- bubble_y + bubble_height - 25),
273
- current_time, fill=self.time_color, font=self.time_font)
 
 
 
274
 
275
  # Add checkmark (delivered status)
276
  check_x = bubble_x + bubble_width - 25
277
  check_y = bubble_y + bubble_height - 22
278
- self.draw_checkmarks(draw, check_x, check_y)
 
 
279
 
280
  return img
281
 
 
105
  """Draw bubble with shadow and gradient effect"""
106
  x1, y1, x2, y2 = coords
107
 
108
+ # Ensure coordinates are valid
109
+ if x2 <= x1 or y2 <= y1:
110
+ return
111
+
112
+ # Ensure radius doesn't exceed bubble dimensions
113
+ max_radius = min((x2 - x1) // 2, (y2 - y1) // 2, radius)
114
+ if max_radius < 1:
115
+ max_radius = 1
116
+
117
+ # Draw shadow first (with bounds check)
118
+ if shadow_offset > 0:
119
+ shadow_coords = (x1 + shadow_offset, y1 + shadow_offset,
120
+ x2 + shadow_offset, y2 + shadow_offset)
121
+ self.draw_rounded_rectangle(draw, shadow_coords, max_radius, (0, 0, 0, 30))
122
 
123
  # Draw main bubble
124
+ self.draw_rounded_rectangle(draw, coords, max_radius, fill)
125
 
126
+ # Add subtle highlight (only if bubble is tall enough)
127
+ if y2 - y1 > 4:
128
+ highlight_coords = (x1, y1, x2, y1 + 2)
129
+ lighter_fill = tuple(min(255, c + 20) for c in fill)
130
+ self.draw_rounded_rectangle(draw, highlight_coords, max_radius, lighter_fill)
131
 
132
  def draw_rounded_rectangle(self, draw, coords, radius, fill):
133
+ """Draw a perfect rounded rectangle with bounds checking"""
134
  x1, y1, x2, y2 = coords
135
 
136
+ # Ensure coordinates are valid
137
+ if x2 <= x1 or y2 <= y1:
138
+ return
139
+
140
+ # Limit radius to prevent invalid coordinates
141
+ width = x2 - x1
142
+ height = y2 - y1
143
+ max_radius = min(width // 2, height // 2, radius)
144
+
145
+ if max_radius < 1:
146
+ # If radius is too small, just draw a regular rectangle
147
+ draw.rectangle([x1, y1, x2, y2], fill=fill)
148
+ return
149
+
150
+ # Main rectangles (only if they have positive dimensions)
151
+ if width > 2 * max_radius:
152
+ draw.rectangle([x1 + max_radius, y1, x2 - max_radius, y2], fill=fill)
153
+ if height > 2 * max_radius:
154
+ draw.rectangle([x1, y1 + max_radius, x2, y2 - max_radius], fill=fill)
155
+
156
+ # Corner circles (only if there's space for them)
157
+ if width >= 2 * max_radius and height >= 2 * max_radius:
158
+ # Top-left
159
+ draw.ellipse([x1, y1, x1 + 2 * max_radius, y1 + 2 * max_radius], fill=fill)
160
+ # Top-right
161
+ draw.ellipse([x2 - 2 * max_radius, y1, x2, y1 + 2 * max_radius], fill=fill)
162
+ # Bottom-left
163
+ draw.ellipse([x1, y2 - 2 * max_radius, x1 + 2 * max_radius, y2], fill=fill)
164
+ # Bottom-right
165
+ draw.ellipse([x2 - 2 * max_radius, y2 - 2 * max_radius, x2, y2], fill=fill)
166
 
167
  def get_text_dimensions(self, text, font):
168
  """Get accurate text dimensions"""
 
209
  padding = 50
210
  max_bubble_width = self.image_size - (padding * 2) - 60
211
 
212
+ # Ensure minimum dimensions
213
+ if max_bubble_width < 200:
214
+ max_bubble_width = 200
215
+
216
  # Wrap text intelligently
217
  wrapped_message = self.wrap_text(message, self.font, max_bubble_width - 60)
218
  msg_width, msg_height = self.get_text_dimensions(wrapped_message, self.font)
 
230
  reply_msg_w, reply_msg_h = self.get_text_dimensions(wrapped_reply, self.reply_font)
231
  reply_height = reply_username_h + reply_msg_h + 25
232
 
233
+ # Calculate total bubble dimensions with minimums
234
  bubble_padding = 25
235
+ min_bubble_width = 300
236
+ bubble_width = max(min_bubble_width, min(max_bubble_width, msg_width + bubble_padding * 2))
237
+ bubble_height = max(80, username_height + msg_height + bubble_padding * 2 + 50)
238
 
239
  if reply_to:
240
  bubble_height += reply_height + 15
241
 
242
+ # Ensure bubble fits in canvas
243
+ if bubble_width > self.image_size - padding:
244
+ bubble_width = self.image_size - padding
245
+ if bubble_height > self.image_size - padding:
246
+ bubble_height = self.image_size - padding
247
+
248
  # Center the bubble vertically in the square
249
+ bubble_x = max(padding, self.image_size - bubble_width - padding)
250
+ bubble_y = max(padding, (self.image_size - bubble_height) // 2)
251
+
252
+ # Ensure bubble coordinates are valid
253
+ if bubble_x + bubble_width > self.image_size:
254
+ bubble_x = self.image_size - bubble_width - 10
255
+ if bubble_y + bubble_height > self.image_size:
256
+ bubble_y = self.image_size - bubble_height - 10
257
 
258
  # Draw main bubble with shadow
259
+ if bubble_width > 0 and bubble_height > 0:
260
+ self.draw_advanced_bubble(
261
+ draw,
262
+ [bubble_x, bubble_y, bubble_x + bubble_width, bubble_y + bubble_height],
263
+ radius=20,
264
+ fill=self.bubble_color,
265
+ shadow_offset=4
266
+ )
267
 
268
  # Current position for content
269
  content_y = bubble_y + bubble_padding
270
 
271
  # Draw reply section if present
272
+ if reply_to and replied_username and bubble_width > 60:
273
  reply_y = content_y
274
+ reply_bubble_height = max(30, reply_height + 10)
275
 
276
+ # Reply background (with bounds checking)
277
+ reply_bubble_x1 = bubble_x + 15
278
+ reply_bubble_x2 = bubble_x + bubble_width - 15
279
+ reply_bubble_y1 = reply_y
280
+ reply_bubble_y2 = reply_y + reply_bubble_height
 
 
 
 
 
 
 
 
 
 
281
 
282
+ if reply_bubble_x2 > reply_bubble_x1 and reply_bubble_y2 > reply_bubble_y1:
283
+ self.draw_rounded_rectangle(
284
+ draw,
285
+ [reply_bubble_x1, reply_bubble_y1, reply_bubble_x2, reply_bubble_y2],
286
+ radius=12,
287
+ fill=self.reply_bubble_color
288
+ )
289
+
290
+ # Blue accent line
291
+ if reply_bubble_height > 10:
292
+ draw.rectangle([bubble_x + 20, reply_y + 5, bubble_x + 24, reply_y + reply_bubble_height - 5],
293
+ fill=self.reply_line_color)
294
+
295
+ # Reply content
296
+ reply_content_x = bubble_x + 35
297
+ reply_content_y = reply_y + 8
298
+
299
+ # Reply username
300
+ if reply_content_x < bubble_x + bubble_width - 20:
301
+ draw.text((reply_content_x, reply_content_y), replied_username,
302
+ fill=self.reply_line_color, font=self.reply_font)
303
+ reply_content_y += 20
304
+
305
+ # Reply message
306
+ for line in wrapped_reply.split('\n'):
307
+ if reply_content_y < bubble_y + bubble_height - 30:
308
+ draw.text((reply_content_x, reply_content_y), line,
309
+ fill=self.reply_text_color, font=self.reply_font)
310
+ reply_content_y += 20
311
 
312
  content_y += reply_bubble_height + 15
313
 
314
  # Main message username
315
+ if content_y < bubble_y + bubble_height - 50:
316
+ draw.text((bubble_x + bubble_padding, content_y), username,
317
+ fill=self.username_color, font=self.username_font)
318
+ content_y += username_height + 10
319
 
320
  # Main message text with better spacing
321
  for line in wrapped_message.split('\n'):
322
+ if content_y < bubble_y + bubble_height - 40:
323
+ draw.text((bubble_x + bubble_padding, content_y), line,
324
+ fill=self.text_color, font=self.font)
325
+ content_y += 28
326
 
327
  # Add timestamp
328
  current_time = datetime.now().strftime("%H:%M")
329
  time_bbox = self.time_font.getbbox(current_time)
330
  time_width = time_bbox[2] - time_bbox[0]
331
 
332
+ timestamp_x = bubble_x + bubble_width - time_width - bubble_padding
333
+ timestamp_y = bubble_y + bubble_height - 25
334
+
335
+ if timestamp_x > bubble_x and timestamp_y > bubble_y:
336
+ draw.text((timestamp_x, timestamp_y),
337
+ current_time, fill=self.time_color, font=self.time_font)
338
 
339
  # Add checkmark (delivered status)
340
  check_x = bubble_x + bubble_width - 25
341
  check_y = bubble_y + bubble_height - 22
342
+
343
+ if check_x > bubble_x and check_y > bubble_y:
344
+ self.draw_checkmarks(draw, check_x, check_y)
345
 
346
  return img
347