{deck}
version:1
card:0
size:[512,342]
name:"pdf.deck"

{fonts}
deckbuilder:"%%[encoded data, 12424 characters]"

{card:Index}
image:"%%IMG2AgABVgD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8APAj/COIAHwj/COIAHwj/COIAHwj/COIAHwj/COIAHwj/COIAHwj/COIAHwj/COIAHwj/COIAHwj/COIAHwj/COIAHwj/COIAHwj/COIAHwj/COIAHwj/COIAHwj/COIAHwj/COIAHwj/COIAHwj/COIAHwj/COIAHwj/COIAHwj/COIAHwj/COIAHwj/COIAHwj/COIAHwj/COIAHwj/COIAHwj/COIAHwj/COIAHwj/COIAHwj/COIA/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wBT"
script:"Index.0"
{widgets}
button1:{"type":"button","size":[60,20],"pos":[442,312],"script":"Index.1","text":"Next","style":"rect"}
field2:{"type":"field","size":[248,55],"pos":[14,96],"locked":1,"show":"transparent","border":0,"value":{"text":["The \"pdf\" module allows decker to generate and export files in the Portable Document Format, with multiple pages populated with raster or vector images.\n\n","Index:"],"font":["","menu"],"arg":["",""]}}
index:{"type":"field","size":[243,155],"pos":[16,159],"locked":1,"volatile":1,"script":"Index.2","scrollbar":1}
version:{"type":"field","size":[42,14],"pos":[16,318],"locked":1,"volatile":1,"border":0}
field1:{"type":"field","size":[488,61],"pos":[14,22],"locked":1,"show":"transparent","border":0,"align":"center","value":{"text":["","PDF\n","\nPDF Export for Decker"],"font":["","deckbuilder","menu"],"arg":["","",""]}}

{script:Index.0}
on view do
 bullet:image["%%IMG0AAYADQAAAAB49Pz8/HgAAAA="]
 i:select c:key t:value..widgets.title.text where value..widgets.title from deck.cards
 index.value:raze each row in rows i
  rtext.make["" "" bullet],
  rtext.make["  "],
  rtext.make[("%s\n" format row.t) "mono" row.c]
 end
 version.text:"v%0.1f" format deck.modules.pdf.version
end
{end}

{script:Index.1}
on click do
 t.Prev:"SlideRight"
 t.Next:"SlideLeft"
 t.Index:"BoxOut"
 go[me.text t[me.text] 15]
end
{end}

{script:Index.2}
on link val do
 go[val "BoxIn" 15]
end
{end}

{card:build}
{widgets}
button1:{"type":"button","size":[60,20],"pos":[442,312],"script":"Index.1","text":"Next","style":"rect"}
button2:{"type":"button","size":[60,20],"pos":[10,312],"script":"Index.1","text":"Prev","style":"rect"}
title:{"type":"field","size":[492,17],"pos":[10,22],"locked":1,"font":"menu","show":"invert","border":1,"align":"center","value":"pdf.build[]"}
button3:{"type":"button","size":[60,20],"pos":[78,312],"script":"Index.1","text":"Index","style":"rect"}
field1:{"type":"field","size":[248,238],"pos":[254,48],"locked":1,"border":0,"value":"The pdf.build[] function takes a table (or tables) of page descriptions and produces an array interface representing the complete PDF document, which can then be saved with the write[] built-in function. Remember to save with a \".pdf\" extension!\n\nThe page description table consists of two columns:\n\n- size: pairs of (width,height) dimensions of pages, measured in display units.\n- code: a string or array containing a sequence of drawing commands for the page.\n\nA full description of PDF vector drawing commands is beyond the scope of this document, but the \"pdf\" module provides a number of helper functions for preparing these code sequences, as we will see later. Of particular note in this example is that the default drawing coordinate system has its origin in the bottom-left corner of each page, rather than the top-left corner used by Decker's canvas APIs."}
ex1:{"type":"field","size":[232,238],"pos":[10,48],"border":1,"style":"code","value":"box:\"\n1 0 0 RG % set (red,green,blue) color\n2 w      % set line width\n 2  2 m  % move to (x,y)\n10  2 l  % line to (x,y)\n10 10 l\n 2 10 l\ns        % stroke line\n\"\n\npages:insert size code with\n 12,12 box\nend\n\nwrite[pdf.build[pages] \".pdf\"]"}
button4:{"type":"button","size":[60,20],"pos":[254,266],"script":"build.0","text":"Try It!"}

{script:build.0}
on click do
 eval[ex1.text () 1]
end
{end}

{card:page_center}
{widgets}
button1:{"type":"button","size":[60,20],"pos":[442,312],"script":"Index.1","text":"Next","style":"rect"}
button2:{"type":"button","size":[60,20],"pos":[10,312],"script":"Index.1","text":"Prev","style":"rect"}
title:{"type":"field","size":[492,17],"pos":[10,22],"locked":1,"font":"menu","show":"invert","border":1,"align":"center","value":"pdf.page_center[]"}
button3:{"type":"button","size":[60,20],"pos":[78,312],"script":"Index.1","text":"Index","style":"rect"}
field1:{"type":"field","size":[248,238],"pos":[254,48],"locked":1,"border":0,"value":{"text":["The pdf module provides a number of \"page\" functions which assemble page descriptions and return a single-row table, which can be concatenated together and provided to pdf.build[].\n\n","pdf.page_center[img margin]\n","\n- img: an Image interface.\n- margin: number of units to pad the image.\n\nImages passed to layout functions must be \"flat\", consisting only of the patterns 0/1 and (if color is used) the solid colors 32-47. See the ","pdf.flatten[]"," function for help flattening images with 1-bit patterns or animated patterns."],"font":["","mono","","",""],"arg":["","","","flatten",""]}}
ex1:{"type":"field","size":[232,238],"pos":[10,48],"border":1,"style":"code","value":"img:image[\"%%IMG0AA8AD+AOgAKB8gIQBAgIaBZoJggwKBLIEYgQCI/ygALgDg==\"]\n\nr:pdf.build[pdf.page_center[img 10]]\nwrite[r \".pdf\"]"}
button4:{"type":"button","size":[60,20],"pos":[254,266],"script":"build.0","text":"Try It!"}

{card:page_vertical}
image:"%%[encoded data, 4880 characters]"
{widgets}
button1:{"type":"button","size":[60,20],"pos":[442,312],"script":"Index.1","text":"Next","style":"rect"}
button2:{"type":"button","size":[60,20],"pos":[10,312],"script":"Index.1","text":"Prev","style":"rect"}
title:{"type":"field","size":[492,17],"pos":[10,22],"locked":1,"font":"menu","show":"invert","border":1,"align":"center","value":"pdf.page_vertical[], pdf.page_horizontal[]"}
button3:{"type":"button","size":[60,20],"pos":[78,312],"script":"Index.1","text":"Index","style":"rect"}
field1:{"type":"field","size":[248,116],"pos":[254,48],"locked":1,"border":0,"value":{"text":["The \"vertical\" layout stacks a list of images vertically on a page, each horizontally centered. The \"horizontal\" layout likewise stacks images horizontally, each vertically centered:\n","\npdf.page_vertical[images margin]\npdf.page_horizontal[images margin]","\n\n- images: a list of Image interfaces.\n- margin: number of units to pad the image.\n"],"font":["","mono",""],"arg":["","",""]}}
ex1:{"type":"field","size":[232,238],"pos":[10,48],"border":1,"style":"code","value":"img:image[\"%%IMG0AA8AD+AOgAKB8gIQBAgIaBZoJggwKBLIEYgQCI/ygALgDg==\"]\n\nwide:image[\"%%IMG0ABQAD+AAcIAAEIH/kAIAgAQAQAgDQBYDQCYAQDARQBIeQBHgQBAAQI//kIAAEOAAcA==\"]\n\ntall:image[\"%%IMG0AA8AFOAOgAKB8gIQBAgIaBZoJgggCCAIJCgkKCSoNKgSSBGIEAiP8oAC4A4=\"]\n\nr:pdf.build[\n pdf.page_vertical  [img,wide 10]\n pdf.page_horizontal[img,tall 10]\n]\n\nwrite[r \".pdf\"]"}
button4:{"type":"button","size":[60,20],"pos":[254,266],"script":"build.0","text":"Try It!"}

