<chapter label="11" id="custom-shapes-chapter">
  <title>Custom Shape Module</title>

  <sect1 id="custom-shapes-intro">
    <title>Custom-shape Module introduction</title>

    <para>
      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.
    </para>
    <para>
      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,A,a,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.
    </para>
    <para>
      A number of connection points can be associated with the shape, which
      are specified in the same coordinate system as the shape description.
      One of the connection points should be marked as the main connection
      point. This main connection point will be used if a line is dragged
      onto the object but not on one of it's connection points.
    </para>
    <para>
      <emphasis>A</emphasis> text box can be associated with the shape. 
      The text box is also 
      specified in the same coordinate system as the shape description. 
    </para>
    <para>
      To choose size and position of the text box, you can think of one 
      rectangle to contain the text box, and another one to  contain all 
      other svg elements (call it the image rectangle): When you get the 
      shape to the canvas, and write some text, all of it has to  go inside 
      the text box; if necessary, this text box will grow, and, in the same 
      proportion, the image rectangle will also grow.  
    </para>

    <para>
      The rest is taken care of for you (resizing, moving, line connection,
      loading, saving, undo, etc).
    </para>
  </sect1>
  <sect1 id='custom-shapes-shapes'>
    <title>Shapes</title>

    <para>
      A typical shape file may look something like this:

      <literallayout>
        <literal>
          <![CDATA[
<?xml version="1.0"?>
  <shape xmlns="http://www.daa.com.au/~james/dia-shape-ns"
         xmlns:svg="http://www.w3.org/2000/svg">
    <name>Circuit with identifiers - NPN Transistor</name>
    <icon>npn.xpm</icon>
    <connections>
      <point x="0" y="0"/>
      <point x="6" y="-4" main="yes"/>
      <point x="6" y="4"/>
    </connections>

    <aspectratio type="fixed"/>

    <textbox x1="4" y1="-3" x2="12" y2="3" />

    <svg:svg>
      <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>
]]>
        </literal>
      </literallayout>
    </para>
    <para>
      Only the <literal>name</literal> and <literal>svg</literal> elements
      are required in the shape file.  The
      rest are optional.
    </para>
    <para>
      The <literal>name</literal> element give the name of the object.  The
      name is a unique identifier for this shape that is used for saving and
      loading. 
    </para>
    <para>
      As in the example, you may use "compound names". Many shapes have first 
      part of its name to indicate the sheet in which they appear, but this
      is optional.
    </para>
    <para>   
      The <literal>icon</literal> element specifies an xpm file or a png
      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.
    </para>
    <para>
      The <literal>connections</literal> 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.
    </para>
    <para>
      The <literal>aspectratio</literal> element allows you to specify 
      how the shape can be
      distorted.  The three possibilities are:
      <itemizedlist>
        <listitem>
          <simpara>
            <literal>
              &lt;aspectratio type="free"/&gt;
            </literal>
            - Any aspect ratio is OK (the default)
          </simpara>
        </listitem>
        <listitem>
          <simpara>
            <literal>
              &lt;aspectratio type="fixed"/&gt;
            </literal>
            - Fix the aspect ratio for this shape.
          </simpara>
        </listitem>
        <listitem>
          <simpara>
            <literal>
              &lt;aspectratio type="range" min="n" max="m"/&gt;
            </literal>
            - Give a range of values.
          </simpara>
        </listitem>
      </itemizedlist>
      The last option allows you to specify a range of allowable amounts of
      distortion, which may be useful in some cases.
    </para>
    <para>
      The <literal>textbox</literal> element allows you to associate some text with
      the shape.  The syntax is:
      <literallayout>
        <literal>
          &lt;textbox x1="left" y1="top" x2="right" y2="bottom"/&gt;
        </literal>
      </literallayout>
      (Only one textbox per shape) Where the attributes give the bounds of 
      the text box in the same coordinate system as the SVG shape description.
    </para>
    <para>
      There are some optional attributes on &lt;textbox/&gt; namely
      <variablelist>
        <varlistentry>
          <term>resize="no" :</term>
          <listitem>
            <simpara>by default the textbox is resized with the text</simpara>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>align="center" :</term>
          <listitem>
            <simpara>"center" is default, also "left" and "right" can be used</simpara>
          </listitem>
        </varlistentry>
      </variablelist>
    </para>
    <para>

      Shapes are given a default size on creation. If that default size does
      not fit your needs you can overwrite it by (one or both):
      &lt;default-width&gt;1cm&lt;/default-width&gt;
      &lt;default-height&gt;3cm&lt;/default-height&gt;
      The default unit "cm" can be omitted.
    </para>
    <para>
      The <literal>svg</literal> 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:
      <ulink type="http"
          url="http://www.w3.org/Graphics/SVG">http://www.w3.org/Graphics/SVG</ulink>
    </para>
    <para>
      The next section details what parts of the SVG spec can be used in
      shape files.
    </para>
  </sect1>

  <sect1 id="custom-chapes-shape-desc">
    <title>The Shape Description</title>

    <para>
      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.
    </para>
    <sect2 id="custom-shapes-shape-style-attribute">
      <title>Style attribute</title>
      <para>
        Each of the SVG drawing elements understands the style attribute.  The
        attribute should be of the form:
        <literallayout>
          <literal>
