128 lines
10 KiB
Python
128 lines
10 KiB
Python
from reportlab.pdfgen import canvas
|
||
from reportlab.lib.colors import HexColor, Color
|
||
from reportlab.pdfbase import pdfmetrics
|
||
from reportlab.pdfbase.ttfonts import TTFont
|
||
from reportlab.lib.utils import simpleSplit
|
||
from reportlab.lib.pagesizes import landscape
|
||
from reportlab.lib.units import inch
|
||
from pathlib import Path
|
||
|
||
OUT=Path('/Users/adolforeyna/brain/exports/emi_latin_america_redesign.pdf')
|
||
W,H=1280,720
|
||
BG=HexColor('#F5F1E8'); INK=HexColor('#17352C'); GREEN=HexColor('#315D48'); MOSS=HexColor('#A7B6A0'); GOLD=HexColor('#C9984D'); CLAY=HexColor('#B9684D'); WHITE=HexColor('#FFFEFA'); PALE=HexColor('#E8E1D4'); MUTED=HexColor('#596C60')
|
||
for n,p in [('Editorial','/System/Library/Fonts/Supplemental/Georgia.ttf'),('Sans','/System/Library/Fonts/Supplemental/Arial.ttf'),('SansB','/System/Library/Fonts/Supplemental/Arial Bold.ttf')]: pdfmetrics.registerFont(TTFont(n,p))
|
||
c=canvas.Canvas(str(OUT),pagesize=(W,H),pageCompression=1); c.setTitle('EMI — A Shared Vision for Latin America'); c.setAuthor('EMI · based on Vision for Latin America')
|
||
def rect(x,y,w,h,fill,stroke=None,r=0):
|
||
c.setFillColor(fill); c.setStrokeColor(stroke or fill)
|
||
if r: c.roundRect(x,y,w,h,r,fill=1,stroke=bool(stroke))
|
||
else: c.rect(x,y,w,h,fill=1,stroke=bool(stroke))
|
||
def text(s,x,y,size=18,font='Sans',color=INK): c.setFillColor(color); c.setFont(font,size); c.drawString(x,y,s)
|
||
def para(s,x,y,w,size=18,lead=27,font='Sans',color=MUTED):
|
||
c.setFillColor(color); c.setFont(font,size)
|
||
for ln in simpleSplit(s,font,size,w): c.drawString(x,y,ln); y-=lead
|
||
return y
|
||
def line(x,y,x2,y2,col=GOLD,sw=2): c.setStrokeColor(col); c.setLineWidth(sw); c.line(x,y,x2,y2)
|
||
def circle(x,y,r,col): c.setFillColor(col); c.circle(x,y,r,fill=1,stroke=0)
|
||
def base(n,section,dark=False):
|
||
c.setFillColor(INK if dark else BG); c.rect(0,0,W,H,fill=1,stroke=0)
|
||
text('EMI / LATIN AMERICA',54,34,11,'SansB',GOLD if dark else GREEN)
|
||
text(f'{section.upper()} · {n:02d} / 08',W-275,34,10,'SansB',HexColor('#D7DED6') if dark else MUTED)
|
||
|
||
def title(kicker,head,sub=None,y=605,w=930,dark=False):
|
||
text(kicker.upper(),58,y,13,'SansB',GOLD if dark else GREEN)
|
||
text(head,55,y-67,42,'Editorial',WHITE if dark else INK)
|
||
if sub: para(sub,60,y-104,w,18,26,'Sans',HexColor('#D7DED6') if dark else MUTED)
|
||
# 1 Cover
|
||
base(1,'The call',True)
|
||
# sunlit layered landscape motif, no abstract spheres
|
||
for i,col in enumerate([HexColor('#24483A'),HexColor('#315D48'),HexColor('#59785B')]):
|
||
y=60+i*65; c.setFillColor(col); p=c.beginPath(); p.moveTo(0,y); p.curveTo(190,y+120,310,y-35,510,y+35); p.curveTo(720,y+125,850,y-55,1055,y+80); p.curveTo(1140,y+130,1210,y+10,1280,y+85); p.lineTo(1280,0); p.lineTo(0,0); p.close(); c.drawPath(p,fill=1,stroke=0)
|
||
text('EMI · A SHARED REGIONAL CALL',65,638,13,'SansB',GOLD)
|
||
text('A vision for',60,518,72,'Editorial',WHITE); text('Latin America',60,434,72,'Editorial',WHITE)
|
||
para('One spiritual family, moving together to establish lasting expressions of the Kingdom of God.',67,365,640,23,33,'Sans',HexColor('#E8E4D9'))
|
||
line(68,255,178,255,GOLD,4); text('“Go and make disciples of all nations.”',67,213,25,'Editorial',HexColor('#F2D69A')); text('MATTHEW 28:18–20',69,177,12,'SansB',HexColor('#D7DED6'))
|
||
c.showPage()
|
||
# 2 clear vision/mission
|
||
base(2,'Direction')
|
||
title('01 · Direction','One destination. One shared way.','The vision names what God desires to establish; the mission describes how the regional family carries it forward.',650,1030)
|
||
rect(60,285,540,178,WHITE,r=18); rect(60,451,540,12,GREEN)
|
||
text('THE VISION / WHAT',90,411,14,'SansB',GREEN); text('Kingdom & family',88,357,37,'Editorial',INK)
|
||
para('Established among every ethnos—every nation, people, and people group.',91,322,455,18,27)
|
||
rect(635,285,585,178,WHITE,r=18); rect(635,451,585,12,CLAY)
|
||
text('THE MISSION / HOW',665,411,14,'SansB',CLAY); text('A family at work',663,357,37,'Editorial',INK)
|
||
para('Discipling, serving, raising leaders, sharing resources, and building works that last.',666,322,485,18,27)
|
||
text('Not a program to run. A people to become—and a mission to carry together.',65,220,24,'Editorial',GREEN)
|
||
text('Rooted in Matthew 28:18–20',66,174,14,'SansB',MUTED)
|
||
c.showPage()
|
||
# 3 collective responsibility
|
||
base(3,'Ownership')
|
||
title('02 · Ownership','The mandate belongs to the family.','Local assignments remain distinct—but they serve a larger shared vision, not competing ones.',650,970)
|
||
# three linked columns with directional flow
|
||
cols=[(70,'MY ASSIGNMENT','Faithful action','Use what I have been given.',GREEN),(460,'OUR REGION','Shared responsibility','Know one another’s work; support and strengthen it.',CLAY),(850,'THE FAMILY','Lasting momentum','The vision continues beyond any one leader.',GOLD)]
|
||
for x,h,s,b,col in cols:
|
||
rect(x,300,340,198,WHITE,r=16); rect(x,300,10,198,col)
|
||
text(h,x+28,453,13,'SansB',col); text(s,x+26,403,26,'Editorial',INK); para(b,x+29,366,272,17,25)
|
||
for x in (420,810):
|
||
line(x,395,x+34,395,GOLD,3); c.setFillColor(GOLD); p=c.beginPath(); p.moveTo(x+34,395); p.lineTo(x+23,403); p.lineTo(x+23,387); p.close(); c.drawPath(p,fill=1,stroke=0)
|
||
text('“Is the family advancing—and is this still our family vision?”',70,226,27,'Editorial',GREEN)
|
||
text('Move from “Who else will do it?” to “What can we carry together?”',71,179,16,'SansB',MUTED)
|
||
c.showPage()
|
||
# 4 practices of shared mission
|
||
base(4,'Practice')
|
||
title('03 · How we move','Many gifts. One mission.','Prayer and spiritual life anchor the work; relationships and practical service give it local roots.',650,990)
|
||
# anchor and five clear service lanes
|
||
rect(60,315,290,170,GREEN,r=18); text('THE FOUNDATION',91,443,13,'SansB',HexColor('#F2D69A')); text('Prayer',89,391,36,'Editorial',WHITE); text('& shared life',91,351,25,'Editorial',WHITE)
|
||
items=[('01','RELATIONSHIPS','Fellowship · presence · trust'),('02','DISCIPLESHIP','Evangelism · leaders · maturity'),('03','PRACTICAL SERVICE','Medicine · business · education'),('04','CROSS-POLLINATION','People · ideas · skills · resources'),('05','LOCAL EXPRESSION','Each place’s gifts · needs · culture')]
|
||
for i,(num,head,desc) in enumerate(items):
|
||
y=467-i*61; circle(417,y+3,17,GOLD if i%2==0 else CLAY); c.setFillColor(WHITE); c.setFont('SansB',10); c.drawCentredString(417,y,num)
|
||
text(head,451,y+7,14,'SansB',GREEN); text(desc,451,y-15,15,'Sans',MUTED)
|
||
if i<4: line(417,y-17,417,y-40,PALE,2)
|
||
c.showPage()
|
||
# 5 establish
|
||
base(5,'The outcome')
|
||
title('04 · The outcome','Go beyond the visit. Establish.','Evangelism opens the door. The aim is a durable spiritual family and local work that can keep growing.',650,950)
|
||
steps=[('GO','Show up with purpose'),('CONNECT','Build trust & belonging'),('DISCIPLE','Form people & leaders'),('ESTABLISH','Grow local roots'),('MULTIPLY','Equip others to carry it')]
|
||
xs=[132,387,642,897,1152]; yy=372
|
||
line(xs[0],yy,xs[-1],yy,PALE,5)
|
||
for i,(h,d) in enumerate(steps):
|
||
col=[GREEN,CLAY,GREEN,GOLD,GREEN][i]; circle(xs[i],yy,36,col); c.setFillColor(WHITE); c.setFont('SansB',10); c.drawCentredString(xs[i],yy-4,h)
|
||
text(d,xs[i]-89,yy-75,14,'Sans',MUTED)
|
||
rect(100,187,1080,59,PALE,r=15)
|
||
text('RELATIONSHIPS',137,210,13,'SansB',GREEN); text('LOCAL LEADERS',375,210,13,'SansB',GREEN); text('SUSTAINABLE ROOTS',618,210,13,'SansB',GREEN); text('REGIONAL OWNERSHIP',923,210,13,'SansB',GREEN)
|
||
text('Stay long enough to build something that remains.',105,130,26,'Editorial',INK)
|
||
c.showPage()
|
||
# 6 regional examples
|
||
base(6,'Regional exchange')
|
||
title('05 · Share what serves','Let good work travel.','Cross-pollination is not copy-and-paste. Adapt good ideas to local relationships, needs, language, and realities.',650,960)
|
||
# arrows linking origin/destination
|
||
rect(60,294,470,190,WHITE,r=18); text('A GIFT ALREADY GROWING',91,442,13,'SansB',CLAY); text('Venezuela',89,385,36,'Editorial',INK); text('Medical work · experience · people',91,341,17,'Sans',MUTED)
|
||
rect(750,294,470,190,WHITE,r=18); text('A QUESTION TO EXPLORE',781,442,13,'SansB',GREEN); text('Across the region',779,385,36,'Editorial',INK); text('Where could this serve—and what must change?',781,341,17,'Sans',MUTED)
|
||
line(551,387,720,387,GOLD,4); c.setFillColor(GOLD); p=c.beginPath(); p.moveTo(720,387); p.lineTo(703,397); p.lineTo(703,377); p.close(); c.drawPath(p,fill=1,stroke=0)
|
||
text('Other resources travel too:',65,229,17,'SansB',GREEN)
|
||
for x,label in [(65,'EDUCATION'),(286,'BUSINESS'),(507,'PROFESSIONAL SKILLS'),(828,'STRATEGIES'),(1033,'PRAYER')]:
|
||
rect(x,170,190,38,PALE,r=19); c.setFillColor(GREEN); c.setFont('SansB',11); c.drawCentredString(x+95,184,label)
|
||
text('Local wisdom leads. Regional relationships make the exchange possible.',67,114,18,'Editorial',INK)
|
||
c.showPage()
|
||
# 7 generations
|
||
base(7,'Continuity')
|
||
title('06 · Leadership across generations','Prepare the next leader while you can still walk together.','Emerging leaders need wisdom, affirmation, coaching, and a real place to function—not a last-minute handoff.',650,1050)
|
||
# bridge motif
|
||
line(150,365,1125,365,GOLD,5)
|
||
for x,col,tag,head,desc in [(220,GREEN,'MATURE LEADERS','Coach','Share wisdom; make room.'),(640,CLAY,'IN THE WORK TOGETHER','Entrust','Practice, learn, and lead.'),(1060,GREEN,'EMERGING LEADERS','Carry forward','Grow into visible responsibility.')]:
|
||
circle(x,365,57,col); c.setFillColor(WHITE); c.setFont('SansB',10); c.drawCentredString(x,361,tag.split()[0])
|
||
text(tag,x-122,274,12,'SansB',col); text(head,x-122,235,25,'Editorial',INK); para(desc,x-122,202,250,16,24)
|
||
text('Moses & Joshua · David & Solomon',68,112,16,'SansB',GREEN)
|
||
text('Continuity is formed through shared life—not just succession plans.',455,112,17,'Editorial',INK)
|
||
c.showPage()
|
||
# 8 next steps closing
|
||
base(8,'Move together',True)
|
||
text('07 · THE NEXT FAITHFUL STEPS',63,637,13,'SansB',GOLD)
|
||
text('Align. Connect. Pray.',58,563,50,'Editorial',WHITE); text('Then move together.',59,504,50,'Editorial',WHITE)
|
||
steps=[('1','ALIGN','One shared understanding of the vision'),('2','CONNECT','Strengthen relationships, including Chiapas ↔ San Luis'),('3','PRAY','Establish a regular regional rhythm'),('4','SHARE','Exchange gifts, people, strategies, and resources'),('5','FOCUS','Choose a few clear priorities; strengthen Chile’s open door')]
|
||
for i,(n,h,b) in enumerate(steps):
|
||
y=422-i*55; text(n,68,y,16,'SansB',GOLD); text(h,111,y,14,'SansB',HexColor('#EBCF91')); text(b,242,y,16,'Sans',HexColor('#E5E7DB'))
|
||
line(66,130,1214,130,HexColor('#8A7650'),1)
|
||
text('A gathering that becomes a family in motion.',66,88,24,'Editorial',WHITE)
|
||
text('Vision alignment · prayer · leadership · collaboration · outreach · the next generation',68,57,13,'Sans',HexColor('#D7DED6'))
|
||
c.showPage(); c.save(); print(f'{OUT} | {OUT.stat().st_size} bytes | 8 slides')
|