{card:page_grid}
image:"%%IMG2AgABVgD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AH4BiAD/AHkBAQCGAQEA/wB5AQEAhgEBAP8AeQEBAIYBAQD/AHkBAQCGAQEA/wB5AQEAhgEBAP8AeQEBAAUBJgAFASYABQEmAAUBAQD/AHkBAQAFAQEAJAEBAAUBAQAkAQEABQEBACQBAQAFAQEA/wB5AQEABQEBACQBAQAFAQEAJAEBAAUBAQAkAQEABQEBAP8AeQEBAAUBAQAkAQEABQEBACQBAQAFAQEAJAEBAAUBAQD/AHkBAQAFAQEAJAEBAAUBAQAkAQEABQEBACQBAQAFAQEA/wB5AQEABQEBACQBAQAFAQEAJAEBAAUBAQAkAQEABQEBAP8AeQEBAAUBAQAkAQEABQEBACQBAQAFAQEAJAEBAAUBAQD/AHkBAQAFAQEAJAEBAAUBAQAkAQEABQEBACQBAQAFAQEA/wB5AQEABQEBACQBAQAFAQEAJAEBAAUBAQAkAQEABQEBAP8AeQEBAAUBAQAkAQEABQEBACQBAQAFAQEAJAEBAAUBAQD/AHkBAQAFAQEAJAEBAAUBAQAkAQEABQEBACQBAQAFAQEA/wB5AQEABQEBACQBAQAFAQEAJAEBAAUBAQAkAQEABQEBAP8AeQEBAAUBAQAkAQEABQEBACQBAQAFAQEAJAEBAAUBAQD/AHkBAQAFAQEAJAEBAAUBAQAkAQEABQEBACQBAQAFAQEA/wB5AQEABQEBACQBAQAFAQEAJAEBAAUBAQAkAQEABQEBAP8AeQEBAAUBAQAkAQEABQEBACQBAQAFAQEAJAEBAAUBAQD/AHkBAQAFAQEAJAEBAAUBAQAkAQEABQEBACQBAQAFAQEA/wB5AQEABQEBACQBAQAFAQEAJAEBAAUBAQAkAQEABQEBAP8AeQEBAAUBAQAkAQEABQEBACQBAQAFAQEAJAEBAAUBAQD/AHkBAQAFAQEAJAEBAAUBAQAkAQEABQEBACQBAQAFAQEA/wB5AQEABQEBACQBAQAFAQEAJAEBAAUBAQAkAQEABQEBAP8AeQEBAAUBAQAkAQEABQEBACQBAQAFAQEAJAEBAAUBAQD/AHkBAQAFAQEAJAEBAAUBAQAkAQEABQEBACQBAQAFAQEA/wB5AQEABQEBACQBAQAFAQEAJAEBAAUBAQAkAQEABQEBAP8AeQEBAAUBJgAFASYABQEmAAUBAQD/AHkBAQCGAQEA/wB5AQEAhgEBAP8AeQEBAIYBAQD/AHkBAQCGAQEA/wB5AQEAhgEBAP8AeQEBAAUBJgAFASYABQEmAAUBAQD/AHkBAQAFAQEAJAEBAAUBAQAkAQEABQEBACQBAQAFAQEA/wB5AQEABQEBACQBAQAFAQEAJAEBAAUBAQAkAQEABQEBAP8AeQEBAAUBAQAkAQEABQEBACQBAQAFAQEAJAEBAAUBAQD/AHkBAQAFAQEAJAEBAAUBAQAkAQEABQEBACQBAQAFAQEA/wB5AQEABQEBACQBAQAFAQEAJAEBAAUBAQAkAQEABQEBAP8AeQEBAAUBAQAkAQEABQEBACQBAQAFAQEAJAEBAAUBAQD/AHkBAQAFAQEAJAEBAAUBAQAkAQEABQEBACQBAQAFAQEA/wB5AQEABQEBACQBAQAFAQEAJAEBAAUBAQAkAQEABQEBAP8AeQEBAAUBAQAkAQEABQEBACQBAQAFAQEAJAEBAAUBAQD/AHkBAQAFAQEAJAEBAAUBAQAkAQEABQEBACQBAQAFAQEA/wB5AQEABQEBACQBAQAFAQEAJAEBAAUBAQAkAQEABQEBAP8AeQEBAAUBAQAkAQEABQEBACQBAQAFAQEAJAEBAAUBAQD/AHkBAQAFAQEAJAEBAAUBAQAkAQEABQEBACQBAQAFAQEA/wB5AQEABQEBACQBAQAFAQEAJAEBAAUBAQAkAQEABQEBAP8AeQEBAAUBAQAkAQEABQEBACQBAQAFAQEAJAEBAAUBAQD/AHkBAQAFAQEAJAEBAAUBAQAkAQEABQEBACQBAQAFAQEA/wB5AQEABQEBACQBAQAFAQEAJAEBAAUBAQAkAQEABQEBABoBAQD/AF4BAQAFAQEAJAEBAAUBAQAkAQEABQEBACQBAQAFAQEA/wB5AQEABQEBACQBAQAFAQEAJAEBAAUBAQAkAQEABQEBAP8AeQEBAAUBAQAkAQEABQEBACQBAQAFAQEAJAEBAAUBAQD/AHkBAQAFAQEAJAEBAAUBAQAkAQEABQEBACQBAQAFAQEA/wB5AQEABQEBACQBAQAFAQEAJAEBAAUBAQAkAQEABQEBAP8AeQEBAAUBAQAkAQEABQEBACQBAQAFAQEAJAEBAAUBAQD/AHkBAQAFASYABQEmAAUBJgAFAQEA/wB5AQEAhgEBAP8AeQEBAIYBAQD/AHkBAQCGAQEA/wB5AQEAhgEBAP8AeQEBAIYBAQD/AHkBiAD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wAj"
{widgets}
button1:{"type":"button","size":[60,20],"pos":[442,312],"script":"Index.1","text":"Next","style":"rect"}
button2:{"type":"button","size":[60,20],"pos":[10,312],"script":"Index.1","text":"Prev","style":"rect"}
title:{"type":"field","size":[492,17],"pos":[10,22],"locked":1,"font":"menu","show":"invert","border":1,"align":"center","value":"pdf.page_grid[]"}
button3:{"type":"button","size":[60,20],"pos":[78,312],"script":"Index.1","text":"Index","style":"rect"}
field1:{"type":"field","size":[248,105],"pos":[254,48],"locked":1,"border":0,"value":{"text":["The \"grid\" layout stacks a list of images in a uniform grid based on the maximum size of the provided images, with a specified number of columns.\n\n","pdf.page_grid[images margin width]","\n\n- images: a list of Image interfaces.\n- margin: number of units to pad the image.\n- width: number of grid columns."],"font":["","mono",""],"arg":["","",""]}}
ex1:{"type":"field","size":[232,238],"pos":[10,48],"border":1,"style":"code","value":"img:image[\"%%IMG0AA8AD+AOgAKB8gIQBAgIaBZoJggwKBLIEYgQCI/ygALgDg==\"]\n\nwide:image[\"%%IMG0ABQAD+AAcIAAEIH/kAIAgAQAQAgDQBYDQCYAQDARQBIeQBHgQBAAQI//kIAAEOAAcA==\"]\n\ntall:image[\"%%IMG0AA8AFOAOgAKB8gIQBAgIaBZoJgggCCAIJCgkKCSoNKgSSBGIEAiP8oAC4A4=\"]\n\nimages:img,wide,img,tall,img\nr:pdf.build[\n pdf.page_grid[images 10 3]\n]\n\nwrite[r \".pdf\"]"}
button4:{"type":"button","size":[60,20],"pos":[254,266],"script":"build.0","text":"Try It!"}

