466 lines
19 KiB
Plaintext
466 lines
19 KiB
Plaintext
#+ <lib id='fgldraw1'
|
|
#+ synopsis='Functions for painting screen drawings on print media (PXML).'
|
|
#+ >
|
|
#+ <note>This library provides functions to paint screen canvas
|
|
#+ drawings, drawn with the <DVMDOCREF href="ui/fgldraw.html">ui.fgldraw</DVMDOCREF>
|
|
#+ functions on !!!PXML reports. The program <USERSRCREF href="demo/apps/canvas/canvas.4gl">canvas.4gl</USERSRCREF>
|
|
#+ demonstrates the usage of this library.
|
|
#+ If more sophisticated drawing capabilities are required, the
|
|
#+ !!!PXML drawing elements should be used directly. Particulary
|
|
#+ the <PXMLDOCREF href="layoutnode/CanvasPath.html">CANVASPATH</PXMLDOCREF>
|
|
#+ layout node should be considered as is covers most of the
|
|
#+ capabilities of the screen drawing library, providing some
|
|
#+ additional features such as cubic and quadratic bezier curves.
|
|
#+ See also <PXMLDOCREF href="layoutnode/package-summary.html#drawing">PXML Layout Nodes for Drawing</PXMLDOCREF>
|
|
#+ and <PXMLDOCREF href="layoutnode/package-summary.html#text-output">PXML Layout Nodes for Text Output</PXMLDOCREF>.
|
|
#+ Some examples of drawings, using these elements can be found
|
|
#+ <PXMLDOCREF href="layoutnode/doc-files/AllExamplesIndex.html">here</PXMLDOCREF>.
|
|
#+ </note>
|
|
#+ </lib>
|
|
define globalWidthExpr String
|
|
define globalHeightExpr String
|
|
define globalFontSize integer
|
|
|
|
globals
|
|
DEFINE __fgldraw_theCanvas om.DomNode
|
|
DEFINE __fgldraw_theCanvas_lineWidth INTEGER
|
|
end globals
|
|
|
|
#+ <function
|
|
#+ id="drawSetSize"
|
|
#+ synopsis="initializes global variables."
|
|
#+ >
|
|
#+ <param name="widthExpr" t="String">!!!PxmlExpression specifying the width of the paint area.
|
|
#+ <note>The drawing coordinate values (0..1000) are scaled into the
|
|
#+ specified width. If for example a width of "10.01cm" is specified, then
|
|
#+ then and object specified at coordinate x=499 will be drawn at
|
|
#+ position x=5cm.
|
|
#+ </note>
|
|
#+ </param>
|
|
#+ <param name="heightExpr" t="String">!!!PxmlExpression specifying the height of the paint area.
|
|
#+ <note>The drawing coordinate values (0..1000) are scaled into the
|
|
#+ specified height. If for example a height of "10.01cm" is specified, then
|
|
#+ then and object specified at coordinate y=499 will be drawn at
|
|
#+ position y=5cm.
|
|
#+ </note>
|
|
#+ </param>
|
|
#+ <param name="fontSize" t="Integer">Font size in point.
|
|
#+ <note>"widthExpr" and "heightExpr" are inserted as "width" and "length"
|
|
#+ values in the generated PXML root node. Further scaleX is set to
|
|
#+ widthExpr/1000 and scaleY to heightExpr/1000. fontSize is set to
|
|
#+ 12*heightExpr/1000.
|
|
#+ </note>
|
|
#+ </param>
|
|
#+ </function>
|
|
FUNCTION drawSetSize(widthExpr,heightExpr,fontSize)
|
|
define widthExpr String
|
|
define heightExpr String
|
|
define fontSize integer
|
|
let globalWidthExpr=widthExpr
|
|
let globalHeightExpr=heightExpr
|
|
let globalFontSize=fontSize
|
|
END FUNCTION
|
|
function initDefaults()
|
|
if globalWidthExpr is null then
|
|
let globalWidthExpr="10cm"
|
|
end if
|
|
if globalHeightExpr is null then
|
|
let globalHeightExpr="10cm"
|
|
end if
|
|
if globalFontSize is null then
|
|
let globalFontSize=12
|
|
end if
|
|
end function
|
|
#+ <function
|
|
#+ id="outputCurrentCanvasToPxml"
|
|
#+ synopsis="outputs the current canvas to the specified SAX stream."
|
|
#+ >
|
|
#+ <param name="out" t="om.SaxDocumentHandler">SaxDocumentHandler receiving PXML markup.</param>
|
|
#+ <note>Does not modify the current canvas Dom tree.
|
|
#+ </note>
|
|
#+ <note>May generate different output between calls if global variables are modified.
|
|
#+ </note>
|
|
#+ </function>
|
|
function outputCurrentCanvasToPXML(out)
|
|
define out om.SaxDocumentHandler
|
|
call initDefaults()
|
|
call outputCanvasToPXML(out,__fgldraw_theCanvas)
|
|
end function
|
|
|
|
function outputCanvasToPXML(out,canvasRoot)
|
|
define out om.SaxDocumentHandler
|
|
define canvasRoot om.DomNode
|
|
define n om.DomNode
|
|
call outputMappedNodePre(out,canvasRoot)
|
|
let n=canvasRoot.getFirstChild()
|
|
while n is not null
|
|
call outputCanvasToPxml(out,n)
|
|
let n=n.getNext()
|
|
end while
|
|
call outputMappedNodePost(out,canvasRoot)
|
|
end function
|
|
function outputMappedNodePre(out,node)
|
|
define out om.SaxDocumentHandler
|
|
define node om.DomNode
|
|
define a om.SaxAttributes
|
|
define name,s String
|
|
let name=node.getTagName()
|
|
if name.equals("CanvasLine") then
|
|
call outputCanvasLinePre(out,node)
|
|
else
|
|
if name.equals("CanvasText") then
|
|
call outputCanvastextPre(out,node)
|
|
else
|
|
if name.equals("CanvasRectangle") then
|
|
call outputCanvasRectanglePre(out,node)
|
|
else
|
|
if name.equals("CanvasCircle") then
|
|
call outputCanvasCirclePre(out,node)
|
|
else
|
|
if name.equals("CanvasOval") then
|
|
call outputCanvasOvalPre(out,node)
|
|
else
|
|
if name.equals("CanvasPolygon") then
|
|
call outputCanvasPolygonPre(out,node)
|
|
else
|
|
if name.equals("CanvasArc") then
|
|
call outputCanvasArcPre(out,node)
|
|
else
|
|
call outputCanvasRootPre(out,node)
|
|
end if
|
|
end if
|
|
end if
|
|
end if
|
|
end if
|
|
end if
|
|
end if
|
|
end function
|
|
function outputMappedNodePost(out,node)
|
|
define out om.SaxDocumentHandler
|
|
define node om.DomNode
|
|
define name String
|
|
let name=node.getTagName()
|
|
if name.equals("CanvasLine") then
|
|
call outputCanvasLinePost(out)
|
|
else
|
|
if name.equals("CanvasText") then
|
|
call outputCanvasTextPost(out)
|
|
else
|
|
if name.equals("CanvasRectangle") then
|
|
call outputCanvasRectanglePost(out)
|
|
else
|
|
if name.equals("CanvasCircle") then
|
|
call outputCanvasCirclePost(out)
|
|
else
|
|
if name.equals("CanvasOval") then
|
|
call outputCanvasOvalPost(out)
|
|
else
|
|
if name.equals("CanvasPolygon") then
|
|
call outputCanvasPolygonPost(out)
|
|
else
|
|
if name.equals("CanvasArc") then
|
|
call outputCanvasArcPost(out)
|
|
else
|
|
call outputCanvasRootPost(out)
|
|
end if
|
|
end if
|
|
end if
|
|
end if
|
|
end if
|
|
end if
|
|
end if
|
|
end function
|
|
function getLineWidth()
|
|
return getLineWidth1(__fgldraw_theCanvas_lineWidth)
|
|
end function
|
|
function getLineWidth1(lineWidth)
|
|
define lineWidth integer
|
|
define s String
|
|
let s=globalHeightExpr||"/1000point"
|
|
return lineWidth||"/("||s||")"
|
|
end function
|
|
function outputCanvasLinePre(out,node)
|
|
define out om.SaxDocumentHandler
|
|
define node om.DomNode
|
|
define s String
|
|
define a om.SaxAttributes
|
|
LET a=om.SaxAttributes.create()
|
|
call a.addAttribute("startX",node.getAttribute("startX"))
|
|
call a.addAttribute("startY",node.getAttribute("startY"))
|
|
call a.addAttribute("endX",node.getAttribute("endX"))
|
|
call a.addAttribute("endY",node.getAttribute("endY"))
|
|
#CanvasLine is the only node type where the lineWidth is passed in the
|
|
#DOM tree.
|
|
call a.addAttribute("lineWidth",getLineWidth1(node.getAttribute("width")))
|
|
let s=getAttributeValueDom(node,"fillColor")
|
|
#when color is null -> black
|
|
if s is null then
|
|
call a.addAttribute("lineColor","black")
|
|
else
|
|
call a.addAttribute("lineColor",s)
|
|
end if
|
|
if not compatibleWith704()
|
|
then
|
|
call a.addAttribute("layoutDirection","swapped")
|
|
call a.addAttribute("swapX","swapped")
|
|
end if
|
|
call out.startElement("CANVASLINE",a)
|
|
end function
|
|
function outputCanvasLinePost(out)
|
|
define out om.SaxDocumentHandler
|
|
call out.endElement("CANVASLINE")
|
|
end function
|
|
#feature request, not compatible to gui clients, leads to incompatibilities
|
|
#in test suite where large text overwrites background in some cases.
|
|
function setTextBackground(a,node)
|
|
define a om.SaxAttributes
|
|
define node om.DomNode
|
|
define bgColor String
|
|
let bgColor=node.getAttribute("fillColor")
|
|
#treat "white" as transparent
|
|
#if you need white write "#ffffff" instead.
|
|
if not bgColor.equals("white") then
|
|
call a.addAttribute("bgColor",bgColor)
|
|
end if
|
|
end function
|
|
function outputCanvasTextPre(out,node)
|
|
define out om.SaxDocumentHandler
|
|
define node om.DomNode
|
|
define s,bgColor String
|
|
define a om.SaxAttributes
|
|
LET a=om.SaxAttributes.create()
|
|
call a.addAttribute("text",node.getAttribute("text"))
|
|
|
|
# call setTextBackground(a,node)
|
|
|
|
let s=getAttributeValueDom(node,"anchor")
|
|
if s is null then
|
|
call a.addAttribute("x",node.getAttribute("startX"))
|
|
call a.addAttribute("y",node.getAttribute("startY"))
|
|
else
|
|
if s.equals("sw") or s.equals("ws") then
|
|
call a.addAttribute("x",node.getAttribute("startX"))
|
|
call a.addAttribute("y",node.getAttribute("startY"))
|
|
else
|
|
if s.equals("se") or s.equals("es") then
|
|
call a.addAttribute("x",node.getAttribute("startX")||"-length(\""||quote(node.getAttribute("text"))||"\")")
|
|
call a.addAttribute("y",node.getAttribute("startY"))
|
|
else
|
|
if s.equals("ne") or s.equals("en") then
|
|
call a.addAttribute("x",node.getAttribute("startX")||"-width(\""||quote(node.getAttribute("text"))||"\")")
|
|
call a.addAttribute("y",node.getAttribute("startY")||"-length(\""||quote(node.getAttribute("text"))||"\")")
|
|
else
|
|
if s.equals("nw") or s.equals("wn") then
|
|
call a.addAttribute("x",node.getAttribute("startX"))
|
|
call a.addAttribute("y",node.getAttribute("startY")||"-length(\""||quote(node.getAttribute("text"))||"\")")
|
|
else
|
|
if s.equals("s") then
|
|
call a.addAttribute("x",node.getAttribute("startX")||"-width(\""||quote(node.getAttribute("text"))||"\")/2")
|
|
call a.addAttribute("y",node.getAttribute("startY"))
|
|
else
|
|
if s.equals("n") then
|
|
call a.addAttribute("x",node.getAttribute("startX")||"-width(\""||quote(node.getAttribute("text"))||"\")/2")
|
|
call a.addAttribute("y",node.getAttribute("startY")||"-length(\""||quote(node.getAttribute("text"))||"\")")
|
|
else
|
|
if s.equals("e") then
|
|
call a.addAttribute("x",node.getAttribute("startX")||"-width(\""||quote(node.getAttribute("text"))||"\")")
|
|
call a.addAttribute("y",node.getAttribute("startY")||"-length(\""||quote(node.getAttribute("text"))||"\")/2")
|
|
else
|
|
if s.equals("w") then
|
|
call a.addAttribute("x",node.getAttribute("startX"))
|
|
call a.addAttribute("y",node.getAttribute("startY")||"-length(\""||quote(node.getAttribute("text"))||"\")/2")
|
|
end if
|
|
end if
|
|
end if
|
|
end if
|
|
end if
|
|
end if
|
|
end if
|
|
end if
|
|
end if
|
|
call a.addAttribute("selfPlacing","true");
|
|
call a.addAttribute("selfAdjusting","true");
|
|
if compatibleWith704()
|
|
then
|
|
call a.addAttribute("orientation","vertical");
|
|
call a.addAttribute("fillingDirection","lrtb");
|
|
call a.addAttribute("mirrored","true");
|
|
end if
|
|
call out.startElement("WORDBOX",a)
|
|
end function
|
|
function outputCanvasTextPost(out)
|
|
define out om.SaxDocumentHandler
|
|
call out.endElement("WORDBOX")
|
|
end function
|
|
function outputCanvasRectanglePre(out,node)
|
|
define out om.SaxDocumentHandler
|
|
define node om.DomNode
|
|
define s String
|
|
define a om.SaxAttributes
|
|
LET a=om.SaxAttributes.create()
|
|
#here the attachment point is "se"
|
|
call a.addAttribute("lineColor","black")
|
|
call a.addAttribute("lineWidth",getLineWidth())
|
|
call a.addAttribute("color",node.getAttribute("fillColor"))
|
|
call a.addAttribute("xyList",node.getAttribute("startX")||" "||
|
|
node.getAttribute("startY")||" "||
|
|
node.getAttribute("endX")||" "||
|
|
node.getAttribute("startY")||" "||
|
|
node.getAttribute("endX")||" "||
|
|
node.getAttribute("endY")||" "||
|
|
node.getAttribute("startX")||" "||
|
|
node.getAttribute("endY"))
|
|
if not compatibleWith704()
|
|
then
|
|
call a.addAttribute("layoutDirection","swapped")
|
|
call a.addAttribute("swapX","swapped")
|
|
end if
|
|
call out.startElement("CANVASPOLYGON",a)
|
|
end function
|
|
function outputCanvasRectanglePost(out)
|
|
define out om.SaxDocumentHandler
|
|
call out.endElement("CANVASPOLYGON")
|
|
end function
|
|
function outputCanvasCirclePre(out,node)
|
|
define out om.SaxDocumentHandler
|
|
define node om.DomNode
|
|
define s String
|
|
define a om.SaxAttributes
|
|
LET a=om.SaxAttributes.create()
|
|
call a.addAttribute("lineColor","black")
|
|
call a.addAttribute("lineWidth",getLineWidth())
|
|
call a.addAttribute("color",node.getAttribute("fillColor"))
|
|
#Attachment point is "ne" of bounding rect
|
|
call a.addAttribute("startX",node.getAttribute("startX")||"+0.5*"||node.getAttribute("diameter"))
|
|
call a.addAttribute("startY",node.getAttribute("startY")||"-0.5*"||node.getAttribute("diameter"))
|
|
call a.addAttribute("radius",node.getAttribute("diameter")||"/2")
|
|
if not compatibleWith704()
|
|
then
|
|
call a.addAttribute("layoutDirection","swapped")
|
|
call a.addAttribute("swapX","swapped")
|
|
end if
|
|
call out.startElement("CANVASOVAL",a)
|
|
end function
|
|
function outputCanvasCirclePost(out)
|
|
define out om.SaxDocumentHandler
|
|
call out.endElement("CANVASOVAL")
|
|
end function
|
|
function outputCanvasOvalPre(out,node)
|
|
define out om.SaxDocumentHandler
|
|
define node om.DomNode
|
|
define s String
|
|
define a om.SaxAttributes
|
|
LET a=om.SaxAttributes.create()
|
|
call a.addAttribute("lineColor","black")
|
|
call a.addAttribute("lineWidth",getLineWidth())
|
|
call a.addAttribute("color",node.getAttribute("fillColor"))
|
|
call a.addAttribute("radiusX","0.5*("||node.getAttribute("endX")||"-"||node.getAttribute("startX")||")")
|
|
call a.addAttribute("radiusY","0.5*("||node.getAttribute("endY")||"-"||node.getAttribute("startY")||")")
|
|
#Attachment point is "ne" of bounding rect
|
|
call a.addAttribute("startX",node.getAttribute("startX")||"+"||a.getValue("radiusX"))
|
|
call a.addAttribute("startY",node.getAttribute("startY")||"+"||a.getValue("radiusY"))
|
|
if not compatibleWith704()
|
|
then
|
|
call a.addAttribute("layoutDirection","swapped")
|
|
call a.addAttribute("swapX","swapped")
|
|
end if
|
|
call out.startElement("CANVASOVAL",a)
|
|
end function
|
|
function outputCanvasOvalPost(out)
|
|
define out om.SaxDocumentHandler
|
|
call out.endElement("CANVASOVAL")
|
|
end function
|
|
function outputCanvasPolygonPre(out,node)
|
|
define out om.SaxDocumentHandler
|
|
define node om.DomNode
|
|
define s String
|
|
define a om.SaxAttributes
|
|
LET a=om.SaxAttributes.create()
|
|
#Canvas is drawn without border
|
|
#call a.addAttribute("lineColor","black")
|
|
#call a.addAttribute("lineWidth",getLineWidth())
|
|
call a.addAttribute("color",node.getAttribute("fillColor"))
|
|
#list is really a yxList
|
|
call a.addAttribute("swapXY","true")
|
|
call a.addAttribute("xyList",node.getAttribute("xyList"))
|
|
if not compatibleWith704()
|
|
then
|
|
call a.addAttribute("layoutDirection","swapped")
|
|
call a.addAttribute("swapX","swapped")
|
|
end if
|
|
call out.startElement("CANVASPOLYGON",a)
|
|
end function
|
|
function outputCanvasPolygonPost(out)
|
|
define out om.SaxDocumentHandler
|
|
call out.endElement("CANVASPOLYGON")
|
|
end function
|
|
function outputCanvasArcPre(out,node)
|
|
define out om.SaxDocumentHandler
|
|
define node om.DomNode
|
|
define s String
|
|
define a om.SaxAttributes
|
|
LET a=om.SaxAttributes.create()
|
|
call a.addAttribute("lineColor","black")
|
|
call a.addAttribute("lineWidth",getLineWidth())
|
|
call a.addAttribute("color",node.getAttribute("fillColor"))
|
|
#Attachment point is "ne" of bounding rect
|
|
call a.addAttribute("startX",node.getAttribute("startX")||"+0.5*"||node.getAttribute("diameter"))
|
|
call a.addAttribute("startY",node.getAttribute("startY")||"-0.5*"||node.getAttribute("diameter"))
|
|
call a.addAttribute("radius",node.getAttribute("diameter")||"/2")
|
|
call a.addAttribute("startDegrees",node.getAttribute("startDegrees"))
|
|
call a.addAttribute("extentDegrees",node.getAttribute("extentDegrees"))
|
|
#call a.addAttribute("startAngle","rad("||node.getAttribute("startDegrees")||")")
|
|
#call a.addAttribute("extendAngle","rad("||node.getAttribute("extentDegrees")||")")
|
|
if not compatibleWith704()
|
|
then
|
|
call a.addAttribute("layoutDirection","swapped")
|
|
call a.addAttribute("swapX","swapped")
|
|
end if
|
|
call out.startElement("CANVASARC",a)
|
|
end function
|
|
function outputCanvasArcPost(out)
|
|
define out om.SaxDocumentHandler
|
|
call out.endElement("CANVASARC")
|
|
end function
|
|
function outputCanvasRootPre(out,node)
|
|
define out om.SaxDocumentHandler
|
|
define node om.DomNode
|
|
define s String
|
|
define a om.SaxAttributes
|
|
LET a=om.SaxAttributes.create()
|
|
if compatibleWith704()
|
|
then
|
|
call a.addAttribute("orientation","vertical")
|
|
call a.addAttribute("fillingDirection","rlbt")
|
|
else
|
|
call a.addAttribute("layoutDirection","bottomToTop")
|
|
end if
|
|
call a.addAttribute("width","1000point")
|
|
call a.addAttribute("length","1000point")
|
|
call a.addAttribute("scaleX",globalWidthExpr||"/1000point")
|
|
call a.addAttribute("scaleY",globalHeightExpr||"/1000point")
|
|
call a.addAttribute("fontSize",globalFontSize||"/("||a.getValue("scaleY")||")")
|
|
#call a.addAttribute("bgColor","#c0c0c0")
|
|
call out.startElement("LAYOUTNODE",a)
|
|
end function
|
|
function outputCanvasRootPost(out)
|
|
define out om.SaxDocumentHandler
|
|
call out.endElement("LAYOUTNODE")
|
|
end function
|
|
|
|
function quote(s)
|
|
define s,result,c String
|
|
define i,l integer
|
|
let result=" ";
|
|
let result=result.trim()
|
|
let l=s.getLength()
|
|
for i =1 to l
|
|
let c=s.getCharAt(i)
|
|
if c.equals("\\") then
|
|
let result=result||c
|
|
end if
|
|
let result=result||c
|
|
end for
|
|
return result
|
|
end function
|