--****************************************************************************
-- Software: PDF CLASS
-- Version: 1.03, based on FPDF 1.51 by Olivier Plathey (respect!)
-- Date: 2004/01/30
-- Author: Valentin Schmidt (original PHP Script by Olivier Plathey, inspiration by Daniel Nelson)
-- Contact: valentin@dasdeck.de
-- License: Freeware
--
-- Requirements/Dependencies: needs fileIO Xtra
--
-- You may use and modify this software as you wish.
--****************************************************************************
property pPDF_CLASS_VERSION
property pPDF_FONTPATH
property pPage --current page number
property pN --current object number
property pOffsets --array of object offsets
property pBuffer --buffer holding in-memory PDF
property pPages --array containing pages
property pState --current document state
property pCompress --compression flag
property pDefOrientation --default orientation
property pCurOrientation --current orientation
property pOrientationChanges --array indicating orientation changes
property pFwPt,pFhPt --dimensions of page format in points
property pFw,pFh --dimensions of page format in user unit
property pWPt,pHPt --current dimensions of page in points
property pK --scale factor (number of points in user unit)
property pW,pH --current dimensions of page in user unit
property pLMargin --left margin
property pTMargin --top margin
property pRMargin --right margin
property pBMargin --page break margin
property pCMargin --cell margin
property pX,pY --current position in user unit for cell positionning
property pLasth --height of last cell printed
property pLineWidth --line width in user unit
property pCoreFonts --array of standard font names
property pFonts --array of used fonts
property pFontFiles --array of font files
property pDiffs --array of encoding differences
property pImages --array of used images
property pPageLinks --array of links in pages
property pLinks --array of internal links
property pFontFamily --current font family
property pFontStyle --current font style
property pUnderline --underlining flag
property pCurrentFont --current font info
property pFontSizePt --current font size in points
property pFontSize --current font size in user unit
property pDrawColor --commands for drawing color
property pFillColor --commands for filling color
property pTextColor --commands for text color
property pColorFlag --indicates whether fill and text colors are different
property pWs --word spacing
property pAutoPageBreak --automatic page breaking
property pPageBreakTrigger --threshold used to trigger page breaks
property pInFooter --flag set when processing footer
property pZoomMode --zoom display mode
property pLayoutMode --layout display mode
property pTitle --title
property pSubject --subject
property pAuthor --author
property pKeywords --keywords
property pCreator --creator
property pAliasNbPages --alias for total number of pages
--Standard fonts
pCoreFonts=[:]
pCoreFonts["courier"]="Courier"
pCoreFonts["courierB"]="Courier-Bold"
pCoreFonts["courierI"]="Courier-Oblique"
pCoreFonts["courierBI"]="Courier-BoldOblique"
pCoreFonts["helvetica"]="Helvetica"
pCoreFonts["helveticaB"]="Helvetica-Bold"
pCoreFonts["helveticaI"]="Helvetica-Oblique"
pCoreFonts["helveticaBI"]="Helvetica-BoldOblique"
pCoreFonts["times"]="Times-Roman"
pCoreFonts["timesB"]="Times-Bold"
pCoreFonts["timesI"]="Times-Italic"
pCoreFonts["timesBI"]="Times-BoldItalic"
pCoreFonts["symbol"]="Symbol"
pCoreFonts["zapfdingbats"]="ZapfDingbats"
--Scale factor
if (unit="pt") then
pK=1.0
else if (unit="mm") then
pK=72/25.4
else if (unit="cm") then
pK=72/2.54
else if(unit="in") then
pK=72.0
else
me._Error("Incorrect unit: "&unit)
end if
--Page format
if (stringP(format)) then
format=strtolower(format)
if (format="a3") then
format=[841.89,1190.55]
else if (format="a4") then
format=[595.28,841.89]
else if (format="a5") then
format=[420.94,595.28]
else if (format="letter") then
format=[612.0,792.0]
else if (format="legal") then
format=[612.0,1008.0]
else
me._Error("Unknown page format: "&format)
end if
pFwPt=format[1]
pFhPt=format[2]
else
pFwPt=format[1]*pK
pFhPt=format[2]*pK
end if
pFw=pFwPt/pK
pFh=pFhPt/pK
--Page orientation
orientation=strtolower(orientation)
if (orientation="p" or orientation="portrait") then
pDefOrientation="P"
pWPt=pFwPt
pHPt=pFhPt
else if (orientation="l" or orientation="landscape") then
pDefOrientation="L"
pWPt=pFhPt
pHPt=pFwPt
else
me._Error("Incorrect orientation: "&orientation)
end if
----------------------------------------
-- Set the path to font folder for non-standard fonts
----------------------------------------
on SetFontpath me, fp
pd=the last char of the moviepath
if the last char of fp<>pd then fp=fp& pd
pPDF_FONTPATH=fp
end
----------------------------------------
-- Set left, top and right margins
----------------------------------------
on SetMargins me, l,t,r
if voidP(r) then r=-1
pLMargin=l
pTMargin=t
if (r=-1) then r=l
pRMargin=r
end
----------------------------------------
-- Set left margin
----------------------------------------
on SetLeftMargin me, marg
pLMargin=marg
if (pPage>0 and pXend
----------------------------------------
-- Set top margin
----------------------------------------
on SetTopMargin me, marg
pTMargin=marg
end
----------------------------------------
-- Set right margin
----------------------------------------
on SetRightMargin me, marg
pRMargin=marg
end
----------------------------------------
-- Set inner cell margin
----------------------------------------
on SetCellMargin me, marg
pCMargin = marg
end
----------------------------------------
-- Set auto page break mode and triggering margin
----------------------------------------
on SetAutoPageBreak me, auto,marg
if voidP(marg) then marg=0
pAutoPageBreak=auto
pBMargin=marg
pPageBreakTrigger=pH-marg
end
----------------------------------------
-- Set display mode in viewer
----------------------------------------
on SetDisplayMode me, zoom,layout
if voidP(layout) then layout="continuous"
if (zoom="fullpage" or zoom="fullwidth" or zoom="real" or zoom="default" or NOT stringP(zoom)) then
pZoomMode=zoom
else if (zoom="zoom") then
pZoomMode=layout
else
me._Error("Incorrect zoom display mode: "&zoom)
end if
if (layout="single" or layout="continuous" or layout="two" or layout="default") then
pLayoutMode=layout
else if (zoom<>"zoom") then
me._Error("Incorrect layout display mode: "&layout)
end if
end
----------------------------------------
-- Set page compression
----------------------------------------
on SetCompression me, compressionFlag
if (me.handlerP(#gzcompress)) then
pCompress=compressionFlag
else
pCompress=false
end if
end
----------------------------------------
-- Set Title of document
----------------------------------------
on SetTitle me, aTitle
pTitle = aTitle
end
----------------------------------------
-- Set Subject of document
----------------------------------------
on SetSubject me, aSubject
pSubject = aSubject
end
----------------------------------------
-- Set Author of document
----------------------------------------
on SetAuthor me, aAuthor
pAuthor = aAuthor
end
----------------------------------------
-- Set Keywords of document
----------------------------------------
on SetKeywords me, aKeywords
pKeywords = aKeywords
end
----------------------------------------
-- Set Creator of document
----------------------------------------
on SetCreator me, aCreator
pCreator = aCreator
end
----------------------------------------
-- Define an alias for total number of pages
----------------------------------------
on AliasNbPages me, aAlias
if voidP(aAlias) then aAlias = "{nb}"
pAliasNbPages = aAlias
end
----------------------------------------
-- Fatal error
----------------------------------------
on _Error me, msg
alert("PDF CLASS error: " & msg)
halt
end
----------------------------------------
-- Begin document
----------------------------------------
on Open me
me._begindoc()
end
----------------------------------------
-- Terminate document
----------------------------------------
on Close me
if (pPage=0) then me.AddPage()
--Page footer
pInFooter = true
if me.handlerP(#Footer) then me.Footer()
pInFooter = false
--Close page
me._endpage()
--Close document
me._enddoc()
end
----------------------------------------
-- Start a new page
----------------------------------------
on AddPage me, orientation
if voidP(orientation) then orientation=""
family=pFontFamily
style=pFontStyle
if (pUnderline) then style=style& "U"
size=pFontSizePt
lw=pLineWidth
dc=pDrawColor
fc=pFillColor
tc=pTextColor
cf=pColorFlag
if (pPage>0) then
--Page footer
pInFooter=true
if me.handlerP(#Footer) then me.Footer()
pInFooter=false
--Close page
me._endpage()
end if
--Start new page
_beginpage(orientation)
--Set line cap style to square
me._out("2 J")
--Set line width
pLineWidth=lw
the floatprecision=2
me._out(float(lw*pK)&" w")
--Set font
if (family<>"") then SetFont(me,family,style,size)
--Set colors
pDrawColor=dc
if (dc<>"0 G") then me._out(dc)
pFillColor=fc
if (fc<>"0 g") then me._out(fc)
pTextColor=tc
pColorFlag=cf
--Page header
if me.handlerP(#Header) then me.Header()
--Restore line width
if (pLineWidth<>lw) then
pLineWidth=lw
the floatprecision=2
me._out(float(lw*pK)&" w")
end if
--Restore font
if (family<>"") then SetFont(me,family,style,size)
--Restore colors
if (pDrawColor<>dc) then
pDrawColor=dc
me._out(dc)
end if
if (pFillColor<>fc) then
pFillColor=fc
me._out(fc)
end if
pTextColor=tc
pColorFlag=cf
end
----------------------------------------
-- Get current page number
----------------------------------------
on PageNo me
return pPage
end
----------------------------------------
-- Set color for all stroking operations
----------------------------------------
on SetDrawColor me, r,g,b
if voidP(g) then g=-1
if voidP(b) then b=-1
the floatprecision=3
if ((r=0 and g=0 and b=0) or g=-1) then
pDrawColor=r/255.0 & " G"
else
pDrawColor=r/255.0 && g/255.0 && b/255.0 && "RG"
end if
if (pPage>0) then me._out(pDrawColor)
end
----------------------------------------
-- Set color for all filling operations
----------------------------------------
on SetFillColor me, r,g,b
if voidP(g) then g=-1
if voidP(b) then b=-1
the floatprecision=3
if ((r=0 and g=0 and b=0) or g=-1) then
pFillColor=r/255.0 & " g"
else
pFillColor=r/255.0 && g/255.0 && b/255.0 && "rg"
end if
pColorFlag=(pFillColor<>pTextColor)
if(pPage>0) then me._out(pFillColor)
end
----------------------------------------
-- Set color for text
----------------------------------------
on SetTextColor me, r,g,b
if voidP(g) then g=-1
if voidP(b) then b=-1
the floatprecision=3
if ((r=0 and g=0 and b=0) or g=-1) then
pTextColor=r/255.0 & " g"
else
pTextColor=r/255.0 && g/255.0 && b/255.0 && "rg"
end if
pColorFlag=(pFillColor<>pTextColor)
end
----------------------------------------
-- Get width of a string in the current font
----------------------------------------
on GetStringWidth me, s
s=string(s)
cw=pCurrentFont["cw"] -- ???
w=0
l=s.length
repeat with i = 1 to l
w=w+cw[ord(s.char[i])+1]--???
end repeat
return w*pFontSize/1000.0
end
----------------------------------------
-- Set line width
----------------------------------------
on SetLineWidth me, aWidth
pLineWidth = aWidth
the floatprecision=2
if (pPage>0) then me._out(float(aWidth*pK) & " w")
end
----------------------------------------
-- Draw a line
----------------------------------------
on DrawLine me, x1,y1,x2,y2
the floatprecision=2
me._out(float(x1*pK) && float((pH-y1)*pK) && "m" && float(x2*pK) && float((pH-y2)*pK) && "l S" )
end
----------------------------------------
-- Draw a rectangle
----------------------------------------
on DrawRect me, x,y,w,h,aStyle
if voidP(aStyle) then g=-1
if (aStyle="F") then
op="f"
else if (aStyle="FD" or aStyle="DF") then
op="B"
else
op="S"
end if
the floatprecision=2
me._out(float(x*pK) && float((pH-y)*pK) && float(w*pK) && float(-h*pK) &&"re" && op)
end
----------------------------------------
-- Add a TrueType or Type1 font
----------------------------------------
on AddFont me, family,aStyle
aStyle=strtoupper(string(aStyle))
family=strtolower(family)
if (family="arial") then family="helvetica"
if (aStyle="IB") then aStyle="BI"
if (NOT voidP(pFonts[family & aStyle])) then me._Error("Font already added: " & family && aStyle)
fontMem=member(family,"fonts")
if (fontMem.memberNum<1) then me._Error("Could not find font definition")
fnt=value(fontMem.text)
if (ilk(fnt)<>#propList) then me._Error("font definition is corrupted")
i=count(pFonts)+1
fnt["i"]=i
pFonts[family & aStyle]=fnt --["i":i,"type":type,"name":name,"desc":desc,"up":up,"ut":ut,"cw":cw,"enc":enc,"file":file]
diff=fnt["diff"]
if (diff<>"") then
--Search existing encodings
d=0
nb=count(pDiffs)
repeat with i = 1 to nb
if (pDiffs[i]=diff) then
d=i
exit repeat
end if
end repeat
if (d=0) then
d=nb+1
pDiffs[d]=diff
end if
pFonts[family&aStyle]["diff"]=d
end if
if (fnt["type"]="TrueType") then
pFontFiles[fnt["file"]]=["length1":fnt["originalsize"]] --fontMem
else
pFontFiles[fnt["file"]]=["length1":fnt["size1"],"length2":fnt["size2"]] --fontMem
end if
end
----------------------------------------
-- Select a font; size given in points
----------------------------------------
on SetFont me, family,style,size
style=string(style)
if voidP(size) then size=0
family=strtolower(family)
if (family="") then family=pFontFamily
if (family="arial") then
family="helvetica"
else if(family="symbol" or family="zapfdingbats") then
style=""
end if
style=strtoupper(style)
if (style contains "U") then
pUnderline=true
style=str_replace("U","",style)
else
pUnderline=false
end if
if (style="IB") then style="BI"
if (size=0) then size=pFontSizePt
--Test if font is already selected
if (pFontFamily=family and pFontStyle=style and pFontSizePt=size) then return
--Test if used for the first time
fontkey=family & style
if (voidP(pFonts[fontkey])) then
--Check if one of the standard fonts
if (NOT voidP(pCoreFonts[fontkey])) then
if (member(fontkey,"fonts").membernum<1) then me._Error("Can't find charwidths for font"&&fontkey) --family
pCharWidths[fontkey] = value(member(fontkey,"fonts").text) --family
i=count(pFonts)+1
pFonts[fontkey]=["i":i,"type":"core","name":pCoreFonts[fontkey],"up":-100,"ut":50,"cw":pCharWidths[fontkey]]
else
me._Error("Undefined font: " & fontkey)
end if
end if
--Select it
pFontFamily=family
pFontStyle=style
pFontSizePt=size
pFontSize=size/pK
pCurrentFont=pFonts[fontkey]
the floatprecision=2
if (pPage>0) then me._out("BT /F" & integer(pCurrentFont["i"]) && float(pFontSizePt) && "Tf ET")
end
----------------------------------------
-- Set font size in points
----------------------------------------
on SetFontSize me, size
if (pFontSizePt=size) then return
pFontSizePt=size
pFontSize=size/pK
floatprecision=2
if (pPage>0) then me._out("BT /F"&integer(pCurrentFont["i"])&& float(pFontSizePt) && "Tf ET")
end
----------------------------------------
-- Create a new internal link
----------------------------------------
on AddLink me
n=count(pLinks)+1
pLinks[n]=[0,0]
return n
end
----------------------------------------
-- Set destination of internal link
----------------------------------------
on SetLink me, link,y,page
if voidP(y) then y=0
if voidP(page) then page=-1
if (y=-1) then y=pY
if (page=-1) then page=pPage
pLinks[link]=[page,y]
end
----------------------------------------
-- Put a link on the page
----------------------------------------
on Link me, x,y,w,h,link
pPageLinks[pPage].add([x*pK,pHPt-y*pK,w*pK,h*pK,link])
end
----------------------------------------
-- Output a string
----------------------------------------
on Text me, x,y,txt
txt=str_replace(")",")",str_replace("(","(",str_replace("","\",txt)))
the floatprecision=2
s="BT" && float(x*pK) && float((pH-y)*pK) && "Td ("&txt&") Tj ET"
if (pUnderline and txt<>"") then s = s && me._dounderline(x,y,txt)
if (pColorFlag) then s="q " & pTextColor && s && "Q"
me._out(s)
end
----------------------------------------
-- Accept automatic page break or not
----------------------------------------
on AcceptPageBreak
return pAutoPageBreak
end
----------------------------------------
-- Output a cell
----------------------------------------
on Cell me, w,h,txt,border,ln,align,fill,link
if voidP(h) then h=0
txt=string(txt)
if voidP(border) then border=0
if voidP(ln) then ln=0
align=string(align)
if voidP(fill) then fill=0
--link=string(link)
if voidP(link) then link=""
if pIsMac then txt=me.mac2ansi(txt)
k=pK
if (pY+h>pPageBreakTrigger and NOT pInFooter and AcceptPageBreak()) then
x=pX
ws=pWs
if (ws>0) then
pWs=0
me._out("0 Tw")
end if
me.AddPage(pCurOrientation)
pX=x
if (ws>0) then
pWs=ws
the floatprecision=3
me._out(float(ws*k) && "Tw")
end if
end if
if (w=0) then w=pW-pRMargin-pX
s=""
if (fill=1 or border=1) then
if (fill=1) then
if (border=1) then op="B"
else op="f"
else op="S"
the floatprecision=2
s=float(pX*k) && float((pH-pY)*k) && float(w*k) && float(-h*k) && "re" && op & " "
end if
if (stringP(border)) then
x=pX
y=pY
the floatprecision=2
if (border contains "L") then s=s& float(x*k) && float((pH-y)*k) && "m" && float(x*k) && float((pH-(y+h))*k) && "l S "
if (border contains "T") then s=s& float(x*k) && float((pH-y)*k) && "m" && float((x+w)*k) && float((pH-y)*k) && "l S "
if (border contains "R") then s=s& float((x+w)*k) && float((pH-y)*k) && "m" && float((x+w)*k) && float((pH-(y+h))*k) && "l S "
if (border contains "B") then s=s& float(x*k) && float((pH-(y+h))*k) && "m" && float((x+w)*k) && float((pH-(y+h))*k) && "l S "
end if
if(txt<>"") then
if (align="R") then dx=w-pCMargin-me.GetStringWidth(txt)
else if(align="C") then dx=(w-me.GetStringWidth(txt))/2
else
dx=pCMargin
end if
txt=str_replace(")",")",str_replace("(","(",str_replace("","\",txt)))
if (pColorFlag) then s=s& "q" && pTextColor &" "
the floatprecision=2
s=s& "BT" && float((pX+dx)*k) && float((pH-(pY+.5*h+.3*pFontSize))*k) && "Td ("&txt&") Tj ET"
if (pUnderline) then s=s&& me._dounderline(pX+dx,pY+.5*h+.3*pFontSize,txt)
if (pColorFlag) then s=s&& "Q"
if (link<>"") then me.Link(pX+dx,pY+.5*h-.5*pFontSize,me.GetStringWidth(txt),pFontSize,link)
end if
if (s<>"") then me._out(s)
pLasth=h
if(ln>0) then
--Go to next line
pY=pY+h
if(ln=1) then
pX=pLMargin
end if
else pX=pX+w
end
----------------------------------------
-- Output text with automatic or explicit line breaks
----------------------------------------
on MultiCell me, w,h,txt,border,align,fill
if voidP(border) then border=0
if voidP(align) then align="J"
if voidP(fill) then fill=0
cw=pCurrentFont["cw"] -- ???
if (w=0) then w=pW-pRMargin-pX
wmax=(w-2*pCMargin)*1000.0/pFontSize
--s=str_replace(pCR,"",txt)
s=str_replace(pCR,pLF,txt)
nb=length(s)
if (nb>0 and s.char[nb]=pLF) then nb=nb-1
b=0
if (NOT voidP(border)) then
if (border=1) then
border="LTRB"
b="LRT"
b2="LR"
else
b2=""
if (border contains "L") then b2=b2& "L"
if (border contains "R") then b2=b2& "R"
if (border contains "T") then b=b2 & "T"
else b=b2
end if
end if
sep=-1
i=1 --0
j=0
l=0
ns=0
nl=1
repeat while (i --Get next character
c=s.char[i]
if (c=pLF) then
--Explicit line break
if(pWs>0) then
pWs=0
me._out("0 Tw")
end if
me.Cell(w,h, s.char[j+1..i-1],b,2,align,fill) --j+1..i
i=i+1
sep=-1
j=i -1
l=0
ns=0
nl=nl+1
if (border and nl=2) then b=b2
next repeat
end if
if (c=" ") then
sep=i -- -1--???
ls=l
ns=ns+1
end if
l=l+cw[ord(c)+1] --???
if (l>wmax) then
--Automatic line break
if (sep=-1) then
if (i=j) then i=i+1
if (pWs>0) then
pWs=0
me._out("0 Tw")
end if
me.Cell(w,h,s.char[j+1..i],b,2,align,fill)
else
if (align="J") then
if (ns>1) then pWs=(wmax-ls)/1000.0*pFontSize/(ns-1.0)
else pWs=0
the floatprecision=3
me._out(float(pWs*pK) && "Tw")
end if
me.Cell(w,h,s.char[j+1..sep-1],b,2,align,fill) --j+1
i=sep+1
end if
sep=-1
j=i -1
l=0
ns=0
nl=nl+1
if (border and nl=2) then
b=b2
end if
else
i=i+1
end if
end repeat
--Last chunk
if (pWs>0) then
pWs=0
me._out("0 Tw")
end if
if (border and (border contains "B")) then b=b& "B"
me.Cell(w,h,s.char[j+1..j+i],b,2,align,fill) --j+1
pX=pLMargin
end
----------------------------------------
-- Output text in flowing mode
----------------------------------------
on Write me, h,txt,link
if voidP(link) then link=""
cw=pCurrentFont["cw"]
w=pW-pRMargin-pX
wmax=(w-2*pCMargin)*1000.0/pFontSize
--s=str_replace(pCR,"",txt)
s=str_replace(pCR,pLF,txt)
nb=length(s)
sep=-1
i=1
j=0
l=0
nl=1
repeat while (i --Get next character
c=s.char[i]
if(c=pLF) then
--Explicit line break
me.Cell(w,h,s.char[j+1..i-1],0,2,"",0,link)
i=i+1
sep=-1
j=i
l=0
if (nl=1) then
pX=pLMargin
w=pW-pRMargin-pX
wmax=(w-2*pCMargin)*1000.0/pFontSize
end if
nl=nl+1
next repeat
end if
if (c=" ") then
sep=i
ls=l
end if
l=l+cw[ord(c)+1]--???
if (l>wmax) then
--Automatic line break
if (sep=-1) then
if (pX>pLMargin) then
--Move to next line
pX=pLMargin
pY=pY+h
w=pW-pRMargin-pX
wmax=(w-2*pCMargin)*1000.0/pFontSize
i=i+1
nl=nl+1
next repeat
end if
if (i=j) then i=i+1
me.Cell(w,h,s.char[j+1..i],0,2,"",0,link)
else
me.Cell(w,h,s.char[j+1..sep-1],0,2,"",0,link)
i=sep+1
end if
sep=-1
j=i
l=0
if (nl=1) then
pX=pLMargin
w=pW-pRMargin-pX
wmax=(w-2*pCMargin)*1000.0/pFontSize
end if
nl=nl+1
else i=i+1
end repeat
--Last chunk
if (i<>j) then me.Cell(l/1000.0*pFontSize,h,s.char[j+1..j+i],0,0,"",0,link)
end
----------------------------------------
-- Put an PNG image on the page
----------------------------------------
on addPng me, file,x,y,w,h,link
if voidP(h) then h=0
if (voidP(pImages[file])) then
--First use of image, get info
info=me._parsepng(file)
info["i"]=count(pImages)+1
pImages[file]=info
else
info=pImages[file]
end if
--Automatic width or height calculation
if (w=0) then w=h*info["w"]/info["h"]
if (h=0) then h=w*info["h"]/info["w"]
the floatprecision=2
me._out("q" && float(w*pK) &&"0 0" && float(h*pK) && float(x*pK) && float((pH-(y+h))*pK) && "cm /I" & integer(info["i"]) && "Do Q")
if (NOT voidP(link)) then me.Link(x,y,w,h,link)
end
----------------------------------------
-- Put an JPG image on the page
----------------------------------------
on addJpg me, file,depth,x,y,w,h,link
if voidP(h) then h=0
if (voidP(pImages[file])) then
--First use of image, get info
info=me._parsejpg(file, depth)
info["i"]=count(pImages)+1
pImages[file]=info
else
info=pImages[file]
end if
--Automatic width or height calculation
if (w=0) then w=h*info["w"]/info["h"]
if (h=0) then h=w*info["h"]/info["w"]
the floatprecision=2
me._out("q" && float(w*pK) &&"0 0" && float(h*pK) && float(x*pK) && float((pH-(y+h))*pK) && "cm /I" & integer(info["i"]) && "Do Q") --sprintf("q %.2f 0 0 %.2f %.2f %.2f cm /I%d Do Q",w*pK,h*pK,x*pK,(pH-(y+h))*pK,info["i"]))
if (NOT voidP(link)) then me.Link(x,y,w,h,link)
end
----------------------------------------
-- Put an image on the page
----------------------------------------
on addImg me, img,x,y,w,h,link
wi=img.width
hi=img.height
depth=img.depth
if (NOT integerP(w) OR w=0) then w=wi/pK -- original size at 72 dpi
if (NOT integerP(h) OR h=0) then h=w*hi/wi
imgStr=string(img)
if (voidP(pImages[imgStr])) then
--First use of image, get info
if (depth=8 AND img.paletteRef=#grayscale) then
colspace="DeviceGray"
else
colspace="DeviceRGB"
end if
bpc=8
--Get Image Data
data=""
if (colspace="DeviceGray") then
--Grayscale
repeat with i=0 to hi-1
repeat with j=0 to wi-1
data=data& chr(255-img.getpixel(j,i,#integer))
end repeat
end repeat
else
--RGB
repeat with i=0 to hi-1
repeat with j=0 to wi-1
col=img.getpixel(j,i)
data=data& chr(col.red) & chr(col.green) & chr(col.blue)
end repeat
end repeat
end if
info = ["w":wi,"h":hi,"cs":colspace,"bpc":bpc]
if pCompress then
--put "before" && count(data)
info["f"] = "FlateDecode"
data = me.gzcompress(data)
--put "after" && count(data)
end if
info["data"] = data
info["i"]=count(pImages)+1
pImages[imgStr]=info
else
info=pImages[imgStr]
end if
the floatprecision=2
me._out("q" && float(w*pK) &&"0 0" && float(h*pK) && float(x*pK) && float((pH-(y+h))*pK) && "cm /I" & integer(info["i"]) && "Do Q")
if (NOT voidP(link)) then me.Link(x,y,w,h,link)
end
----------------------------------------
-- Line feed; default value is last cell height
----------------------------------------
on Ln me, h
if voidP(h) then h=""
pX=pLMargin
if (stringP(h)) then pY=pY+pLasth
else pY=pY+h
end
----------------------------------------
-- Get x position
----------------------------------------
on GetX me
return pX
end
----------------------------------------
-- Set x position
----------------------------------------
on SetX me, x
if (x>=0) then pX=x
else pX=pW+x
end
----------------------------------------
-- Get y position
----------------------------------------
on GetY me
return pY
end
----------------------------------------
-- Set y position and reset x
----------------------------------------
on SetY me, y
pX=pLMargin
if (y>=0) then pY=y
else pY=pH+y
end
----------------------------------------
-- Set x and y positions
----------------------------------------
on SetXY me, x,y
me.SetY(y)
me.SetX(x)
end
----------------------------------------
-- Output PDF to file (or msg window)
----------------------------------------
on Output me, file
if (pState<3) then me.Close()
if (voidP(file)) then
return pBuffer
else
writeFile(pBuffer,file)
end if
end
----------------------------------------
-- Start document
----------------------------------------
on _begindoc me
pState=1
me._out("%PDF-1.3")
end
----------------------------------------
--
----------------------------------------
on _putpages me
nb=pPage
if (NOT voidP(pAliasNbPages)) then
--Replace number of pages
repeat with n=1 to nb
pPages[n]=str_replace(pAliasNbPages,nb,pPages[n])
end repeat
end if
if (pDefOrientation="p") then
wPt=pFwPt
hPt=pFhPt
else
wPt=pFhPt
hPt=pFwPt
end if
if (pCompress) then filter = "/Filter /FlateDecode "
else filter = ""
repeat with n=1 to nb
--Page
me._newobj()
me._out("< me._out("/Parent 1 0 R")
the floatprecision=2
if (count(pOrientationChanges)>=n) then
if pOrientationChanges[n] then me._out("/MediaBox [0 0 "&float(hPt)&&float(wPt)&"]")
end if
me._out("/Resources 2 0 R")
if (pPageLinks[n]<>[]) then
--Links
annots="/Annots ["
repeat with pl in pPageLinks[n]
the floatprecision=2
rect=float(pl[1]) && float(pl[2]) && float(pl[1]+pl[3]) && float(pl[2]-pl[4])
annots=annots& "< if (stringP(pl[5])) then annots=annots& "/A <>>>"
else
l=pLinks[pl[5]]
if (count(pOrientationChanges)>=l[1]) then h=wPt
else h=hPt
the floatprecision=2
annots=annots& "/Dest [" & integer(1+2*l[1]) && "0 R /XYZ 0" & float(h-l[2]*pK) && "null]>>"
end if
end repeat
me._out(annots & "]")
end if
me._out("/Contents " & (pN+1) & " 0 R>>")
me._out("endobj")
--Page content
p=pPages[n]
if (pCompress) then p=me.gzcompress(p)
me._newobj()
me._out("<<" & filter & "/Length " & length(p) & ">>")
me._putstream(p)
me._out("endobj")
end repeat
--Pages root
pOffsets[1]=length(pBuffer)
me._out("1 0 obj")
me._out("< kids="/Kids ["
repeat with i = 0 to nb-1
kids=kids& (3+2*i) & " 0 R "
end repeat
me._out(kids&"]")
me._out("/Count " & nb)
the floatprecision=2
me._out("/MediaBox [0 0" && float(wPt) && float(hPt) &"]")
me._out(">>")
me._out("endobj")
end
----------------------------------------
--
----------------------------------------
on _putfonts me
nf=pN
repeat with diff in pDiffs
--Encodings
me._newobj()
me._out("<>")
me._out("endobj")
end repeat
repeat with i = 1 to count(pFontFiles)
file = pPDF_FONTPATH&pFontFiles.getPropAt(i)
info = pFontFiles[i]
--Font file embedding
me._newobj()
pFontFiles[i]["n"]=pN
size=filesize(file)
if (NOT size) then me._Error("Font file not found: "&file)
me._out("< the itemdelimiter="."
if (the last item of file="z") then me._out("/Filter /FlateDecode")
me._out("/Length1 " & info["length1"])
if (NOT voidP(info["length2"])) then me._out("/Length2 " & info["length2"] & " /Length3 0")
me._out(">>")
str=readBinFile(file)
me._putstream(str)
me._out("endobj")
end repeat
repeat with i = 1 to count(pFonts)
font=pFonts[i]
k=pFonts.getPropAt(i)
--Font objects
me._newobj()
pFonts[k]["n"]=pN
name=font["name"]
me._out("< me._out("/BaseFont /" & name)
if (font["type"]="core") then
--Standard font
me._out("/Subtype /Type1")
if(name<>"Symbol" and name<>"ZapfDingbats") then
me._out("/Encoding /WinAnsiEncoding")
end if
else
--Additional font
me._out("/Subtype /"& font["type"])
me._out("/FirstChar 32")
me._out("/LastChar 255")
me._out("/Widths " & (pN+1) & " 0 R")
me._out("/FontDescriptor " & (pN+2) & " 0 R")
if (font["enc"]<>"") then
if(font["diff"]<>"") then me._out("/Encoding " & (nf+font["diff"]) & " 0 R")
else me._out("/Encoding /WinAnsiEncoding")
end if
end if
me._out(">>")
me._out("endobj")
if (font["type"]<>"core") then
--Widths
me._newobj()
cw=font["cw"]-- ???
s="["
repeat with j = 32 to 255
s=s& cw[j+1] & " "
end repeat
me._out(s & "]")
me._out("endobj")
--Descriptor
me._newobj()
s="< repeat with j = 1 to count(font["desc"])
s=s& " /"&font["desc"].getPropAt(j)&" "&font["desc"][j]
end repeat
file=font["file"]
if (file<>"") then
s=s& " /FontFile"
if (font["type"]<>"Type1") then s=s& "2"
s=s& " " & pFontFiles[file]["n"] & " 0 R"
end if
me._out(s & ">>")
me._out("endobj")
end if
end repeat
end
----------------------------------------
--
----------------------------------------
on _putimages me
if (pCompress) then filter = "/Filter /FlateDecode "
else filter = ""
repeat with i = 1 to count(pImages)
info=pImages[i]
file=pImages.getPropAt(i)
me._newobj()
pImages[file]["n"]=pN
me._out("< me._out("/Subtype /Image")
me._out("/Width "&info["w"])
me._out("/Height "&info["h"])
if (info["cs"]="Indexed") then
me._out("/ColorSpace [/Indexed /DeviceRGB "&(length(info["pal"])/3-1)&&(pN+1)&&"0 R]")
else
me._out("/ColorSpace /"&info["cs"])
if(info["cs"]="DeviceCMYK") then me._out("/Decode [1 0 1 0 1 0 1 0]")
end if
me._out("/BitsPerComponent "&info["bpc"])
if (NOT voidP(info["f"])) then me._out("/Filter /"&info["f"])
if (NOT voidP(info["parms"])) then me._out(info["parms"])
if (NOT voidP(info["trns"]) and listP(info["trns"])) then
trns=""
repeat with j = 1 to count(info["trns"]) -- -1
trns=trns& info["trns"][j]&" "&info["trns"][j]&" "
end repeat
me._out("/Mask ["&trns&"]")
end if
me._out("/Length "&length(info["data"])&">>")
me._putstream(info["data"])
me._out("endobj")
--Palette
if (info["cs"]="Indexed") then
me._newobj()
pal = info["pal"]
if (pCompress) then pal = me.gzcompress(pal)
me._out("<<"&filter&"/Length "&length(pal)&">>")
me._putstream(pal)
me._out("endobj")
end if
end repeat
end
----------------------------------------
--
----------------------------------------
on _putresources me
me._putfonts()
me._putimages()
--Resource dictionary
pOffsets[2]=length(pBuffer)
me._out("2 0 obj")
me._out("< me._out("/Font <<")
repeat with aFont in pFonts
me._out("/F"&aFont["i"]&" "&aFont["n"]&" 0 R")
end repeat
me._out(">>")
if (count(pImages)>0) then
me._out("/XObject <<")
repeat with aImage in pImages
me._out("/I"&aImage["i"]&" "&aImage["n"]&" 0 R")
end repeat
me._out(">>")
end if
me._out(">>")
me._out("endobj")
end
----------------------------------------
--
----------------------------------------
on _putinfo me
me._out("/Producer " & textstring("PDF CLASS "&pPDF_CLASS_VERSION))
if (string(pTitle)<>"") then me._out("/Title " & textstring(pTitle))
if (string(pSubject)<>"") then me._out("/Subject " & textstring(pSubject))
if (string(pAuthor)<>"") then me._out("/Author " & textstring(pAuthor))
if (string(pKeywords)<>"") then me._out("/Keywords " & textstring(pKeywords))
if (string(pCreator)<>"") then me._out("/Creator " & textstring(pCreator))
-- 20031118002711
d = the systemDate
t = d.seconds
hr = t/3600
mins = (t/60) - (hr*60)
sec = t mod 60
dat = d.year & _lz(d.month) & _lz(d.day) & _lz(hr) & _lz(mins) & _lz(sec)
me._out("/CreationDate " & textstring("D:"&dat))
end
on _lz n
if n<10 then n="0"&n
return n
end
----------------------------------------
--
----------------------------------------
on _putcatalog me
me._out("/Type /Catalog")
me._out("/Pages 1 0 R")
if (pZoomMode="fullpage") then me._out("/OpenAction [3 0 R /Fit]")
else if(pZoomMode="fullwidth") then me._out("/OpenAction [3 0 R /FitH null]")
else if(pZoomMode="real") then me._out("/OpenAction [3 0 R /XYZ null null 1]")
else if(NOT stringP(pZoomMode)) then me._out("/OpenAction [3 0 R /XYZ null null "&(pZoomMode/100)&"]")
if (pLayoutMode="single") then me._out("/PageLayout /SinglePage")
else if(pLayoutMode="continuous") then me._out("/PageLayout /OneColumn")
else if(pLayoutMode="two") then me._out("/PageLayout /TwoColumnLeft")
end
----------------------------------------
--
----------------------------------------
on _puttrailer me
me._out("/Size "&(pN+1))
me._out("/Root "&pN&" 0 R")
me._out("/Info "&(pN-1)&" 0 R")
end
----------------------------------------
--
----------------------------------------
on _enddoc me
me._putpages()
me._putresources()
--Info
me._newobj()
me._out("<<")
me._putinfo()
me._out(">>")
me._out("endobj")
--Catalog
me._newobj()
me._out("<<")
me._putcatalog()
me._out(">>")
me._out("endobj")
--Cross-ref
o=length(pBuffer)
me._out("xref")
me._out("0 "&(pN+1))
me._out("0000000000 65535 f ")
repeat with i = 1 to pN
s=string(integer(pOffsets[i]))
s="0000000000".char[1..10-length(s)]&s
me._out(s && "00000 n ")
end repeat
--Trailer
me._out("trailer")
me._out("<<")
me._puttrailer()
me._out(">>")
me._out("startxref")
me._out(o)
me._out("%%EOF")
pState=3
end
----------------------------------------
--
----------------------------------------
on _beginpage me, orientation
pPage=pPage+1
pPages[pPage]=""
pPageLinks[pPage]=[]--???
pState=2
pX=pLMargin
pY=pTMargin
pLasth=0
pFontFamily=""
--Page orientation
if (string(orientation)="") then
orientation=pDefOrientation
else
orientation=strtoupper(orientation.char[0])
if (orientation<>pDefOrientation) then pOrientationChanges[pPage]=true
end if
if (orientation<>pCurOrientation) then
--Change orientation
if (orientation="P") then
pWPt=pFwPt
pHPt=pFhPt
pW=pFw
pH=pFh
else
pWPt=pFhPt
pHPt=pFwPt
pW=pFh
pH=pFw
end if
pPageBreakTrigger=pH-pBMargin
pCurOrientation=orientation
end if
end
----------------------------------------
-- End of page contents
----------------------------------------
on _endpage me
pState=1
end
----------------------------------------
-- Begin a new object
----------------------------------------
on _newobj me
pN=pN+1
pOffsets[pN]=length(pBuffer)
me._out(pN&" 0 obj")
end
----------------------------------------
-- Underline text
----------------------------------------
on _dounderline me, x,y,txt
up=pCurrentFont["up"]
ut=pCurrentFont["ut"]
w=me.GetStringWidth(txt)+pWs*substr_count(txt," ")
the floatprecision=2
return float(x*pK) && float((pH-(y-up/1000.0*pFontSize))*pK) && float(w*pK) && float(-ut/1000.0*pFontSizePt) && "re f"
end
----------------------------------------
-- Extract info from a JPEG file
----------------------------------------
on _parsejpg me, file, depth
m=new(#bitmap)
m.filename=file
w=m.width
h=m.height
--put m.depth
m.erase()
if (depth=8) then colspace="DeviceGray"
else if (depth=24) then colspace="DeviceRGB"
else if (depth=32) then colspace="DeviceCMYK"
else me._error("unknown depth")
bpc=8
data=ReadBinFile(file)
return ["w":w,"h":h,"cs":colspace,"bpc":bpc,"f":"DCTDecode","data":data]
end
----------------------------------------
-- Extract info from a PNG file
----------------------------------------
on _parsepng me, file
f=ReadBinFile(file)
--Check signature
if (f.char[1..8]<>chr(137)&"PNG"&chr(13)&chr(10)&chr(26)&chr(10)) then me._Error("Not a PNG file: "&file)
--Read header chunk
if (f.char[13..16]<>"IHDR") then me._Error("Incorrect PNG file: "&file)
w=str2int(f.char[17..20])
h=str2int(f.char[21..24])
bpc=ord(f.char[25])
if (bpc>8) then me._Error("16-bit depth not supported: "&file)
ct=ord(f.char[26])
if (ct=0) then
colspace="DeviceGray"
else if(ct=2) then
colspace="DeviceRGB"
else if(ct=3) then
colspace="Indexed"
else me._Error("Alpha channel not supported: "&file)
if (ord(f.char[27])<>0) then me._Error("Unknown compression method: "&file)
if (ord(f.char[28])<>0) then me._Error("Unknown filter method: "&file)
if (ord(f.char[29])<>0) then me._Error("Interlacing not supported: "&file)
if (ct=2) then cols=3
else cols=1
parms="/DecodeParms <>"
--Scan chunks looking for palette, transparency and image data
pal=""
trns=""
data=""
num=34
repeat while true
n=str2int(f.char[num..num+3])
num=num+4
type=f.char[num..num+3]
num=num+4
if (type="PLTE") then
--Read palette
pal=f.char[num..num+n-1]
num=num+n+4
else if (type="tRNS") then
--Read transparency info
t=f.char[num..num+n-1]
if (ct=0) then
trns=[ord(t.char[2])]
else if (ct=2) then
trns=[ord(t.char[2]),ord(t.char[4]),ord(t.char[6])]
else
pos=offset(chr(0),t)-1
end if
if (integerP(pos)&pos>=0) then trns=[pos]
num=num+n+4
else if (type="IDAT") then
repeat with i = 0 to n-1
data=data& f.char[num+i]
end repeat
num=num+n+4
else if (type="IEND") then
nothing
else
num=num+n+4
end if
if (n=0) then exit repeat
end repeat
if (colspace="Indexed" and pal="") then me._Error("Missing palette in "&file)
return ["w":w,"h":h,"cs":colspace,"bpc":bpc,"f":"FlateDecode","parms":parms,"pal":pal,"trns":trns,"data":data]
end
----------------------------------------
--
----------------------------------------
on _putstream me, s
me._out("stream")
me._out(s)
me._out("endstream")
end
----------------------------------------
-- Add a line to the document
----------------------------------------
on _out me, s
if (pState=2) then
pPages[pPage]=pPages[pPage]& s&pLF
else
pBuffer=pBuffer& s&pLF
end if
end
----------------------------------------
-- Format a text string
----------------------------------------
on textstring s
return "("&escape(s)&")"
end
----------------------------------------
-- Add before , ( and )
----------------------------------------
on escape s
return str_replace(")",")",str_replace("(","(",str_replace("","\",s)))
end
----------------------------------------
-- convert mac string to ansi string
----------------------------------------
on mac2ansi me, str
out=""
l=str.length
repeat with i = 1 to l
c=str.char[i]
n=ord(c)
if n>127 then
out=out&chr(pMacAnsiVec[n-127])
else
out=out&c
end if
end repeat
return out
end
----------------------------------------
-- returns true if specified handler exists in object or any of its ancestor
----------------------------------------
on handlerP me, aHandler
if me.ilk = #Instance then
a = me.getAProp(#ancestor)
if a.ilk = #Instance then
fnd = handlerP(a, aHandler)
if fnd then
return 1
else
return me.handler(aHandler)
end if
end if
end if
return 0
end
Contact
MMI
36 South Court Sq
Suite 300
Newnan, GA 30263
USA