{card:rasterize}
{widgets}
button1:{"type":"button","size":[60,20],"pos":[442,312],"script":"Index.1","text":"Next","style":"rect"}
button2:{"type":"button","size":[60,20],"pos":[10,312],"script":"Index.1","text":"Prev","style":"rect"}
title:{"type":"field","size":[492,17],"pos":[10,22],"locked":1,"font":"menu","show":"invert","border":1,"align":"center","value":"pdf.rasterize[], pdf.palette[]"}
button3:{"type":"button","size":[60,20],"pos":[78,312],"script":"Index.1","text":"Index","style":"rect"}
field1:{"type":"field","size":[248,238],"pos":[254,48],"locked":1,"border":0,"value":{"text":["The layout functions we've seen previously automatically handle converting Images into PDF drawing instructions. If you want to define your own custom layouts, you can use pdf.rasterize[] to convert an image into a string of drawing instructions.\n\n","pdf.rasterize[img pos]","\n\n- img: an Image interface.\n- pos: (x,y) drawing coordinates of the bottom-left corner of the image.\n\nBy default, pdf.rasterize[] converts images with Decker's default palette. If you have customized the palette, first call pdf.palette[] with the deck's Patterns interface."],"font":["","mono",""],"arg":["","",""]}}
ex1:{"type":"field","size":[232,238],"pos":[10,48],"border":1,"style":"code","value":"img:image[\"%%IMG2ACAAEQEDABoBBAAPAQUACgECAA4BASgEAQEACgEBAA4BASgGAQEAEQEFAAEBASgEAQIoAQEBAAIBBQAJAQEjBAECKAEBAigCAQIoAQEBAAEBAScEAQEACAEBIwYBASgBAQIoBQECJwYBAQAGAQEjBAECIwEBASgGAQEoAQEBJwQBAicBAQEABQEBIwEBAiMCAQIjAQEBKAIBASgBAQIoAQEBJwEBAicCAQInAQEBAAQBASMCAQIjBQEBKAMBAigBAQEnAgECJwUBAQAEAQIjBgEBIwEBASgGAQInBgEBJwEBAQAFAQEjAgEBIwEBAiMCAQknAgEBJwEBAicCAQEABQEBIwMBAiMDAQEABwEBJwMBAicDAQEABQEBIwgBAQAHAQEnCAEBAAIBAQADAQgACQEIAAIBAgAeAQQAGgED\"]\n\npdf.palette[deck.patterns]\nr:pdf.build[\n pdf.page_raw[\n  48,32 pdf.rasterize[img 3,5]\n ]\n]\nwrite[r \".pdf\"]"}
button4:{"type":"button","size":[60,20],"pos":[254,266],"script":"build.0","text":"Try It!"}