&lt;svg:whatever style="name1: value1; name2: value2; ... name42: value42"/&gt;
          </literal>
        </literallayout>
      </para>
      <para>
        Currently only the following style attributes are understood:
        <itemizedlist>
          <listitem>
            <simpara>
              <literal>stroke-width</literal> - The width of the line, relative to the
              user specified width.
            </simpara>
          </listitem>
          <listitem>
            <simpara>
              <literal>stroke-linecap</literal> - The line cap style.  One of 
              <literal>butt</literal>,
              <literal>round</literal>,
              <literal>square</literal>,
              <literal>projecting</literal> 
              (a synonym for <literal>square</literal>),
              or <literal>default</literal>.
            </simpara>
          </listitem>
          <listitem>
            <simpara>
              <literal>stroke-linejoin</literal>
              - The line join style.  One of
              <literal>miter</literal>,
              <literal>round</literal>,
              <literal>bevel</literal> or
              <literal>default</literal>.
            </simpara>
          </listitem>
          <listitem>
            <simpara>
              <literal>stroke-pattern</literal>
              - The dash pattern.  One of
              <literal>none</literal>,
              <literal>dashed</literal>,
              <literal>dash-dot</literal>,
              <literal>dash-dot-dot</literal>,
              <literal>dotted</literal>
              or <literal>default</literal>.
            </simpara>
          </listitem>
          <listitem>
            <simpara>
              <literal>stroke-dashlength</literal>
              - The length of the dashes in the dash pattern, in
              relation to the user selected value (<literal>default</literal> is a
              synonym for 1.0).
            </simpara>
          </listitem>
          <listitem>
            <simpara>
              <literal>stroke</literal>
              - The stroke colour.  You can use one of the symbolic names
              <literal>foreground</literal>,
              <literal>fg</literal>,
              <literal>default</literal>,
              <literal>background</literal>,
              <literal>bg inverse</literal>,
              <literal>text</literal> 
              or <literal>none</literal>, or use a hex colour value of the form
              <literal>#rrggbb</literal>.
            </simpara>
          </listitem>
          <listitem>
            <simpara>
              <literal>fill</literal>
              - The fill colour.  The same values as for stroke are used,
              except that the meaning of 
              <literal>default</literal> and
              <literal>inverse</literal> are
              exchanged.  By default, elements are not filled, so to get
              the default fill, use "<literal>fill: default</literal>"
            </simpara>
          </listitem>
        </itemizedlist>
        <tip>
          <para>
            So to draw a rectangle with a hairline stroke, the following would do
            the trick:
            <literallayout>
              <literal>
