Skip to content

Instantly share code, notes, and snippets.

@rvagg
Created March 4, 2011 02:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rvagg/854088 to your computer and use it in GitHub Desktop.
Save rvagg/854088 to your computer and use it in GitHub Desktop.
<fo:block>
<fo:instream-foreign-object>
##########################################
## Layout and cm/pixel conversions
##
## We roughly calibrate the pixel size of the SVG area so that font-size="X" matches the FOP font size in points,
## this also happens to work out at about 72dpi
#set ($widthCm = 16)
#set ($cm2px = 28.35)
#macro (cm $v)$math.mul($cm2px, $v)#end
##########################################
## Settings
##
## Most of the sizing, spacing and strokes are editable here
#set ($graphStroke = 0.04)
#set ($innerLine = { "stroke": 0.01, "opacity": "0.5" })
#set ($graphInsets = { "top": 0.75, "right": 1.25, "bottom": $graphStroke, "left": 3.5 })
#set ($graphWidth = $widthCm - $graphInsets.left - $graphInsets.right)
#set ($fs9pt = 6.75) #set ($fs9ptcm = $fs9pt / $cm2px) ## rough height of 9pt characters, don't need to be exact
#set ($fs6pt = 4.25) #set ($fs6ptcm = $fs6pt / $cm2px) ## rough height of 8pt characters, don't need to be exact
#set ($graphBar = { "opacity": 0.925, "shift": 0.6, "minWidth": 0.07, "height": 0.35, "innerPercentOpacity": 0.6, "innerPercentShowThreshold": 0.07 })
#set ($graphBarMaxWidth = $graphWidth - $graphStroke)
#set ($graphBarLeft = $graphInsets.left + $graphStroke / 2)
#set ($graphBarTop = $graphInsets.top + $graphStroke / 2 + ($graphBar.shift - $graphBar.height) / 2)
#set ($breakdownBarColours = [ "#ed1c24", "#00aeef", "#8dc63f", "#662d91", "#f26522", "#0072bc", "#39b54a", "#92278f", "#f7941d", "#0054a6", "#00a651", "#ec008c", "#fff200", "#2e3192", "#00a99d", "#ed145b" ])
#set ($legend = { "top": 0.75, "shift": 0.4, "textLeft": 0.5 })
##########################################
## Collect nutrient list for this user then set up the diet ingredient list
#set ($nl = $nutrientList)
#set ($nl2 = [])
<!-- #foreach ($nutrient in $nl)#if ($analysis.diet.user.accessPlan.isAccessibleNutrient($nutrient))$nl2.add($nutrient)#end#end -->
#set ($dil = $list.reverse($analysis.diet.dietIngredients))
##########################################
## Height settings, these depend on many nutrients there are and how many ingredients (for the advanced graph)
#set ($rectH = $nl2.size() * $graphBar.shift + $graphStroke)
#set ($boxH = $rectH + $graphInsets.top + $graphInsets.bottom)
#if ($advanced) #set ($boxH = $boxH + $legend.top + $legend.shift * ($dil.size() + 1)) #end
##########################################
## Macro to draw an individual component of a break-down bar, this is pulled out of the main loop
## because it's used by both standard ingredients and the pasture special-case so is duplicated
## if it's not a macro
#macro (breakdownBar $nutrient $totalWidth $totalPerc $ingredient $quantity $i)
#set ($c = $breakdownBarColours.get($math.mod($i, $breakdownBarColours.size())))
#set ($p = $analysis.getIngredientNutrientIntakeContributionFraction($nutrient, $ingredient, $quantity))
#set ($w = $totalWidth * $p)
## no point in drawing a zero sized rectangle
#if ($w gt 0)
<rect y="#cm($top)" x="#cm($currentBarLeft)" width="#cm($w)" height="#cm($graphBar.height)" fill="$c" fill-opacity="$graphBar.opacity" />
##########################################
## If we have enough space, print the % that this ingredient makes up, space is flexible so we need to take
## that into account, we also don't want these numbers to be too distracting so they are made slightly transparent
#if ($math.min($totalPerc, 2) * $p ge $graphBar.innerPercentShowThreshold) ## multiply by $perc cause the bar could be quite small in total
#set ($t = $top + $graphBar.height / 2 + $fs6ptcm / 2)
#set ($l = $currentBarLeft + $w / 2)
<text y="#cm($t)" x="#cm($l)" fill="white" font-size="6pt" text-anchor="middle" fill-opacity="$graphBar.innerPercentOpacity">
$number.format($text.get("wizard.results.analysis.number_format.percent.1000").toString(), $p)
</text>
#end
#set ($currentBarLeft = $currentBarLeft + $w)
#end
#end
##########################################
## Macro to draw a component of the colour legend. Same deal as the previous macro, it's used by both
## standard ingredients and pasture so is declared a macro
#set ($legendTextLeft = $graphInsets.left + $legend.textLeft)
#macro (legendComponent $ingredient $i)
#set ($c = $breakdownBarColours.get($math.mod($i, $breakdownBarColours.size())))
#set ($h = $rectH + $graphInsets.top + $legend.top + $legend.shift * $i)
<rect x="#cm($graphInsets.left)" y="#cm($math.sub($h, $fs9ptcm))" width="$fs9pt" height="$fs9pt" fill="$c" stroke="none" />
<text x="#cm($legendTextLeft)" y="#cm($h)">$textHelper.getIngredientName($ingredient)</text>
#end
##########################################
## START SVG
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.0"
height="${boxH}cm" width="${widthCm}cm" viewBox="0 0 #cm($widthCm) #cm($boxH)" font-family="sans-serif,sans" text-rendering="auto"
preserveAspectRatio="xMidYMid meet" zoomAndPan="magnify" fill="black" stroke-width="0" letter-spacing="-0.05em" font-size="9pt">
<g>
##########################################
## Graph area and axis labels
#set ($graphMiddle = $graphInsets.left + $graphWidth / 2)
#set ($textLabelY = $graphInsets.top - $fs9ptcm / 2)
<text x="#cm($graphMiddle)" y="$fs9pt" font-style="italic" text-anchor="middle" font-size="8pt">$text.pdf.analysis.graph.x_axis</text>
<text x="#cm($graphInsets.left)" y="#cm($textLabelY)" font-weight="bold" text-anchor="middle">$text.get("pdf.analysis_graph.0_percent")</text>
<text x="#cm($graphMiddle)" y="#cm($textLabelY)" font-weight="bold" text-anchor="middle">$text.get("pdf.analysis_graph.100_percent")</text>
<text x="#cm($math.sub($widthCm, $graphInsets.right))" y="#cm($textLabelY)" font-weight="bold" text-anchor="middle">$text.get("pdf.analysis_graph.200_percent")</text>
#set ($lineY2 = $graphInsets.top + $rectH)
<rect x="#cm($graphInsets.left)" y="#cm($graphInsets.top)" width="#cm($graphWidth)" height="#cm($rectH)" fill="none" stroke-width="#cm($graphStroke)" stroke="rgb(0, 103, 177)" />
#foreach ($i in [ 1, 3 ])
#set ($lineX = $graphInsets.left + $graphWidth / 4 * $i)
<line x1="#cm($lineX)" y1="#cm($graphInsets.top)" x2="#cm($lineX)" y2="#cm($lineY2)" fill="none" stroke-opacity="$innerLine.opacity" stroke-width="#cm($innerLine.stroke)" stroke="rgb(0, 103, 177)" />
#end
<line x1="#cm($graphMiddle)" y1="#cm($graphInsets.top)" x2="#cm($graphMiddle)" y2="#cm($lineY2)" fill="none" stroke-width="#cm($graphStroke)" stroke="rgb(0, 103, 177)" />
##########################################
## One bar per nutrient
#foreach ($nutrient in $nl2)
#set ($component = $analysis.result.getNutrient($nutrient))
<!-- #xmlNutrientName($nutrient) -->
#set ($top = $graphBarTop + $graphBar.shift * $velocityCount)
#set ($textY = $top + ($graphBar.height / 2) + ($fs9ptcm / 2))
## Bar label
<text x="#cm(3.3)" y="#cm($textY)" font-weight="bold" text-anchor="end">$esc.xml($lastName)</text>
##########################################
## Green if nutrient requirements are met, red/purple if they are not (under or over)
#if ($component.status and $component.status.action.key != "none")
#set ($barColour = "rgb(204, 102, 153)")
#set ($textColour = "rgb(150, 39, 78)")
#else
#set ($barColour = "rgb(102, 204, 102)")
#set ($textColour = "rgb(39, 150, 39)")
#end
##########################################
## Bar width is between 0% and 200%, we cap at 200% because it's not so interesting beyond that.
## We also have a minimum width so on the standard graph it'll show up as a bump even if it's zero
#if ($component.comparisonFraction and $component.comparisonFraction > 0)
#set ($perc = $component.comparisonFraction)
#set ($width = ($perc / 2) * $graphBarMaxWidth)
#set ($width = $math.max($graphBar.minWidth, $math.min($width, $graphBarMaxWidth)))
#else
#set ($perc = 0)
#set ($width = 0)
#end
#if ($advanced)
##########################################
## For the advanced graph we iterate over each diet ingredient and draw coloured segments representing
## how much of this nutrient is supplied by that ingredient
#set ($currentBarLeft = $graphBarLeft) ## reset this each time to the far left, it'll be incremented by our macro
#foreach ($di in $dil) ## each ingredient
#breakdownBar($nutrient, $width, $perc, $di.ingredient, $di.toQuantity(), $velocityCount)
#end
##########################################
## Special case to handle the extra pasture component of the diet, if it is present
#if ($analysis.horse.pastureTime and ($analysis.pasture or $analysis.result.pastureIngredient))
#breakdownBar($nutrient, $width, $perc, $analysis.result.pastureIngredient, $analysis.result.pasture.intake, $dil.size())
#end
#else
##########################################
## For the simple graph we just draw a single coloured bar
<rect y="#cm($top)" x="#cm($graphBarLeft)" width="#cm($width)" height="#cm($graphBar.height)" fill="$barColour" fill-opacity="$graphBar.opacity" />
#end
##########################################
## Print the total % of RDI to the right of the bar
#set ($tleft = $width + $graphBarLeft + 0.1)
<text x="#cm($tleft)" y="#cm($textY)" fill="$textColour" font-size="9pt">
#messageBasedNumberFormat("wizard.results.analysis.number_format.percent", $perc, true)
</text>
#end
#if ($advanced)
##########################################
## Draw a colour legend at the underneath the graph to show which colours represent which ingredient
#foreach ($di in $dil)
#legendComponent($di.ingredient, $velocityCount)
#end
#if ($analysis.horse.pastureTime and ($analysis.pasture or $analysis.result.pastureIngredient))
#legendComponent($analysis.result.pastureIngredient, $dil.size())
#end
#end
</g>
</svg>
</fo:instream-foreign-object>
</fo:block>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment