# VectorImage Demo

## What Is It

A `VectorImage` contains vector-based rendering instructions to represent/recreate an image.

## How To Use It

Some possible use cases include storing painting instructions:

    VectorImage myImage = new VectorImage();
    Graphics2D g = myImage.createGraphics();
    myComponent.paint(g);
    g.dispose();

Or replaying those instructions:

    VectorImage myImage = ...;
    myImage.paint(otherGraphics2D);

Or inspecting painting instructions:

    VectorImage myImage = ...;
    List ops = myImage.getOperations();
    for(Operation op : ops) {
      // alter or examine certain operations
    }

Or serialization:

    VectorImage myImage = new VectorImage(inputStream);
    myImage.save(outputStream);

## How It Works

There are `com.pump.graphics.vector.Operation` objects that can represent all the methods in `Graphics2D` that render data. And the `VectorGraphics2D` stores a running list of these `Operations`.

The `VectorImage` is just a wrapper for that `List` of operations.

Also this architecture introduces the `Graphics2DContext` object to document the state (stroke, clipping, transform, etc.) of any `Graphics2D` and its operations.

## Discussion

### Usages

The original intended use case for this class was for debugging. Have you ever had a stray line or artifact in your UI? This object lets you diagram every rendering operation. You can even add the stack trace that triggered each call, so you can pinpoint exactly what code is responsible for rendering each pixel.

(If you take a screenshot in the demo by pressing F6, then as you adjust the demo's slider you see a tooltip showing exactly what line of source code each rendering operation originated from.)

But once I had the `VectorImage` in my toolbelt I found lots of other uses for it. For example: most of the sliders in this showcase app include a popover that points directly at the thumb. How do I know where the thumb is? As long as the `SliderUI` is a `BasicSliderUI`, I can call:

    VectorImage img = new VectorImage();
    myBasicSliderUI.paintThumb(img.createGraphics());
    Rectangle2D thumbBounds = img.getBounds();

Also this architecture is used in the QHTML classes in a few places. For example: we use it to apply shadows to text. We render everything using Swing's default renderer to a `VectorGraphics2D`, and then (with the help of some well-placed `RenderingHints`) we isolate each `Operation` and apply a shadow as needed.

### Serialization

Making the `VectorImage` serializable was a lot more work than expected.

Many java.awt classes are not Serializable: `java.awt.BasicStroke`, `java.awt.AlphaComposite`, `java.awt.Shape`, `java.awt.RenderingHints`, etc.

I ended up creating a whole separate architecture just to address this. Its core usage boils down to:

    Object obj = ConverterUtils.readObject(objectInputStream);

... and ...

    ConverterUtils.writeObject(objectOutputStream, obj);

The `ConverterUtils` class includes over a dozen filters (`BeanMapConverters`) that break up unserializable classes into named key/value pairs. So in addition to serialization it also includes helper methods like:

    String str = ConverterUtils.toString(obj);

... and ...

    ConverterUtils.equals(obj1, obj2);

### JVG / SVG Files

If you're familiar with vector graphics then you're probably familiar with the SVG file format.

It seemed like a natural extension of this project to try to serialize the `VectorImage` too. I decided to use the file extension JVG ("Java Vector Graphics").

Obviously there are a couple of similarities between SVG and JVG, but they are also radically different. In summary: SVG is complex and powerful, and JVG is just a serialized wrapper for what the `Graphics2D` supports. SVG supports animation, scripts, and filters. And it is written in XML, which makes it slightly human-readable.

(It's also worth mentioning that the `VectorImage` doesn't even promise to perfectly replicate all `Graphics2D` calls. It works with simple `BufferedImages`, but if you use a more complex or abstract image (like an animated GIF loaded from the AWT toolkit, or like a `MultiResolutionImage`), then it will only serialize a frozen snapshot (`BufferedImage`) for one-time use.)

What they have in common is vector scalability. Vector data (esp text and shapes) can be printed at high resolutions without being pixelated. So this is especially useful as we migrate to 4K monitors. And although I haven't formally set up any benchmark comparisons, I like to think that "deserialized rendering operations" will generally outperform most "SVG parsers" in the real world. (At least a little.)

The demo in this showcase app includes 4 JVG files. These were created by grabbing SVG files from openclipart.org and converting them to Java source code with the Flamingo SVG transcoder.