Created
March 4, 2011 02:52
-
-
Save rvagg/854088 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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