Package cox.jmatt.java.MathTools.markup.svg

This is MathTools' SVG implementation.

See:
          Description

Class Summary
CircleTag This class handles the SVG <circle> tag.
ClipTag This class implements the <clipPath> tag.
DrawableContainerTag This class provides the abstract superclass for the SVG tags that can contain other tags (container tags) and the methods to add those tags quickly, easily, and conveniently (drawable).
EllipseTag This class provides the SVG <ellipse> tag.
GradientTag This class provides both <linearGradient> and <radialGradient> tags.
GroupTag This class implements the group tag, <g>.
LineTag This class generates SVG <line> tags; lines from one point to another.
MarkerPen Use this class to place markers on any entity able to accept them.
MarkerTag This class implements the <marker> tag.
MaskTag This class implements the <mask> tag.
MathDrawSVG This class furnishes instances of SVG tag classes.
PathTag This class encapsulates the SVG <path> tag.
PatternTag This class provides the <pattern> tag.
PolygonTag This class provides both the <polygon> and <polyline>: tags.
RectangleTag This class provides the SVG <rect> tag: rectangles.
StylePen This is the SVG class used to encapsulate CSS rules and 'style=' attributes.
StyleTag This class provides the basic machinery for the other SVG tags.
SVGTag This class encapsulates the <svg> tag.
SymbolTag This class encapsulates the <symbol> tag.
TextPen This StylePen subclass is designed and optimized for styling text.
TextTag This class handles the SVG <text> tag.
TransformPen This pen provides an easy way to create a sequence of transformations for an SVG tag 'transform=' attribute.
TSpanTag The TSpanTag class encapsulates the <tspan> tag, which is basically a <text> tag within another <text> tag.
UseTag This class implements the SVG <use> tag.
 

Enum Summary
StyleTag.TagKeys This enum is used internally by the SVG classes to store defaults and other such information.
 

Package cox.jmatt.java.MathTools.markup.svg Description

This is MathTools' SVG implementation. The classes here exactly mirror SVG tags and provide methods for setting attributes and content properly. Where possible values are constrained to prevent invalid values, whether by accident or design. Each tag has its own class (with a few limited, special-case exceptions) and the classes themselves are organized logically so that the range of attributes and options available increases 'down' the subclassing chain.

Presentation styling is done via CSS. The StylePen, a StyleInfo subclass, provides the basic styling options available to all tags. It has two specialized subclasses: MarkerPen and TextPen. The former is optimized for placing markers along paths and the latter has text-specific methods and options. The tag classes are written specifically to separate structure from presentation: no individual attributes are used for style information. The 'style=' attribute is an option, but the preferred way is to establish a CSS rule and use and re-use it throughout the document.

Styles and Pens: A Metaphor

MathTools SVG, much as does the graphing.* package, uses the metaphor of pen and paper to model its behavior. To wit, the structure elements represent the paper with the CSS styling as the pen. There are four __Pen classes: Style, Marker, Text, and Transform. StylePen is the base styling class. It has methods for setting stroke color, fill color, URLs, and other such things dealing with making the graphic look good.

A StylePen, once configured, can be used one of two ways. The structure tags ('paper') have setStyle(StylePen) methods that convert the StylePen directly to a 'style=' attribute on the tag to which it is applied. This allows individual tags requiring only one or two different things to have them without defining a CSS rule that only one or two tags might use.