{card:flatten}
{widgets}
button1:{"type":"button","size":[60,20],"pos":[442,312],"script":"Index.1","text":"Next","style":"rect"}
button2:{"type":"button","size":[60,20],"pos":[10,312],"script":"Index.1","text":"Prev","style":"rect"}
title:{"type":"field","size":[492,17],"pos":[10,22],"locked":1,"font":"menu","show":"invert","border":1,"align":"center","value":"pdf.image_flatten[]"}
button3:{"type":"button","size":[60,20],"pos":[78,312],"script":"Index.1","text":"Index","style":"rect"}
field1:{"type":"field","size":[248,121],"pos":[254,48],"locked":1,"border":0,"value":{"text":["As noted previously, Images passed to layout functions must be \"flat\", consisting only of the patterns 0/1 and (if color is used) the solid colors 32-47. The pdf.flatten[] function can convert images that contain 1-bit or animated patterns into this format:\n","\npdf.flatten[img deck]","\n\n- img: an Image interface.\n- deck: a Deck interface."],"font":["","mono",""],"arg":["","",""]}}
ex1:{"type":"field","size":[232,143],"pos":[10,48],"border":1,"style":"code","value":"i:pdf.flatten[patterned.copy[] deck]\nr:pdf.build[pdf.page_center[i]]\nwrite[r \".pdf\"]"}
button4:{"type":"button","size":[60,20],"pos":[253,171],"script":"build.0","text":"Try It!"}
patterned:{"type":"canvas","size":[91,82],"pos":[83,211],"locked":1,"image":"%%IMG2AFsAUgD/AP8APAEGAFEBCwBOAQ8ASgEIHQYBBABIAQUdCwEFABoBCgAhAQQdDwEFABMBEQAeAQMdEgEHAAoBGAAcAQMdFQEGAAYBDicKAQQAGgEDHRgBBQADAQsnEAEDABkBAx0cAQMAAQEGJxcBAwAXAQMdHQEHJxoBBAAVAQMdHwEEJx0BBAATAQMdIQEEJx0BBAASAQMdIgEDJx4BAwARAQMdJAEDJx4BAwAQAQMdJQEDJx4BAwAPAQMdJQEDJx8BAwAOAQMdJQEDJyABAwANAQMdJgEDJx8BAwANAQMdJgEDJyABAwAMAQMdJgEDJyABAwAMAQMdJgEDJyABAwAMAQMdJgEDJyABAwAMAQMdJgEDJyEBAwALAQMdJgEDJyEBAwALAQMdJgEDJyEBAwAMAQMdJQEDJyEBAwAMAQMdJQEDJyEBAwAMAQMdJQEDJyEBAwAMAQMdJQEDJyEBAwANAQMdIwEDJyIBAwANAQMdIwEDJyIBAwANAQMdIwEDJyIBAwAOAQMdIQEDJyMBAwAPAQMdHwEEJyIBAwARAQMdHQEEJyIBAwATAQMdHAEHJx4BAwAVAQQdGQEJJxwBAwAXAQUdAwEBHQIBAR0PAQMNAwEFJxoBAwAZAQwdDAEEDQcBAycXAQUAGwEZDQkBBScPAQkAHgEWDQsBBicKAQoAIgEDDQEBDg0OARcAJAEDDSABDwApAQMNIgEKACwBAw0nAQMALgEDDScBAwAuAQMNJwEEAC0BAw0oAQMALQEDDSgBAwAtAQMNKAEDAC4BAw0mAQMALwEDDSYBAwAvAQMNJQEDADEBAw0kAQMAMQEDDSQBAwAyAQMNIwEDADIBAw0iAQMANAEDDSABAwA2AQMNHgEEADYBAw0dAQQAOAEEDRoBBAA6AQUNFgEFADwBBQ0TAQYAPwEGDQ4BBgBDAQcNCQEGAEYBEwBLAQ4AUAEJAP8A/wCp","scale":1}
field2:{"type":"field","size":[100,14],"pos":[78,198],"locked":1,"show":"transparent","border":0,"value":"patterned"}