&lt;svg:rect style="stroke-width: 0" x="..." y="..." width="..." 
  height="..."/&gt;
              </literal>
            </literallayout>
          </para>
        </tip>
      </para>
      <para>
        Ordinates x and y grow as in Dia. 
      </para>
    </sect2>
    <sect2 id="custom-shapes-shape-elements">
      <title>Recognised drawing elements</title>
      <para>
        The recognised drawing elements are:
      </para>
      <itemizedlist>
        <listitem>
          <simpara>
            <literal>&lt;svg:g&gt;</literal>
          </simpara>
          <para>
            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).
          </para>
        </listitem>
        <listitem>
          <simpara>
            <literal>
              &lt;svg:line x1="..." y1="..." x2="..." y2="..."/&gt;
            </literal>
          </simpara>
          <para>
            This element is a line.
          </para>
        </listitem>
        <listitem>
          <simpara>
            <literal>
              &lt;svg:polyline points="...."/&gt;
            </literal>
          </simpara>
          <para>
            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 ...".
          </para>
        </listitem>
        <listitem>
          <simpara>
            <literal>
              &lt;svg:polygon points="...."/&gt;
            </literal>
          </simpara>
          <para>
            This is a polygon.  The points argument has the same format as the
            polyline.
          </para>
        </listitem>
        <listitem>
          <simpara>
            <literal>
              &lt;svg:rect x1="..." y1="..." width="..." height="..."/&gt;
            </literal>
          </simpara>
          <para>
            This is a rectangle.  The upper left corner is (x1,y1), and the lower
            right corner is (x1+width,y1+height).
          </para>
        </listitem>
        <listitem>
          <simpara>
            <literal>
              &lt;svg:image x1="..." y1="..." width="..." height="..." xlink:href="..." /&gt;
            </literal>
          </simpara>
          <para>
            This is an external image.  The upper left corner is (x1,y1), and the 
            lower right corner is (x1+width,y1+height).
            Their are two forms of links supported, an absolute filename of the form
            "<literal>file:///home/user/image.png</literal>" or a relative one
            without the "<literal>file://</literal>" prefix
            like in "<literal>image.png</literal>". The latter form is
            preferred because it is installation
            independent. The filename is relative to the shape file placement. In the
            above example PNG and shape need to be in the same directory.
	    
	    Inlined image data is also supported with xlink:href="data:image/png;base64,..."
          </para>
        </listitem>
        <listitem>
          <simpara>
            <literal>
              &lt;svg:circle cx="..." cy="..." r="..."/&gt;
            </literal>
          </simpara>
          <para>
            This is a circle with centre (cx,cy) and radius r.
          </para>
        </listitem>
        <listitem>
          <simpara>
            <literal>
              &lt;svg:ellipse cx="..." cy="..." rx="..." ry="..."/&gt;
            </literal>
          </simpara>
          <para>
            This is a ellipse with centre (cx, cy) and radius rx in the x direction
            and ry in the y direction.
          </para>
        </listitem>
        <listitem>
          <simpara>
            <literal>
              &lt;svg:path d="...."/&gt;
            </literal>
          </simpara>
          <para>
            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
            "<literal>x arg1 arg2 ...</literal>"
            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 absolute one are
            spelled with an upper case letter. The relative ones are spelled with
            a lower case letter, and use the end point of the previous command
            as the origin.
          </para>
          <para>
            The supported commands are:
            <itemizedlist>
              <listitem>
                <simpara>
                  <literal>M x,y</literal> - Move cursor
                </simpara>
              </listitem>
              <listitem>
                <simpara>
                  <literal>L x,y</literal> - Draw a line to (x,y)
                </simpara>
              </listitem>
              <listitem>
                <simpara>
                  <literal>H x</literal> - Draw a horizontal line to x
                </simpara>
              </listitem>
              <listitem>
                <simpara>
                  <literal>V y</literal> - Draw a vertical line to y
                </simpara>
              </listitem>
              <listitem>
                <simpara>
                  <literal>C x1,y1 x2,y2, x3,y3</literal> - Draw a bezier curve to 
                  (x3,y3) with (x1,y1) and (x2,y2) as control points. C (uppercase) indicates 
		  that absolute coordinates will follow; c (lowercase) indicates that relative 
		  coordinates will follow.
                </simpara>
              </listitem>
              <listitem>
                <simpara>
                  <literal>S x1,y1 x2,y2</literal> -  Same as above, but draw a `smooth'
                  bezier. That is, infer the first control point from
                  the previous bezier. S (uppercase) indicates that absolute coordinates will 
		  follow; s (lowercase) indicates that relative coordinates will follow. 
                </simpara>
              </listitem>
              <listitem>
                <simpara>
                  <literal>A (rx ry x-axis-rotation large-arc-flag sweep-flag x y)+</literal> -  
                  Draw an elliptical arc from the current point to (x, y). The size and orientation 
		  of the ellipse are defined by two radii (rx, ry) and an x-axis-rotation. 
		  The center is automatically calculated. large-arc-flag and sweep-flag contribute 
		  to the automatic calculations and help determine how the arc is drawn. 
		  A (uppercase) indicates that absolute coordinates will follow; a (lowercase) 
		  indicates that relative coordinates will follow.
                </simpara>
              </listitem>
              <listitem>
                <simpara>
                  <literal>Z</literal> - Close the path.
                </simpara>
              </listitem>
            </itemizedlist>
            If the path is closed with <literal>z</literal> or
            <literal>Z</literal>, then it can be filled.
            Otherwise, it will just be drawn.
          </para>
        </listitem>
        <listitem>
          <simpara>
            <literal>
              &lt;svg:text x="..." y="..." style="..."&gt;...&lt;/svg:text&gt;
            </literal>
          </simpara>
          <para>
            A text in the shape. The text has to be enclosed in the tags
          </para>
          <para>
            The parameters are:

            <itemizedlist>
              <listitem>
                <simpara>
                  <literal>x,y</literal> - The text position
                </simpara>
              </listitem>
              <listitem>
                <simpara>
                  <literal>style</literal> - Text formatting options
                </simpara>
                <para>
                  The following style options are supported:
                  <itemizedlist>
                    <listitem>
                      <simpara>
                        <literal>font-size</literal> - font size in pt  
                      </simpara>
                    </listitem>
                  </itemizedlist>
                </para>
              </listitem>
            </itemizedlist>
          </para>
        </listitem>
      </itemizedlist>
    </sect2>
  </sect1>
  <sect1>
    <title>Shapes in Shapes aka. Subshapes</title>
    <para>
      Adding indepentently resizable symbols into your custom shapes is possible by
      creating subshapes. This is done by some extra attributes on the group element.
    </para>
    <literallayout>
      <literal>
        <![CDATA[
<svg:g
 subshape="true"
 v_anchor="fixed.bottom"
 h_anchor="fixed.left"
 default_scale="1.0">
 ]]>
      </literal>
    </literallayout>
    <variablelist>
      <varlistentry>
        <term>v_anchor<termdef>Supported values:
            <parameter>"fixed.top"</parameter>
            <parameter>"fixed.bottom"</parameter>
            <parameter>"proportional"</parameter>
          </termdef>
        </term> 
        <listitem>
          <simpara>The vertical anchoring of the subshape.
          </simpara>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>h_anchor
          <termdef>Supported values are:
            <parameter>"fixed.left"</parameter>
            <parameter>"fixed.right"</parameter>
            <parameter>"proportional"</parameter>
          </termdef>
        </term>
        <listitem>
          <simpara>The horizontal anchoring of the subshape.</simpara>
        </listitem> 
      </varlistentry>
      <varlistentry>
        <term>default_scale</term>
        <listitem>
          <simpara>currently unused</simpara>
        </listitem>
      </varlistentry>
    </variablelist>
  </sect1>
  <sect1>
    <title>Extented Attributes</title>
    <para>
      To extend your custom shape with custom attributes you can put something like:
    </para>
    <literallayout>
      <literal>
        <![CDATA[
  <ext_attributes>
    <ext_attribute name="Integer" type="int" />
    <ext_attribute name="String" type="string" />
    <ext_attribute name="Float" type="real" />
  </ext_attributes>
]]>
      </literal>
    </literallayout>
    <para>
      between the <literal>&lt;shape&gt;&lt;/shape&gt;</literal> tags. The effect will be 
      some custom properties in your object. They are editable by the properties dialog 
      and will be loaded and saved with your diagram. To programatically access them use 
      <literal>"custom:&lt;name&gt;"</literal>
    </para>

  </sect1>
  <sect1 id='custom-shapes-sheets'>
    <title>The Sheet description</title>
    <para>
    </para>
    <para>
      You can put several shapes in one sheet: the shapes you create  or any 
      other shape or object "belonging" to other sheets.
    </para>
    <para>
      A simple sheet file may look something as this:

      <literallayout>
        <literal>
          <![CDATA[
<?xml version="1.0" encoding="utf-8"?> 
<sheet xmlns="http://www.lysator.liu.se/~alla/dia/dia-sheet-ns">
  <name>Circuit with identifiers</name>
  <name xml:lang="es">Circuito con identificadores</name>
  <description>Components for circuit diagrams</description>
  <description xml:lang="es">Componentes para diagramas de circuitos
  </description>
  <contents>
    <object name="Circuit with identifiers - NPN Transistor">
     <description>A bipolar npn transistor</description>
     <description xml:lang="es">Un transistor bipolar npn identificable
     </description>
    </object>
    <object name="UML - Objet">
     <description>An UML object</description>
     <description xml:lang="es">Un objeto UML</description>
    </object>
   </contents>
</sheet>
]]>
        </literal>
      </literallayout>
    </para>
  </sect1>
  <sect1 id='custom-shapes-managing'>
    <title>How Dia helps to create and manage sheets and shapes.</title>
    <para>
      You can use Dia with its available elements to draw a shape and then 
      export it to a shape file, by using  
      <menuchoice>
        <guimenu>File (of  diagram)</guimenu>
        <guimenuitem>Export</guimenuitem>
        <guimenuitem>By extension</guimenuitem>
        <guimenuitem>Shape</guimenuitem>
      </menuchoice>.
    </para>
    <para>
      But until now, this shapes  don't have any text box. (They are expected 
      to manage some svg:text but not a text box). If you need one,  you can 
      edit the file. 

    </para>
    <para>    
      Together with the shape file, you get a png file (after accepting the 
      proposed size) which can be used for the shape's icon. 

    </para>
    <para>    
      By using
      <menuchoice>
        <guimenu>File(of principal menu)</guimenu>
        <guimenuitem>Sheets
          and Objects</guimenuitem>
      </menuchoice> 
      you can create  new sheets;  and add,  remove and parcially edit  shapes;
      and copy or move shapes from one sheet to other.  
    </para>
  </sect1>
  <sect1 id="custom-shapes-code">
    <title>Design Notes</title>
    <para>
      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, with the sheet description going to 
      ~/.dia/sheets
    </para>


    <para>
      If you have any suggestions for this code, please tell me.
    </para>
    <para>
      James Henstridge <email>james@daa.com.au</email>
      with some modifications written by 
      Dolores Alia de Saravia <email>loli@unsa.edu.ar</email>  
    </para>
  </sect1>
</chapter>
