Custom Shape Module
===================

The custom shape module allows you to create new shapes for Dia
without	writing any C code.  Instead, you just have to write a simple
XML file describing the shape.  This opens up the job of creating new
shapes for dia to non programmers as well.

The actual shape is described using a subset of the SVG
specification.  The line, polyline, polygon, rect, circle, ellipse,
path and g elements are supported.  Note that the path element only
supports the M,m,L,l,H,h,V,v,C,c,S,s,Z and z commands.
Transformations and CSS units are not supported (only `user' units
are), and only a limited set of the CSS attributes are supported.

A number of connection points can be associated with the shape, which
are specified in the same coordinate system as the shape description.

A text box can be associated with the shape.  The custom shape code
will make sure that the text entered into it fits the text box by
resizing the image if necessary.  The text box is specified in the
same units as the shape.

A name and description can be given to the shape.  The description can
have multiple variants stored in the file to allow i18n.

The rest is taken care of for you (resizing, moving, line connection,
loading, saving, undo, etc).


Sheets
======

Shapes are organised into sheets in the notebook of the toolbox in
dia.  The custom shape code decides which sheet a shape is in by which
directory it is in.

Each sheet of custom objects is a directory under
$(prefix)/share/dia/shapes, ~/.dia_shapes or any of the directories in
the DIA_SHAPE_PATH environment variable.

If there is an index.sheet or index.xml file in the sheet directory,
it lists which shapes exist in that particular sheet.  If one of these
files does not exist, then all the *.shape and *.xml files are added
to the sheet, and the directory name is used as the sheet name.

You will need to provide an index.sheet file if you want to specify
the ordering of of shapes in the sheet, or give a description of the
sheet.  You will also need an index.sheet file if you want to provide
translations for the sheet name or description.

The index.sheet file is an xml file that uses the
http://www.daa.com.au/~james/dia-sheet-ns namespace.  Here is an
example:

  <?xml version="1.0"?>
  <sheet xmlns="http://www.daa.com.au/~james/dia-sheet-ns">
    <name xml:lang="de">German name for sheer</name>
    <name xml:lang="en_AU">A string that spells grey or colour correctly</name>
    <name>A default name</name>
    <description xml:lang="es">Spanish description</description>
    <description>Default description</description>

    <shapes>
      <shape>shapefile1.shape</shape>
      <shape>shapefile2.shape</shape>
      ...
    </shapes>
  </sheet>

Notice that the standard xml:lang attribute is used to mark the
language of a particular string.  The custom shape code will pick the
best language based on the contents of the LANG variable.

The <shapes> section specifies the names of all the shapes in the
sheet.  The file names can be relative to the index.sheet file.


Shapes
======

A typical shape file may look something like this:
  <?xml version="1.0"?>

  <shape xmlns="http://www.daa.com.au/~james/dia-shape-ns"
         xmlns:svg="http://www.w3.org/Graphics/SVG/svg-19990730.dtd">
    <name>Circuit - NPN Transistor</name>
    <description>An npn bipolar transistor</description>
    <icon>npn.xpm</icon>
    <connections>
      <point x="0" y="0"/>
      <point x="6" y="-4"/>
      <point x="6" y="4"/>
    </connections>

    <aspectratio type="fixed"/>

    <svg:svg width="3.0" height="3.0">
      <svg:line x1="0" y1="0" x2="3" y2="0" />
      <svg:line x1="3" y1="-3" x2="3" y2="3" />
      <svg:line x1="3" y1="-2" x2="6" y2="-4" />
      <svg:line x1="3" y1="2" x2="6" y2="4" />

      <svg:polyline points="5,4 6,4 5.6154,3.0769" />
    </svg:svg>
  </shape>

Only the name, description and svg elements are required in the shape
file.  The rest are optional.

The name and description elements give the name and description.  The
name is a unique identifier for this shape that is used for saving and
loading.  For this reason the xml:lang attribute will be ignored.  The
description is the user visible description shown as a tooltip in the
dia toolbox.  It is translatable with the xml:lang attribute.

The icon element specifies an xpm file that is used as the icon in the
dia toolbox.  The filename can be relative to the shape file.  If it
is not given, a default custom shape icon will be used.

The connections section specifies a number of connection points for
the shape.  The coordinate system for these points is the same as the
coordinate system used in the svg shape description.

The aspectratio element allows you to specify how the shape can be
distorted.  The three possibilities are:
  <aspectratio type="free"/>    Any aspect ratio is OK (the default)
  <aspectratio type="fixed"/>   Fix the aspect ratio for this shape.
  <aspectratio type="range" min="n" max="m"/>  Give a range of values.

The last option allows you to specify a range of allowable amounts of
distortion, which may be useful in some cases.

The textbox element (not shown) allows you to associate some text with
the shape.  The syntax is:
  <textbox x1="left" y1="top" x2="right" y2="bottom"/>
Where the attributes give the bounds of the text box in the same
coordinate system as the SVG shape description.

The svg element describes the shape.  The width and height attributes
are ignored, and only given to comply with the SVG specification.  For
more information on SVG, see the W3C pages about the format at:
  http://www.w3.org/Graphics/SVG/

The next section details what parts of the SVG spec can be used in
shape files.


The Shape Description
=====================

The Scalable Vector Graphics format is used to describe the shape.
That is why the separate namespace is used for that part of the file.

Each of the SVG drawing elements understands the style attribute.  The
attribute should be of the form:
  <svg:whatever style="name1: value1; name2: value2; ... name42: value42"/>

Currently only the following style attributes are understood:
  stroke-width - The width of the line, relative to the user specified
                 width.
  stroke-linecap    - The line cap style.  One of butt, round, square,
                      projecting (a synonym for square), or default.
  stroke-linejoin   - The line join style.  One of miter, round, bevel or
                      default.
  stroke-pattern    - The dash pattern.  One of none, dashed, dash-dot,
                      dash-dot-dot, dotted or default.
  stroke-dashlength - The length of the dashes in the dash pattern, in
                      relation to the user selected value (default is a
                      synonym for 1.0).

  stroke       - The stroke colour.  You can use one of the symbolic
                 names foreground, fg, default, background, bg inverse,
                 text or none, or use a hex colour value of the form #rrggbb.
  fill         - The fill colour.  The same values as for stroke are used,
                 except that the meaning of default and inverse are
                 exchanged.  By default, elements are not filled, so to get
                 the default fill, use "fill: default"

So to draw a rectangle with a hairline stroke, the following would do
the trick:
  <svg:rect style="stroke-width: 0" x1="..." y1="..." x2="..." y2="..."/>

The recognised drawing elements are:

<svg:g>
  This is the group element.  You can place other drawing elements
  inside it.  The contents of the style attribute on a group element
  will propagate to the contained elements (unless they override it).

<svg:line x1="..." y1="..." x2="..." y2="..."/>
  This element is a line.

<svg:polyline points="...."/>
  This is a polyline.  That is, a number of connected line segments.
  The points attribute holds the coordinates of the end points for the
  line segments.  The coordinates are separated by white space or
  commas.  The suggested format is "x1,y1 x2,y2 x3,y3 ...".

<svg:polygon points="...."/>
  This is a polygon.  The points argument has the same format as the
  polyline.

<svg:rect x1="..." y1="..." x2="..." y2="..."/>
  This is a rectangle.  The upper left corner is (x1,y1), and the lower
  right corner is (x2,y2).

<svg:circle cx="..." cy="..." r="..."/>
  This is a circle with centre (cx,cy) and radius r.

<svg:ellipse cx="..." cy="..." rx="..." ry="..."/>
  This is a ellipse with centre (cx, cy) and radius rx in the x direction
  and ry in the y direction.

<svg:path d="...."/>
  This is the most complicated drawing element.  It describes a path
  made up of line segments and bezier curves.  It currently does not
  support the elliptic arc or quadratic bezier curves.  The d string
  is made up of a number of commands of the form "x arg1 arg2 ..."
  where x is a character code identifying the command, and the
  arguments are numbers separated by white space or commas.  Each
  command has an absolute and relative variant.  The relative ones use
  the end point of the previous command as the origin.

  The supported commands are:
    M x,y                 Move cursor
    L x,y                 Draw a line to (x,y)
    H x                   Draw a horizontal line to x
    V y                   Draw a vertical line to y
    C x1,y1 x2,y2, x3,y3  Draw a bezier curve to (x3,y3) with (x1,y1)
                          and (x2,y2) as control points.
    S x1,y1 x2,y2         Same as above, but draw a `smooth' bezier.
                          That is, infer the first control point from
                          the previous bezier.
    Z                     Close the path.

  If the path is closed with z or Z, then it can be filled.
  Otherwise, it will just be drawn.


Design Notes
============

The custom shape code is designed so that a sheet of objects can be
self contained in a single directory.  Installing new shapes can be as
easy as untaring a .tar.gz file to ~/.dia_shapes or
$(prefix)/share/dia/shapes.

In the future, I will look at adding support for overriding the user's
choice of colour or line style for parts of a drawing, and setting
line join styles.

If you have any suggestions for this code, please tell me.


  James Henstridge <james@daa.com.au>