{card:integration}
{widgets}
button2:{"type":"button","size":[60,20],"pos":[10,312],"script":"Index.1","text":"Prev","style":"rect"}
title:{"type":"field","size":[492,17],"pos":[10,22],"locked":1,"font":"menu","show":"invert","border":1,"align":"center","value":"integration"}
button3:{"type":"button","size":[60,20],"pos":[442,312],"script":"Index.1","text":"Index","style":"rect"}
field1:{"type":"field","size":[248,238],"pos":[254,48],"locked":1,"border":0,"value":"Using everything we've discussed, here's an example script that turns the current deck into a printable PDF of thumbnail images.\n\n(This takes a little while; be patient.)"}
ex1:{"type":"field","size":[232,238],"pos":[10,48],"border":1,"style":"code","value":"images:each card in range deck.cards\n pdf.flatten[app.render[card] deck]\nend\n\nr:pdf.build[\n raze each p in 2 window images\n  pdf.page_vertical[p 10]\n end\n]\n\nwrite[r \".pdf\"]"}
button4:{"type":"button","size":[60,20],"pos":[254,266],"script":"build.0","text":"Try It!"}

{module:pdf}
description:"A utility module for assembling PDF documents from Images and vector drawing streams."
version:1.1
{script}

on build ...parts do
 local out:array[]
 local ob_offsets:()
 local ob_index:0
 local ob_pages:()
 on fmt_dict x do "<< %s >>" format " " fuse range each v k in x "/%s %s" format k,v end end
 on fmt_list x do "[ %s ]" format " " fuse x end
 on fmt_refs x do "[ %s ]" format " " fuse (list "%i 0 R") format x end
 on fmt_ref  x do "%i 0 R" format x end
 on object props body do
  ob_index:ob_index+1
  ob_offsets:ob_offsets,out.size
  out.cat["%i 0 obj\n%s\n" format ob_index,fmt_dict[props]]
  if body out.cat[body "\n"] end
  out.cat["endobj\n"]
  ob_index
 end
 on stream x do
  p.Length:1+if "string"~typeof x count x else x.size end
  object[p array[].cat["stream\n" x "\nendstream"]]
 end
 out.cat["%PDF-1.4\n%generated by Decker\n"]
 each row in rows raze parts
  local t:()
  t.MediaBox:fmt_list[0,0,row.size]
  t.Contents:fmt_ref[stream[row.code]]
  ob_pages:ob_pages,list t
 end
 c.Type:"/Catalog"
 c.Pages:fmt_ref[ob_index+2]
 local index_catalog:object[c]
 l.Type:"/Pages"
 l.Count:count ob_pages
 l.Kids:fmt_refs[(ob_index+2)+range count ob_pages]
 local index_pages:object[l]
 each p in ob_pages
  p.Type:"/Page"
  p.Parent:fmt_ref[index_pages]
  object[p]
 end
 local base:out.size
 out.cat["xref\n0 %i\n0000000000 65535 f\n" format 1+ob_index]
 each offset in ob_offsets out.cat["%010i 00000 n\n" format offset] end
 trailer:fmt_dict[("Size","Root") dict (1+ob_index),fmt_ref[index_catalog]]
 out.cat["trailer\n%s\nstartxref\n%i\n%%%%EOF" format trailer,base]
 out
