awacke1 commited on
Commit
d5ec0f0
ยท
verified ยท
1 Parent(s): c99c131

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +66 -49
app.py CHANGED
@@ -10,7 +10,7 @@ from PIL import Image
10
  import fitz # PyMuPDF
11
 
12
  from reportlab.lib.pagesizes import A4
13
- from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, PageBreak
14
  from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
15
  from reportlab.lib import colors
16
  from reportlab.pdfbase import pdfmetrics
@@ -27,12 +27,18 @@ available_fonts = {
27
  "NotoEmoji SemiBold": "NotoEmoji-SemiBold.ttf"
28
  }
29
 
30
- # Sidebar: Let the user choose the NotoEmoji font.
31
- selected_font_name = st.sidebar.selectbox(
32
- "Select NotoEmoji Font",
33
- options=list(available_fonts.keys())
34
- )
35
- selected_font_path = available_fonts[selected_font_name]
 
 
 
 
 
 
36
 
37
  # Register the chosen emoji font with ReportLab.
38
  pdfmetrics.registerFont(TTFont(selected_font_name, selected_font_path))
@@ -216,7 +222,7 @@ default_markdown = """# ๐ŸŒŸ Deities Guide: Mythology and Moral Lessons ๐ŸŒŸ
216
  """
217
 
218
  # ---------------------------------------------------------------
219
- # Process markdown into a two-page layout based on line count.
220
  def markdown_to_pdf_content(markdown_text):
221
  lines = markdown_text.strip().split('\n')
222
  pdf_content = []
@@ -261,30 +267,31 @@ def markdown_to_pdf_content(markdown_text):
261
  if current_item and sub_items:
262
  pdf_content.append([current_item, sub_items])
263
 
264
- # Split based on line count, erring on left side longer.
265
  total_lines = sum(1 + len(subs) if isinstance(item, list) else 1 for item in pdf_content)
266
  target_lines = total_lines // 2
267
- page1_content = []
268
- page2_content = []
269
  current_lines = 0
270
 
271
  for item in pdf_content:
272
  line_count = 1 + (len(item[1]) if isinstance(item, list) else 0)
273
- if current_lines <= target_lines or len(page1_content) == 0:
274
- page1_content.append(item)
275
  current_lines += line_count
276
  else:
277
- page2_content.append(item)
278
 
279
- return page1_content, page2_content
280
 
281
  # ---------------------------------------------------------------
282
- # Create the PDF with two pages.
283
  def create_main_pdf(markdown_text, base_font_size=10, auto_size=False):
284
  buffer = io.BytesIO()
 
