The export as SVG is indeed easy.
I've added this helper class to CardsMorphic-StephanEggermont.56
It is not well-factored, and for now ignores font families.
A class helper method to directly create a file:
CardSvgWriter class>newFile: aString on: aCardWall
^self new write: aCardWall to: (aString asFileReference writeStream )
Write a SVG header, the size and then the contents of the cardwall,
finally close the SVG.
CardSvgWriter>>write: aWall to: aStream
stream := aStream.
stream nextPutAll: self fileHeader.
self fileSized: aWall fullFrame.
stream cr.
aWall cardSpace submorphsDo: [ :column |
self writeColumn: column].
stream nextPutAll: '</svg>'.
stream close
SVG is an XML format
CardSvgWriter>>fileHeader
^'<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
'
Take the SVG size from the CardWall morph. Two namespaces are needed,
the second one to make the images work.
CardSvgWriter>>fileSized: frame
stream nextPutAll: '<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" viewBox = "',
(frame left) asString,' ',
(frame top) asString,' ',
(frame width) asString,' ',
(frame height) asString,'" version = "1.1">'
For each column, write the title and a gray background
CardSvgWriter>>writeColumn: aColumn
|background|
stream nextPutAll: '<text x="',(aColumn left+2) asString,'"
y="',(aColumn top+2) asString,'" fill="gray" font-size= "11">'.
stream nextPutAll: aColumn title.
stream nextPutAll: '</text>'.
stream cr.
background := aColumn submorphs first.
stream nextPutAll: '<rect x= "',(background left) asString,
'" y="',(background top) asString,
'" width="',(background width) asString,
'" height="',(background height) asString,
'" fill="rgb(250,250,250)" />'.
stream cr.
background submorphsDo: [ :card | self writeCard: card ].
for each card, write its components
CardSvgWriter>>writeCard: aCard
self writeCardRectangle: aCard.
self writeCardText: aCard.
self writeCardImage: aCard
The rectangle still has hardcoded border and borderColor
CardSvgWriter>>writeCardRectangle: aCard
stream nextPutAll: '<rect x= "',(aCard left) asString,
'" y="',(aCard top) asString,
'" width="',(aCard width) asString,
'" height="',(aCard height) asString,
'" stroke="','rgb(240,240,240)'"aCard borderColor asHTMLColor",
'" stroke-width="', '1',"aCard borderWidth asString,"
'" fill="',aCard color asHTMLColor,'" />'.
stream cr.
Positioning of text is different in SVG and Morphic. In SVG,
it is the left-bottom, vs left-top in Morphic.
CardSVGWriter>>writeCardText: aCard
stream nextPutAll: '<text x="',(aCard left+2) asString,'" y="',(aCard
top+12) asString,'" fill="black" font-size= "10">'.
stream nextPutAll: aCard title.
stream nextPutAll: '</text>'.
stream cr.
The avatars are jpegs. they need to be base64 encoded.
Here they are repeated for each card, they should be
written once and linked.
CardSVGWriter>writeCardImage: aCard
aCard person ifNotNil: [
stream nextPutAll: '<image x="',(aCard right-32) asString,'"
y="',(aCard bottom-32) asString,'" width="32" height="32"
xlink:href="data:image/jpg;base64,',
(ZnUtils encodeBase64: (ByteArray streamContents: [:s |
PluginBasedJPEGReadWriter putForm: (AvatarCache default imageFor:
aCard person) onStream: s]))
,'"/>'.
stream cr]