end

# image preparation:

colors:"|" split "FFFFFF|FFFF00|FF6500|DC0000|FF0097|360097|0000CA|0097FF|00A800|006500|653600|976536|B9B9B9|868686|454545|000000"
on palette pat do
 colors:each i in range 16 "%06H" format pat[32+i] end
end
on flatten img deck do
 anim:28,29,30,31
 img:img.copy[].map[anim dict first @ deck.patterns @ anim]
 c:deck.card.add["canvas"]
 c.size:img.size
 c.paste[img]
 c.invert[]
 c.invert[]
 c.paste[img.map[(33+range 14) dict (33+range 14) 0] 0,0 1]
 r:c.copy[]
 deck.card.remove[c]
 r
end
on rasterize img pos do
 if 1<max keys img.hist
  pix:"" fuse colors @ 0|15& -32+ raze img.copy[].map[(0,1) dict (32,47)].pixels
  cs:"RGB"
 else
  pix:"" fuse ("FF","00") @ raze img.pixels
  cs:"G"
 end
 "q %i 0 0 %i %i %i cm BI /W %i /H %i /CS /%s /BPC 8 /F /AHx ID\n%s> EI Q " format img.size,pos,img.size,cs,pix
end

# page construction:

on page_raw size code do
 insert size code with size code end
end
on page_center img margin do
 insert size code with img.size+2*margin rasterize[img margin,margin] end
end
on page_vertical images margin do
 local cw:max images..size[0]
 local ch:sum images..size[1]
 local w:cw+margin*2
 local h:ch+margin*1+count images
 local y:h-margin
 local code:"" fuse each img i in images
  local r:rasterize[img (margin+.5*cw-img.size[0]),y-img.size[1]]
  y:y-img.size[1]+margin
  r
 end
 insert size code with w,h code end
end
on page_horizontal images margin do
 local cw:sum images..size[0]
 local ch:max images..size[1]
 local w:cw+margin*1+count images
 local h:ch+margin*2
 local x:margin
 local code:"" fuse each img i in images
  local r:rasterize[img x,margin+.5*ch-img.size[1]]
  x:x+img.size[0]+margin
  r
 end
 insert size code with w,h code end
end
on page_grid images margin width do
 local cell:max images..size
 local height:-floor-(count images)/width
 local w:(cell[0]*width )+margin*1+width
 local h:(cell[1]*height)+margin*1+height
 local code:"" fuse each pos i in (count images) take width cross height
  img:images[i]
  rasterize[img ((.5*cell[0]-img.size[0])+margin+pos[0]*margin+cell[0]),(h-(-.5*cell[1]-img.size[1])+(pos[1]+1)*margin+cell[1])]
 end
 insert size code with w,h code end
end

# public methods:

module.build          :build
module.palette        :palette
module.flatten        :flatten
module.rasterize      :rasterize
module.page_raw       :page_raw
module.page_center    :page_center
module.page_vertical  :page_vertical
module.page_horizontal:page_horizontal
module.page_grid      :page_grid
{end}