285
  doc = SimpleDocTemplate(
286
  buffer,
287
- pagesize=A4,
288
  leftMargin=36,
289
  rightMargin=36,
290
  topMargin=36,
@@ -294,16 +301,16 @@ def create_main_pdf(markdown_text, base_font_size=10, auto_size=False):
294
  styles = getSampleStyleSheet()
295
  story = []
296
  spacer_height = 10
297
- page1_content, page2_content = markdown_to_pdf_content(markdown_text)
298
 
299
- total_items = sum(1 + len(subs) if isinstance(item, list) else 1 for item in page1_content + page2_content)
300
  if auto_size:
301
- base_font_size = max(6, min(12, 400 / total_items)) # Adjusted for two pages.
302
 
303
  item_font_size = base_font_size
304
  subitem_font_size = base_font_size * 0.9
305
  section_font_size = base_font_size * 1.2
306
- title_font_size = min(16, base_font_size * 1.5)
307
 
308
  # Define ParagraphStyles using Helvetica for normal text.
309
  title_style = ParagraphStyle(
@@ -344,40 +351,59 @@ def create_main_pdf(markdown_text, base_font_size=10, auto_size=False):
344
  spaceAfter=1
345
  )
346
 
347
- # Page 1
348
  story.append(Paragraph(apply_emoji_font("Deities Guide: Mythology and Moral Lessons", selected_font_name), title_style))
349
  story.append(Spacer(1, spacer_height))
350
 
351
- for item in page1_content:
 
 
352
  if isinstance(item, str) and item.startswith('<b>'):
353
  text = item.replace('<b>', '').replace('</b>', '')
354
- story.append(Paragraph(apply_emoji_font(text, selected_font_name), section_style))
355
  elif isinstance(item, list):
356
  main_item, sub_items = item
357
- story.append(Paragraph(apply_emoji_font(main_item, selected_font_name), item_style))
358
  for sub_item in sub_items:
359
- story.append(Paragraph(apply_emoji_font(sub_item, selected_font_name), subitem_style))
360
  else:
361
- story.append(Paragraph(apply_emoji_font(item, selected_font_name), item_style))
362
 
363
- story.append(PageBreak()) # Explicitly move to Page 2.
364
-
365
- # Page 2
366
- story.append(Paragraph(apply_emoji_font("Deities Guide: Continued", selected_font_name), title_style))
367
- story.append(Spacer(1, spacer_height))
368
-
369
- for item in page2_content:
370
  if isinstance(item, str) and item.startswith('<b>'):
371
  text = item.replace('<b>', '').replace('</b>', '')
372
- story.append(Paragraph(apply_emoji_font(text, selected_font_name), section_style))
373
  elif isinstance(item, list):
374
  main_item, sub_items = item
375
- story.append(Paragraph(apply_emoji_font(main_item, selected_font_name), item_style))
376
  for sub_item in sub_items:
377
- story.append(Paragraph(apply_emoji_font(sub_item, selected_font_name), subitem_style))
378
  else:
379
- story.append(Paragraph(apply_emoji_font(item, selected_font_name), item_style))
 
 
 
 
 
380
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
381
  doc.build(story)
382
  buffer.seek(0)
383
  return buffer.getvalue()
@@ -399,15 +425,6 @@ def pdf_to_image(pdf_bytes):
399
  return None
400
 
401
  # ---------------------------------------------------------------
402
- # Sidebar options for text size.
403
- with st.sidebar:
404
- auto_size = st.checkbox("Auto-size text", value=True)
405
- if not auto_size:
406
- base_font_size = st.slider("Base Font Size (points)", min_value=6, max_value=16, value=10, step=1)
407
- else:
408
- base_font_size = 10
409
- st.info("Font size will auto-adjust between 6-12 points based on content length.")
410
-
411
  # Persist markdown content in session state.
412
  if 'markdown_content' not in st.session_state:
413
  st.session_state.markdown_content = default_markdown
@@ -422,7 +439,7 @@ with st.container():
422
  pdf_images = pdf_to_image(pdf_bytes)
423
  if pdf_images:
424
  for i, img in enumerate(pdf_images):
425
- st.image(img, caption=f"Page {i+1}", use_container_width=True)
426
  else:
427
  st.info("Download the PDF to view it locally.")
428
 
@@ -430,7 +447,7 @@ with st.container():
430
  st.download_button(
431
  label="Download PDF",
432
  data=pdf_bytes,
433
- file_name="deities_guide.pdf",
434
  mime="application/pdf"
435
  )
436
 
 
10
  import fitz # PyMuPDF
11
 
12
  from reportlab.lib.pagesizes import A4
13
+ from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle
14
  from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
15
  from reportlab.lib import colors
16
  from reportlab.pdfbase import pdfmetrics
 
27
  "NotoEmoji SemiBold": "NotoEmoji-SemiBold.ttf"
28
  }
29
 
30
+ # Sidebar: Font selection and size adjustment.
31
+ with st.sidebar:
32
+ selected_font_name = st.selectbox(
33
+ "Select NotoEmoji Font",
34
+ options=list(available_fonts.keys())
35
+ )
36
+ selected_font_path = available_fonts[selected_font_name]
37
+
38
+ auto_size = st.checkbox("Auto-size text", value=True)
39
+ base_font_size = st.slider("Base Font Size (points)", min_value=6, max_value=16, value=10, step=1)
40
+ if auto_size:
41
+ st.info("Font size will adjust between 6-16 points based on content length, starting from your base size.")
42
 
43
  # Register the chosen emoji font with ReportLab.
44
  pdfmetrics.registerFont(TTFont(selected_font_name, selected_font_path))
 