For defining broad CSS rules that multiple tags will use, each pen has a setPen(int) method for assigning a pen number. StyleTag also specifies a setPen(int) method, but this one is used to assign the CSS rule defined by the pen to that tag. When output as a document, the result is something like this:

     <!-- CSS Stylesheet -->
        .Pen_0 { stroke:blue; fill:none; stroke-width: 3; }
        .Pen_1 { stroke: black; fill: #888; }
. . .
<!-- Document Content --> <circle cx='25' cy='40' r='10' class='Pen_1' />
When added to the document, StylePen assigned the pen number '1' becomes the CSS rule 'Pen_1'. Any StyleTag assigned pen #1 has its 'class=' attribute set to 'Pen_1'. CSS made simple!

When using the various StylePens it is important to understand how they are actually set. The setStyle() method and its defaults instantly convert the pen to an immutable String, thus 'freezing' it as soon as it is added. The pen can be changed subsequently and the already-set tags will not change! This is handy when using 'style=' attributes since it allows one pen to be re-used for all tags. On the other hand, using the pen numbers does not freeze things, it only sets the 'class=' CSS attribute to the given 'Pen_' value and that can be changed. Under this model the pen remains mutable until it is added to the document itself: SVGTag add(StylePen) does this. Up until that point any changes in the pen will be reflected in all the tags using it because setting a pen number in fact sets a reference to that pen!

The TransformPen deserves special attention. It does not extend StylePen and it is used for one purpose only: holding transforms. It has methods to add each kind of transform available and it retains them, in order. Although technically transformation is more structure than presentation, the model fit nicely so it was used. As with other pens, once added to a tag TransformPen is 'frozen' into String form. That means the pen can be altered later and re-used without affecting the tag(s) to which it has already been applied.

Defaults and Drawing: Speeding Up the Process

StyleTag, in addition to setter methods for each tag class, also specifies default setters: a default style, pen number, or both can be assigned to any subclass! So, if you are preparing to draw a lot of similar lines (or circles!), simply deside how each is to be styled, assign a pen number and make that the default pen number for that particular class. Then, when it's no longer needed, clear the default or replace it with another. Simple!

Speaking of drawing, the DrawableContainerTag is optimized for just such a thing. The 'container' part means that this class (tag) is used to hold other classes (tags). For example the <svg> tag serves as the document root so of course it is a container! These classes all have 'add__()' methods for putting graphic content where it is needed.

The 'drawable' part means that each of these classes has a set of draw__() methods designed to take the minimum necessary information about a tag, create an instance from it, and add it to the container's content. drawLine(X1, Y1, X2, Y2) creates a <LineTag> with the given points and adds it to the container in one fell swoop.

When combined, the default style setters and 'draw' methods equal one powerful and fast way to add tags to a document. Set the default pen (style declarations) for the needed tags and go to town with it. The draw__() methods take the minimum amount of required structural information, but they do require sufficiency! The tag added to the container will have enough information (modulo style information, handled with default pens) to add a proper tag!

It is also worth noting that there is no reason whatsoever that both models cannot be combined. Graphics requiring large numbers of basically similar tags with a few specials should use both creation methods: draw__() the similar tags, which are added automatically, and create and add the special tags individually.

Getting Things Started

The MathDrawSVG class exists to provide tag class instances and to set defaults. It is somewhat analogous to a GraphEngine in that it provides what is necessary to create graphics. It is different in that it can also set default values in the form of styling and transformation pens for each type of tag it creates. As with draw__() methods, MathDrawSVG also ensures that sufficient information is available to create a tag. ClipTag, for instance, must have a valid 'id=' attribute. This is because the <clipPath> tag lives inside the <defs> block and cannot be referenced without a valid ID. Whenever this is the case, both the class constructors or factory methods and MathDrawSVG make certain the mandatory information is supplied.

For those using MathTools in a Java application it is possible to instantiate the SVG classes directly. This works, and will create tags properly, but it is still a better idea to use MathDrawSVG. It collects all the tag classes, pens, and default-setting methods in one class. It also performs certain housekeeping tasks 'under the hood' on a per-tag as-needed basis. Direct instantiation works, but MathDrawSVG is designed for the purpose.

Units and Measurement

One glaring omission in the SVG package concerns units of measurement. The W3C SVG specification allows individual units to be attached to numbers in almost all SVG tags with numeric attributes. MathTools does not allow this! This exclusion is deliberate. Not allowing units on individual tags prevents massive careless errors caused by using incorrect units or simply misspelling them. Casting numerical values as double, or Double when they might be null, is one of MathTools' strongest goof-proofing features.

Individual unit omission is also good error-protection in another way: structural. While many tags do allow units, some do not. Some tags omit units by the specification and automatically adopt the units of their parent tag, or user units which may be radically different from what is desired. Leaving units off the individual tags requires that the document itself (SVGTag) establish a uniform and consistent coordiante system for all of its elements. Since creating an <svg> tag absolutely requires a non-null, non-empty width and height this is guaranteed.

For best results (and fewest headaches) first establish the overall size of the graphic. Set the width and height accordingly. Next set the viewport to a convenient number of user units per established unit (setViewBox()). The MathDrawSVG getLetter() method does this: the width and height are '8.5in' and '11in' respectively and the viewport is set to '0 0 850 1100'. This gives 100 user units per inch in both dimensions and all contained tags use this consistently.