KoalaRainbow :: Tags
Don't forget to check the examples if you
want to see these things used practically.
Top-Level Tags
The following tags may be used anywhere in MovableType templates (or in
the visualization lab). Currently, this is just the
MTKRVisualization tag, but at some point the ability to use KRQL for
textual purposes will probably be implemented.
MTKRVisualization
Creates a visualization, producing a .png image file as output.
Note that when used inside the visualization "lab", the resulting image
will always be written to "krtvis.png" in the root of the blog against
which you were authenticated. Since the visualization lab just
looks for the first blog where you have permission to edit templates,
there's no guarantee of which blog that will be (if you have multiple
blogs), although it will presumably be consistent.
When all and said and done, all that this tag will output to the
template that encloses it is an img tag pointing at the generated
visualization image.
Concept
The MTKRVisualization tag serves as the container for all of the
drawing nodes.
Filename Concerns
Unfortunately, the current implementation of MT makes it impossible to
determine the name of the file that will result from the generation of
the current template instance, at least in a sane fashion.
Automatic mechanisms to attempt to reverse engineer the information are
a lost cause because the only context information available to us is
the same information that MTEntries would set. As such, the most
intuitive approach is to have you, the user, just explicitly state the
name of the file with some help from MT's date formatting mechanism.
So here's how it works. If there is a timestamp context at the
time of the MTKRVisualization tag, the filename will be run through the
MT date formatter using the current timestamp. (The timestamp
will be set to the creation date of an entry if it's a specific entry,
or to the start of the range associated with a given archive,
etc. I provide reasonable idioms below.) If there is no
timestamp context, the filename is used as is. Processed or not,
this filename (which may include path info) is appended to the current
blog's base location to figure out where to save the file.
Of course, it's not completely that simple. Specifically, you may
find that you want to generate a bunch of visualizations at once, at
which point you need the ability to generate the filename using
KRQL. Our solution is then that we provide two attributes you can
use. If you use "filename", we treat it as a string, not a KRQL
query. We do the date magic described above, then use it.
If you use "filename_dyn" then we know it is a KRQL query, and we
evaluate it to get the string that we then pass to the date-transform,
and then we use it. When using filename_dyn you will probably
want to use the concat function that allows you to concatenate things
together. For example, you could do "concat('images/foo-',
position(), '.png')" if generating a visualization for every item in a
set. If there was date formatting involved, just put the fancy %
codes in one of the string literals. If you are going to do a
visualization on a per-entry basis, you will probably need to use
filename_dyn; see below.
For a description of the MT date tag formats, please see the MT Tag Manual Date
Tags Section. For your leisure, I include the following
suggestions. Note that "archives/" is a configurable variable on
a per-blog basis. I assume most people will follow this idiom,
but if you put them somewhere else, be sure to change archives/
appropriately. If you put them somewhere that is not directly
beneath the blog's root, you're either going to need to use relative
paths involving "..", or perhaps come up with a good solution and let
me know. (I'm developing this part last, and under time pressure,
so it's distinctly not the best solution.)
Also keep in mind with these that the default archive mappings map all
date-based archives to a single template. If you're going to be
generating more than one type of date-based archive, as things stand,
you will probably need to bind each one to a separate template
instance. Them's the breaks. Do this by going to the
'templates' page and 'create new archive template'. Once you make
this template (just copy over you existing template...), you can then
go to your 'weblog config', and on the 'archive files' page, 'create a
new template/archive type association' between the given archive type
and your new template.
- Index files. Since there's only one instance of a given
index file template, you can safely just hard-code a static path for
any visualization used in the given template. No problem.
Some possible values might be "index-vis1.png" or
"images/index-vis1.png". Clearly, if you use multiple
visualizations on a page, you need to differentiate them. If you
are manually defining separate visualizations, do that by hand.
If you are building multiple visualizations autmoatically, you will
want to use filename_dyn.
- Individual Archives. We need to use 'filename_dyn' to get
this to work peroperly. A good starting string is
"concat('archives/%Y/%m/', mtenv('entry')/basename, '-vis.png')"; this
corresponds to MT's automatic archival hierarchy.
- Daily Archives. We can just use 'filename' with date
formatting for the simple cases. A good starting string is
"archives/%Y/%m/%d/vis.png"; this corresponds to MT's automatic
archival hierarchy.
- Weekly Archives. We can just use 'filename' with date
formatting for the simple cases. A good starting string is
"archives/%Y/%m/%d-week/vis.png"; this corresponds to MT's automatic
archival hiearchy.
- Monthly Archives. We can just use 'filename' with date
formatting for the simple cases. A good starting string is
"archives/%Y/%m/vis.png"; this corresponds to MT's automatic archival
hierarchy.
- Category Archives. We need to use 'filename_dyn' to get
this to work properly. A good starting string is
"concat('archives/', mtdirify(mtenv('archive_category')/label),
'/vis.png')"; this corresponds to MT's automatic archival hierarchy.
Attributes
Note that all of the following attributes are actually KRQL queries,
but that there is no implied context, so if you choose to work with a
set, you will need to fetch it via a global set query or via a function
call (such as mtenv()). This allows for dynamically setting the
width or height of an image, if desired.
- width: Specifies the desired width of the resulting image in
pixels. May be auto if
'scale' is set to auto or auto-aspect. If auto-aspect is used, then only
width or height may be set to auto,
not both.
- height: Specifies the desired height of the resulting image in
pixels. May be auto if
'scale' is set to auto or auto-aspect. If auto-aspect is used, then only
width or height may be set to auto,
not both.
- padall: Sets the padding in pixels around the image to this
value. Padding only is relevant if you are using scale="auto",
otherwise it's up to you to keep things in bounds. Maybe that'll
change some day.
- padleft, padtop, padright, padbottom: Sets the padding in pixels
for the given side to the given value. Overrides a setting to
padall. Only used when scale="auto".
- scale: Valid values are:
- left empty. No scaling is performed. All drawing
coordinates are treated as pixel-space values, so clipping may occur.
- auto: Using
this flag indicates that before drawing the image, the bounds of the
image should be found, and that this information should be used to map
the user coordinate space so that the drawing is entirely visible
(nothing is clipped) and that it uses all the space available
(observing the pad* settings.) This means if your visualization
is 200x200 and you have a circle that is 300x300, you will see the
entire circle rather than just part of it. Likewise, if the only
thing in your drawing is a 4x4 circle, this will be scaled so that it
uses all available space. This mode does not maintain the aspect
ratio; use auto-aspect if you
want it maintained. Note that if you set both width and height to
auto, your image will
definitively have its aspect ratio maintained. The width of lines
and
the edges of shapes is not scaled; this may be good or bad.
- auto-aspect: Similar
to auto, but the aspect ratio
of the image is maintained; one vertical unit translates to the same
number of pixels as one horizontal unit. More specifically, this
mode will result in using the scale-factor (width or height) whose use
results in the entire drawing to be able to fit into the image.
Extra space will be distributed proportionately to the current
allocations of padding for the given axis unless auto is specified for that axis, in
which case the image size will be adjusted. If no padding had
been specified, the image will be centered along that axis. Note
that you may only specify auto
for either the width or height if you use this option, not both.
If you wish to set both to auto,
you should just be using auto
for scale, not auto-aspect.
- background: Specifies the background color of the image. If
not specified, this defaults to white. If specified, make sure
that you use one of the KRQL color functions, such as color(), rgb(),
or hsv(). Ex: color('green').
- imagemap: If present, indicates that a client-side image map
should be generated using the 'url' attributes attached to
square/rect/ellipse/circle nodes using the unevaluated string
provided. For example, if you use a value of "bob", a client-side
image map should be generated. The image map will precede the
<img> tag in the output of the visualization tag.
Visualization
Data/Control Tags
The following tags may only be used within a KRVisualization tag.
MTKRVsetset
All of the attributes of a MTKRVsetset tag are evaluated as KRQL
queries in a set context, and their values are saved to the KRQL global
environment using the attribute name they are associated with.
For example, the <MTKRVsetset foo="/entries[days_old(created_on) {
4"> will save the set of all entries less than 4 days old to the
variable foo. This can then be accessed later via $foo.
It is important to note that the values are not saved to the
environment until after all the queries have been evaluated. This
means that the queries in a single MTKRVsetset tag cannot depend on a
value assigned in the same tag. If you need to derive a value
from another variable, it needs to have been set in a previous tag.
MTKRVsetval
All of the attributes of a MTKRVsetset tag are evaluated as KRQL
queries in a value context, and their values are saved to the KRQL
global
environment using the attribute name they are associated with.
For
example, the <MTKRVsetval bar="add(1, 3)"> will save 3 to the
variable bar. This can later be retrieved via $bar.
It is important to note that the values are not saved to the
environment until after all the queries have been evaluated. This
means that the queries in a single MTKRVsetset tag cannot depend on a
value assigned in the same tag. If you need to derive a value
from
another variable, it needs to have been set in a previous tag.
MTKRVloop
MTKRVloop takes a set and iterates over the contents of the set
resulting from the execution of the contents of the query
attribute. For each object in the set, it creates a new singleton
set that becomes the 'current set' for the body of the loop.
Additionally, it assigns this singleton set to the variable name found
in the name attribute. This allows the value to be accessed
explicitly, without depending on the 'current set' (which quickly can
become impossible to get to.)
MTKRVloop is a container tag, and evaluates its entire contents for
each iteration of the loop. Nominally the contents of the loop
will just be other tags described in this document, but if you can
think of a useful way to use other tags and actually get values from
them, feel free to use them. Keep in mind that MTKRVisualization
only returns an img tag, so no text output is going to show up from
this.
Loops may be nested to your heart's content. To help increase
clarity (and simplify text searching), I have created additional tag
definitions like "MTKRVloop#" for 0, 1, 2, 3, and 4. You can use
these if you want, or you can just use the normal MTKRVloop for all of
your nesting needs. They're all the same inside.
Attributes
- query: the KRQL expression to evaluate to get the set that will
be the default 'current set' for all KRQL expressions evaluated within
the confines of the <MTKRVloop></MTKRVloop> pair.
- name: the variable name to assign the results of evaluating query
to.
MTKRVif
A conditional tag that evaluates the query found in the 'test'
attribute in a boolean context. If the result of the test is
true, the contents of the conditional tag are evaluated. If it is
false, they are not. I honestly don't know if the MTElse tag
works with this. My impression is that it should because we
define it as a conditional tag, but I could be wrong.
Attributes
- test: The KRQL expression to evaluate in a boolean context to
determine whether to evaluate the contents of the tag.
Visualization Draw Tags
A quick hard-coded teaser:
<MTKRVisualization width="200" height="200" bg="rgb(230, 230, 230)">
<MTKRVsquare x="50" y="50" edge="50" fillcolor="color('blue')" edgecolor="color('black')" layer="1">
<MTKRVrect x="50" y="75" width="20" height="40" fillcolor="color('#eeeeff')" edgecolor="color('black')" layer="2">
<MTKRVcircle x="100" y="100" edge="100" fillcolor="color('red')" edgecolor="color('black')" layer="0">
<MTKRVcircle x="100" y="100" edge="140" fillcolor="color('pink')" edgecolor="color('black')" layer="5" startang="0" endang="60">
<MTKRVellipse x="135" y="100" width="70" height="40" startang="180" endang="360" fillcolor="rgb(190, 240, 200)" edgecolor="color('black')" layer="3">
<MTKRVline x1="10" y1="190" x2="100" y2="100" layer="10" edgecolor="hsv(0.8, 0.8, 0.6)">
</MTKRVisualization>
The following tags may only be used within a KRVisualization tag.
common attributes (all)
- layer: Specifies the layer of the drawing node. The way
drawing works is that we find out all the layers used, then we sort
them numerically. Then, we go through each layer and draw the
contents of the layer, applying any filters associated with that layer
before we continue on to the next layer. It is important to note
that this drawing behavior only applies filters if there is some node
to draw in that layer. Layer will default to 0 if not specified.
- edgecolor: Specifies the edge color for actual shapes (circles,
squares, etc.), as well as the color of lines. Use one of the
KRQL color functions (color, rgb, hsv, etc.) to get a value for
this. This value never has a default value, and things probably
won't work if you forget to specify one.
common attributes (shapes, not lines)
Take care not to try and apply contradicting position/size
information. It'll be consistent, but possibly not what you'd
expect. Note that all of these attributes are evaluated (in a
value context.)
- fillcolor: Specifies the fill color for actual shapes. Use one of
the KRQL color functions (color, rgb, hsv, etc.) to get a value for
this. This value never has a default value, and things probably
won't work if you forget to specify one.
- width: Specifies the width of the shape.
- height: Specifies the height of the shape.
- x: Sets the x coordinate of the center point of the shape
- y: Sets the y coordinate of the center point of the shape.
- left: Sets the left of the bounding box of the shape (aka x
coordinate of upper left point defining the shape)
- top: Sets the top of the bounding box of the shape (aka y
coordinate of upper left point defining the shape)
- right: Sets the right of the bounding box of the shape (aka x
coordinate of the lower right point defining the shape)
- bottom: Sets the bottom of the bounding box of the shape (aka y
coordinate of the lower right point defining the shape)
- url: If specified, and imagemap is present on the enclosing
visualization tag, associates the provided url with the object via the
image map. There's no magic way for Koala Rainbow to know the
proper URL to something, so you may need to do some fancy
footwork. For example, if you want to link to an individual
archive page, where the entry in question is stored in the variable
$myentry, the following would be a good idea: "
MTKRVsquare
Draws a square.
Attributes (those not already found in common attributes):
- edge: sets the width and height in one go.
MTKRVrect
Draws a rectangle, which is technically referred to as a "square that
someone sat on, and then possibly rotated by 90 degrees; 270 degrees is
theoretically possible, but takes 3 times the turning, and my wrist
hurts when I try to do that."
No new attributes.
MTKRVcircle/MTKRVellipse
Draws a circle or an ellipse. They're actually the same
thing. It's a secret though, so keep it on the down low. A circle
is defined by the square in which it is circumscribed (same deal for
the ellipse.)
Attributes (those not already found in common attributes):
- edge: sets the width and height in one go.
- startang, endang: specify to only draw a wedge of the circle or
ellipse, both in degrees. endang should always be greater than
startang. 0 degrees is due east, 90 degrees is due south, 180
degrees is due west, 270 degrees is due north. At least in my
copy of ImageMagick, there appears to be a bug when the angle gets to
be 45 degrees or less; only the outgoing line is drawn, and neither the
wedge nor the completion line gets drawn. Tweaking the other
flags and variables passed seems to suggest this is ImageMagick's
problem rather than a problem with my code generating the path.
In any event, if you experience this problem, the workaround appears to
be to ensure that you subtend an angle of at least 46 degrees.
This clearly isn't the happiest solution, but it is a solution.
MTKRVline
Draw a line! fun fun fun!
Attributes (those not already found in common attributes):
- x1: x coordinate of start point
- y1: y coordinate of start point
- x2: x coordinate of end point
- y2: y coordinate of end point
- width: Specifies the width of the line (in pixels). This
value is _not_ affected by the auto-scale functionality as currently
implemented. Defaults to ImageMagick's default if omitted (which
appears to be 1-like.)
MTKRVfilter
This mechanism allows you to apply filters to your drawing to help
provide a more natural feel. At this time there really aren't so
many filters, but... some day!
It is important to note that 'layers' as implemented do not result in
separate images that are then composited together. Layers are
just a mechanism to allow a different drawing sequence to be used than
the order in which nodes are added to the image. This has been
further extended by associating filters with a layer so they are
applied after the nodes in that layer is drawn. This allows neat
tricks like drawing your image twice, once on layer 0 and once on layer
1 and then having a blur happen on layer 0. This creates a nice
(to me) soft effect behind the image, with your true drawing then laid
overtop. Clearly it would be nice to have the flexibility to do
all kinds of crazy image processing, but the key idea right now is
intuitive-ness and not enough time.
Attributes For KRVfilter
- name: Specifies the name of the filter to use, see below for
supported filters.
- layer: Specifies the layer with which this filter should be
applied. This filter will _only_ be applied if something is drawn
on the layer.
Supported Filters and their attributes:
- "blur": performs a gaussian blur
- sigma: Specifies the standard deviation of the gaussian blur to
use. This is the key value.
- radius: Specifies the radius of the blur. I think this
actually specifies the size of the convolution which would then imply
that the radius mainly allows you to cut off the convolution before the
multiplier hits zero, but that's just guesswork. Anywho, if you
omit this value, ImageMagick will pick an appropriate value for you
unless your sigma is crazy large, so feel free to omit this.
- "shade": per ImageMagick, "shade the image using a distant light
source"
- gray: boolean ("true", "false", or standard boolean logic rules
(0, undef, empty-string are false, all else true)) indicating whether
to make the image gray. (I think this mainly determines whether
the derived embossy type thing is overlaid in a lighting combine, or
used to replace the image.)
- azimuth: azimuth of the light source that does the shading,
defaults to 45.0
- elevation: elevation of the light source that does the shading,
defaults to 120.0
Copyright 2004, Andrew Sutherland