222
  """
223
 
224
  # ---------------------------------------------------------------
225
+ # Process markdown into a two-column layout for a double-page spread.
226
  def markdown_to_pdf_content(markdown_text):
227
  lines = markdown_text.strip().split('\n')
228
  pdf_content = []
 
267
  if current_item and sub_items:
268
  pdf_content.append([current_item, sub_items])
269
 
270
+ # Split into two columns (left and right) based on line count.
271
  total_lines = sum(1 + len(subs) if isinstance(item, list) else 1 for item in pdf_content)
272
  target_lines = total_lines // 2
273
+ left_column = []
274
+ right_column = []
275
  current_lines = 0
276
 
277
  for item in pdf_content:
278
  line_count = 1 + (len(item[1]) if isinstance(item, list) else 0)
279
+ if current_lines < target_lines or len(left_column) == 0:
280
+ left_column.append(item)
281
  current_lines += line_count
282
  else:
283
+ right_column.append(item)
284
 
285
+ return left_column, right_column
286
 
287
  # ---------------------------------------------------------------
288
+ # Create the PDF as a double-page spread.
289
  def create_main_pdf(markdown_text, base_font_size=10, auto_size=False):
290
  buffer = io.BytesIO()
291
+ # Double-page spread: Two A4 pages side-by-side (landscape).
292
  doc = SimpleDocTemplate(
293
  buffer,
294
+ pagesize=(A4[1] * 2, A4[0]), # Width = 2 * A4 width, Height = A4 height
295
  leftMargin=36,
296
  rightMargin=36,
297
  topMargin=36,
 
301
  styles = getSampleStyleSheet()
302
  story = []
303
  spacer_height = 10
304
+ left_column, right_column = markdown_to_pdf_content(markdown_text)
305
 
306
+ total_items = sum(1 + len(subs) if isinstance(item, list) else 1 for item in left_column + right_column)
307
  if auto_size:
308
+ base_font_size = max(6, min(16, base_font_size * 200 / total_items)) # Scale based on userโ€™s base size.
309
 
310
  item_font_size = base_font_size
311
  subitem_font_size = base_font_size * 0.9
312
  section_font_size = base_font_size * 1.2
313
+ title_font_size = min(20, base_font_size * 1.5)
314
 
315
  # Define ParagraphStyles using Helvetica for normal text.
316
  title_style = ParagraphStyle(
 
351
  spaceAfter=1
352
  )
353
 
354
+ # Title spanning both columns.
355
  story.append(Paragraph(apply_emoji_font("Deities Guide: Mythology and Moral Lessons", selected_font_name), title_style))
356
  story.append(Spacer(1, spacer_height))
357
 
358
+ # Prepare two-column layout.
359
+ left_cells = []
360
+ for item in left_column:
361
  if isinstance(item, str) and item.startswith('<b>'):
362
  text = item.replace('<b>', '').replace('</b>', '')
363
+ left_cells.append(Paragraph(apply_emoji_font(text, selected_font_name), section_style))
364
  elif isinstance(item, list):
365
  main_item, sub_items = item
366
+ left_cells.append(Paragraph(apply_emoji_font(main_item, selected_font_name), item_style))
367
  for sub_item in sub_items:
368
+ left_cells.append(Paragraph(apply_emoji_font(sub_item, selected_font_name), subitem_style))
369
  else:
370
+ left_cells.append(Paragraph(apply_emoji_font(item, selected_font_name), item_style))
371
 
372
+ right_cells = []
373
+ for item in right_column:
 
 
 
 
 
374
  if isinstance(item, str) and item.startswith('<b>'):
375
  text = item.replace('<b>', '').replace('</b>', '')
376
+ right_cells.append(Paragraph(apply_emoji_font(text, selected_font_name), section_style))
377
  elif isinstance(item, list):
378
  main_item, sub_items = item
379
+ right_cells.append(Paragraph(apply_emoji_font(main_item, selected_font_name), item_style))
380
  for sub_item in sub_items:
381
+ right_cells.append(Paragraph(apply_emoji_font(sub_item, selected_font_name), subitem_style))
382
  else:
383
+ right_cells.append(Paragraph(apply_emoji_font(item, selected_font_name), item_style))
384
+
385
+ # Balance the columns by padding with empty strings.
386
+ max_cells = max(len(left_cells), len(right_cells))
387
+ left_cells.extend([""] * (max_cells - len(left_cells)))
388
+ right_cells.extend([""] * (max_cells - len(right_cells)))
389
 
390
+ # Create a table for the double-page spread.
391
+ table_data = list(zip(left_cells, right_cells))
392
+ col_width = (A4[1] - 36) # Half the spread width minus margins.
393
+ table = Table(table_data, colWidths=[col_width, col_width], hAlign='CENTER')
394
+ table.setStyle(TableStyle([
395
+ ('VALIGN', (0, 0), (-1, -1), 'TOP'),
396
+ ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
397
+ ('BACKGROUND', (0, 0), (-1, -1), colors.white),
398
+ ('GRID', (0, 0), (-1, -1), 0, colors.white),
399
+ ('LINEAFTER', (0, 0), (0, -1), 0.5, colors.grey), # Divider between columns.
400
+ ('LEFTPADDING', (0, 0), (-1, -1), 2),
401
+ ('RIGHTPADDING', (0, 0), (-1, -1), 2),
402
+ ('TOPPADDING', (0, 0), (-1, -1), 1),
403
+ ('BOTTOMPADDING', (0, 0), (-1, -1), 1),
404
+ ]))
405
+
406
+ story.append(table)
407
  doc.build(story)
408
  buffer.seek(0)
409
  return buffer.getvalue()
 
425
  return None
426
 
427
  # ---------------------------------------------------------------
 
 
 
 
 
 
 
 
 
428
  # Persist markdown content in session state.
429
  if 'markdown_content' not in st.session_state:
430
  st.session_state.markdown_content = default_markdown
 
439
  pdf_images = pdf_to_image(pdf_bytes)
440
  if pdf_images:
441
  for i, img in enumerate(pdf_images):
442
+ st.image(img, caption=f"Double-Page Spread", use_container_width=True)
443
  else:
444
  st.info("Download the PDF to view it locally.")
445
 
 
447
  st.download_button(
448
  label="Download PDF",
449
  data=pdf_bytes,
450
+ file_name="deities_guide_double_page.pdf",
451
  mime="application/pdf"
452
  )
453