- From: Fred P. <fprog26@hotmail.com>
- Date: Sat, 12 Apr 2003 08:33:56 -0400
- To: www-svg@w3.org
Here's some experiments that were performed in an attempt to use SVG, PNG or
HTML tables
to display clean, professional, good looking UML class diagram drawing
results
from an industrial database back-end for documentation purposes.
Unfortunately, some problems occurs and some possible solutions are proposed
in this document.
Test Environment:
Microsoft Windows 98 SE
Internet Explorer 5.50.x.x; SP2
Adobe SVG Viewer 3.0 build 76
Screen Resolution: 1152x864 True color (32-bit)
Other tools:
PHP4 on Apache HTTP Server 1.3.x
ActiveState ActivePerl 5.6.1 build 635
with GD.ppm for PNG generation
The following display a problem with SVG stroke-width: 1 to display UML
boxes.
<!----------------------------------------------------------------------------------------------->
<?xml version='1.0' encoding='iso-8859-1'?>
<!DOCTYPE svg SYSTEM
'http://www.w3.org/TR/2000/03/WD-SVG-20000303/DTD/svg-20000303-stylable.dtd'>
<svg>
<rect x='100' y='40' width='100' height='60'
style='
fill: #FFFFCC;
stroke: #990033;
/* Adobe SVG viewer 3.0 build 76 */
/* Width 2 with shadow at high quality (default) */
/* Width 1 without shadow at low quality */
stroke-width: 1;
fill-opacity: 1;
opacity: 1;
stroke-opacity: 1;
'
/>
</svg>
<!----------------------------------------------------------------------------------------------->
Apart using lines after lines with special orientation or bezier curves,
one of the troublesome work around this is the following:
<!----------------------------------------------------------------------------------------------->
<?xml version='1.0' encoding='iso-8859-1'?>
<!DOCTYPE svg SYSTEM
'http://www.w3.org/TR/2000/03/WD-SVG-20000303/DTD/svg-20000303-stylable.dtd'>
<svg>
<style type="text/css">
<![CDATA[
.UML-box-lined { fill: #FFFFCC;
stroke: #990033;
stroke-width: 2;
fill-opacity: 1;
opacity: 1;
stroke-opacity: 1;
stroke-linejoin: mitter;
}
.UML-box-blank { fill: #FFFFCC;
stroke: #FFFFCC;
stroke-width: 0;
fill-opacity: 1;
opacity: 1;
stroke-opacity: 1;
stroke-linejoin: mitter;
}
]]>
</style>
<rect x="100" y="40" width="100" height="60" class="UML-box-lined" />
<rect x="100" y="40" width="100" height="60" class="UML-box-blank" />
<rect x="100" y="60" width="100" height="20" class="UML-box-lined" />
<rect x="100" y="60" width="100" height="20" class="UML-box-blank" />
<rect x="100" y="80" width="100" height="20" class="UML-box-lined" />
<rect x="100" y="80" width="100" height="20" class="UML-box-blank" />
<text x="119" y="53.5" style="font-family: Arial; font-size: 12; ">
Component
</text>
<!-- Corner: (+9.0, +8.0) -->
<use xlink:href="#UML_function" x="109" y="88" />
<!-- Corner: (+1.0, +1.0) -->
<use xlink:href="#UML_lock" x="101" y="61" />
<!-- Corner: (+9.0, +8.0) Lock dist: (+8.0, +7.0) -->
<use xlink:href="#UML_attribute" x="109" y="68" />
<!-- Corner: (+20.0, +13.5) -->
<text x="120" y="73.5" style="font-family: Arial; font-size: 12; ">
Attribute
</text>
<!-- Corner: (+20.0, +13.5) -->
<text x="120" y="93.5" style="font-family: Arial; font-size: 12; ">
Function
</text>
</svg>
<!----------------------------------------------------------------------------------------------->
Another way is to use an HTML table as follow:
<!----------------------------------------------------------------------------------------------->
<!doctype html public '-//W3C//DTD HTML 4.0 Transitional//EN'>
<html>
<head>
<meta http-equiv='content-type' content='text/html; charset=iso-8859-1'>
<style>
<!--
.UML
{
border:1px solid #990033;
background-color: #FFFFCC;
font-family:Arial;
font-size:12;
}
.UML-division
{
border-top:1px solid #990033;
background-color: #FFFFCC;
font-family:Arial;
font-size:12;
}
//-->
</style>
</head>
<body>
<table border='0' cellspacing='0' cellpadding='0' width='100px'
class='UML' id='panel'
style='position:absolute; left:100px; top:40px; cursor:move'
>
<tr height='20px'>
<td height='20px' id='class0'
style='text-align:center; cursor:text;'>Arial aliased</td>
</tr>
<tr height='20px'>
<td class='UML-division'>
<table border='0' cellspacing='0' cellpadding='0'>
<tr>
<td width='12px'><nobr> <img
src='attribute.gif'> </nobr></td>
<td style='text-align:left; cursor:text;'>Attribute</td>
<td width='12px'> </td>
</tr>
</table>
</td>
</tr>
<tr height='20px'>
<td class='UML-division'>
<table border='0' cellspacing='0' cellpadding='0'>
<tr>
<td width='12px'><nobr> <img
src='function.gif'> </nobr></td>
<td style='text-align:left; cursor:text;'>Function</td>
<td width='12px'> </td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
<!----------------------------------------------------------------------------------------------->
Propositions:
1. Embed/Object an SVG object directly inside an HTML/XHTML document without
SRC=''
<EMBED NAME='svgEmbed1'
TYPE='image/svg+xml'
width='500'
height='500'
PLUGINSPAGE='http://www.adobe.com/svg/viewer/install/'>
<SVG>...</SVG>
</EMBED>
<OBJECT NAME='svgEmbed2'
TYPE='image/svg+xml'
width='500'
height='500'
PLUGINSPAGE='http://www.adobe.com/svg/viewer/install/'>
<SVG>...</SVG>
</OBJECT>
2. Provide CSS stylesheet property for text (for SVG/HTML/XHTML):
aliased: false; // Force anti-aliased text
aliased: true; // Force non-anti-aliased text (TrueType font)
selectable: false; // Can highlight the text acts like a graphic
selectable: true; // useful for button icons and similar
align: justify; // We got center/left/right but no justify
// which is the default layout for IEEE/ACM/journal
paper, etc.
3. Provide XHTML <table> layout in SVG
Letter by letter, word by word fixing is tedious
4. Provide CSS stylesheet property for graphics:
blur: true/false or 0..100%;
// for line, box, circle, elipse and text: sub-pixel drawing/conversion
// Equivalent per object: low/high quality on Adobe SVG viewer
stroke-width: 1; // Doesn't work as expected.
stroke-width: .1; // Fraction doesn't work neither.
People currently rely on bezier curved (i.e. VectorEye translator)
or
Line by Line drawing with tedious effort to have very thin line
5. Even though SVG is for Vector graphics, it's very tedious to obtain
the same effect than bitmap drawing effects at pixel scale.
Provide something like: D x y => Print a Dot at (x,y)
<g id='bitmap'>
<!-- Bitmap derived version -->
<path style='fill:#040404' d='D6 2 D l0 3 D 10 4'/>
</g>
6. Even without bitmap it's very difficult to provide weird stroke shadow
for boxes,
consider rendering the following 'trivial' UML function box:
[ #FFFFCC ][ #FFFFCC ][ #FFFFCC ][ #000000 ][ #FFFFCC ][ #FFFFCC ][ #FFFFCC
][ #FFFFCC ][ #FFFFCC ]
[ #FFFFCC ][ #FFFFCC ][ #000000 ][ #FF00FF ][ #800000 ][ #FFFFCC ][ #FFFFCC
][ #FFFFCC ][ #FFFFCC ]
[ #FFFFCC ][ #800080 ][ #FF00FF ][ #FF00FF ][ #FF00FF ][ #000080 ][ #FFFFCC
][ #FFFFCC ][ #FFFFCC ]
[ #000080 ][ #FF00FF ][ #FF00FF ][ #FF00FF ][ #FF00FF ][ #FF00FF ][ #000080
][ #FFFFCC ][ #FFFFCC ]
[ #000000 ][ #800080 ][ #FF00FF ][ #FF00FF ][ #FF00FF ][ #FF00FF ][ #FF00FF
][ #800000 ][ #FFFFCC ]
[ #FFFFCC ][ #000080 ][ #000000 ][ #FF00FF ][ #FF00FF ][ #FF00FF ][ #FF00FF
][ #FF00FF ][ #000080 ]
[ #FFFFCC ][ #FFFFCC ][ #800080 ][ #000080 ][ #FF00FF ][ #FF00FF ][ #FF00FF
][ #000080 ][ #000000 ]
[ #FFFFCC ][ #FFFFCC ][ #FFFFCC ][ #000000 ][ #800000 ][ #FF00FF ][ #000000
][ #800080 ][ #FFFFCC ]
[ #FFFFCC ][ #FFFFCC ][ #FFFFCC ][ #FFFFCC ][ #000080 ][ #000080 ][ #000080
][ #FFFFCC ][ #FFFFCC ]
[ #FFFFCC ][ #FFFFCC ][ #FFFFCC ][ #FFFFCC ][ #FFFFCC ][ #800000 ][ #FFFFCC
][ #FFFFCC ][ #FFFFCC ]
Even with lines, bezier curves, it never looks as good as the original
picture
and the shadow doesn't scale well when make bigger.
Stroke and Shadow consist of: Red, Blue, Dark purple and black in a
pseudo-random fashion.
<!-- Best attempt but different then original -->
<!-- Public attribute - cyan square -->
<g id='UML_attribute_v9'>
<path style='fill:#7777FF; stroke:#000000' d='M 5 0 L 8 4 L 3 9 L 0
6 z' />
<path style='fill:#00FFFF; stroke:#7777FF' d='M 5 0 L 8 3 L 3 8 L 0
5 z' />
<path style='fill:#99FFFF; stroke:#99FFFF' d='M 8 3 L 5 0 L 0 5' />
</g>
<!-- Public function - purple square -->
<g id='UML_function_v9'>
<path style='fill:#7777FF; stroke:#000000' d='M 8 6 L 5 9 L 0 4 L 3
1 z' />
<path style='fill:#FF66FF; stroke:#CC00CC' d='M 3 0 L 8 5 L 5 8 L 0
3 z' />
<path style='fill:#FF66FF; stroke:#FF66FF' d='M 8 5 L 3 0 L 0 3' />
</g>
Other attempts but for attribute component:
<g id='UML_attribute_v7'>
<path style='fill:#000080; stroke:#000080' d='M 8 6 L 5 9 L 0 4 L 3
1 z' />
<path style='fill:#FF00FF; stroke:#FF00FF' d='M 3 0 L 8 5 L 5 8 L 0
3 z' />
<path style='stroke:#000000' d='M 2 1 L 3 0 l.75 .75'/>
<path style='stroke:#800000' d='M 4 1 l.75 .75'/>
<path style='stroke:#000080' d='M 5 2 L 6 3 l.75 .75'/>
<path style='stroke:#800000' d='M 7 4 l.75 .75'/>
<path style='stroke:#000080' d='M 8 5 L 5 8'/>
<path style='stroke:#000000' d='M 6.5 7.5 l-.75 -.75'/>
<path style='stroke:#800080' d='M 7 7 l-.75 -.75'/>
<path style='stroke:#000080' d='M 6 8 L 4 8'/>
<path style='stroke:#444444' d='M 7 4'/>
<path style='stroke:#800000' d='M 5 9'/>
<path style='stroke:#800000' d='M 4 7'/>
<path style='stroke:#000000' d='M 0 4'/>
<path style='stroke:#000000' d='M 2 5'/>
<path style='stroke:#000000' d='M 0 4'/>
<path style='stroke:#000000' d='M 3 7'/>
<path style='stroke:#000000' d='M 0 4'/>
<path style='stroke:#000000' d='M 6 7'/>
<path style='stroke:#000000' d='M 8 6'/>
</g>
<g id='UML_function_v6'>
<path style='fill:#000000' d='M11 19 l-1 0 c-0.4316 -1.061 1.432
-1.061 1 0 z'/>
<path style='fill:#000000' d='M10 19 c-0.1667 0.5 -0.5 0.8333 -1 1
c0.1667 -0.5 0.5 -0.8333 1 -1 z'/>
<path style='fill:#ff00ff' d='M11 19 c0.1667 0.5 0.5 0.8333 1 1
c0.1667 0.5 0.5 0.8333 1 1 c0.1667 0.5 0.5 0.8333 1 1 c0.1667 0.5 0.5 0.8333
1 1 c-0.2232 1.242 -1.538 1.81 -2.25 2.75 l-0.5 0 c-1.333 -1.333 -2.667
-2.667 -4 -4 l-0.25 -0.75 c0.5 -0.1667 0.8333 -0.5 1 -1 c0.5 -0.1667 0.8333
-0.5 1 -1 l1 0 z'/>
<path style='fill:#800000' d='M12 20 c-0.5 -0.1667 -0.8333 -0.5 -1
-1 c0.5 0.1667 0.8333 0.5 1 1 z'/>
<path style='fill:#800080' d='M9 20 c-0.1667 0.5 -0.5 0.8333 -1 1
c0.1667 -0.5 0.5 -0.8333 1 -1 z'/>
<path style='fill:#000080' d='M13 21 c-0.5 -0.1667 -0.8333 -0.5 -1
-1 c0.5 0.1667 0.8333 0.5 1 1 z'/>
<path style='fill:#23004e' d='M8 21 l0.25 0.75 c1.333 1.333 2.667
2.667 4 4 l0.5 0 c0.7119 -0.9402 2.027 -1.508 2.25 -2.75 l0.75 0.25 l0.25
0.75 c-0.5193 1.599 -2.23 2.461 -3.25 3.75 l-0.5 0 c-1.667 -1.667 -3.333
-3.333 -5 -5 l-0.25 -0.75 l0.25 -0.75 l0.75 -0.25 z'/>
<path style='fill:#000080' d='M14 22 c-0.5 -0.1667 -0.8333 -0.5 -1
-1 c0.5 0.1667 0.8333 0.5 1 1 z'/>
<path style='fill:#800000' d='M15 23 c-0.5 -0.1667 -0.8333 -0.5 -1
-1 c0.5 0.1667 0.8333 0.5 1 1 z'/>
</g>
<!----------------------------------------------------------------------------------------------->
* Experiments were also performed to try to mimic the 'protected' attribute
lock icons
- with bezier curves, bitmap, VectorEye translator
This conducted to the conclusion that some techniques must be created to
enhance
the transform of bitmap into vectorial images.
The major issue is mainly pixel by pixel shadow and other transforms,
it seems to be quite a challenge to create such thing even for small 9x9
pictures.
Space is not an issue, it might be for 640x480 gif image to be converted
in SVG perhaps.
Most translator use something that looks like a drawing picture
instead of a professional picture; therefore,
making the end-result quite laughable and unprofessional sometimes.
The main expectation is to replace GIF/PNG/Flash/HTML Table+CSS/PDF/DOC
with SVG files.
In fact, if SVG provided the same kind of support than HTML for forms and
text display,
it could even replace HTML/XHTML altogheter,
by providing a real canvas environment for dynamic display.
It could even provide a scriptable web-based GUI environment
with a Java/Windows/MacOS/KDE-taste,
where widgets would be simple <g id='button'></g> scalable graphic
elements.
<!----------------------------------------------------------------------------------------------->
* Extension problems
It would be also useful, if SVG documents could be 'MORE' scriptable
or at least being generated by PHP/ASP/JSP.
The main problem is that let say a file called view.svg.php generating an
view.svg,
the browser won't recognized that PHP generates an SVG document, even
though it does!
Another solution would be to be able to do something like SHTML document
with import or include statement to import document.
It can be done by xlink:href altought.
But the point would be to have a dynamic, conditional xlink:href then.
It would be nice to be able to say:
<use xlink:href='windows.svg#button' x='109' y='88' />
<use xlink:href='macos.svg#button' x='109' y='88' />
<use xlink:href='java.svg#button' x='109' y='88' />
<use xlink:href='kde.svg#button' x='109' y='88' />
<use xlink:href='gnome.svg#button' x='109' y='88' />
<use xlink:href='mytheme.svg#button' x='109' y='88' />
by being able to specify such button 'theme'.
Trying to do so would be possible if PHP generated document were
considered valid
or with embedded SVG inside HTML as proposed earlier.
It could be done also via some heavy javascript.
One of the problem with PHP/ASP/JSP is that whenever a document is
fopen/fwrite/fclose
then embedded inside an HTML, the file is not flushed to disk; therefore,
one must use special tricks, like using a
<META HTTP-EQUIV='Refresh' CONTENT='0; URL=<?php echo $PHP_SELF
."?op=display_svg_file"; ?>'>
and a
<INPUT NAME='op' TYPE='hidden' VALUE='generate_svg_file'>
to have a two step process:
- first: create/generate/save/flush the file
- second: reload a new HTML file and display it.
If not done as follow,
it might work when first viewing the file for the first time,
BUT whenever someone submit the form to 'save the file', let say,
the new form will NOT work, since the browser will download
a file which wasn't saved completely.
Normally a blank file, a corrupt file or a file containing
a list of the current file inside the current directory
equivalent to an APACHE implicit index.html version
(This could be considered as a security risk problem on some website).
<!----------------------------------------------------------------------------------------------->
Currently, we are forced to go back to the old HTML/DIV/CSS technique
with transparent GIF images, since SVG does NOT provide
an equivalent professional look with current viewers, yet! =(
It's quite weird that current HTML browser can display properly
thin border and text properly but that SVG viewer
are still lacking such basic feature.
Nevertheless, experiment with GD::Image and PNG generation in perl
was also tried and suffered also from anti-aliased sickness,
but was still 'cleaner' and 'closer' to pure TrueType font,
then Adobe SVG viewer 3.0 build 76, even in low quality mode.
GD was able to provide thin border box easily though,
BUT the Arial 12pt text was still a bit unclean and dirty
compared to its HTML equivalent.
Finally, experiment with 'MyArial' TTF font using SVGFont,
also suffered from anti-aliased sickness
and looked dirty in low quality mode.
<!----------------------------------------------------------------------------------------------->
Look&feel and expected behavior to be found in SVG from its HTML
counterpart
Beta version fast prototype
<!----------------------------------------------------------------------------------------------->
<!doctype html public '-//W3C//DTD HTML 4.0 Transitional//EN'>
<html>
<head>
<meta http-equiv='content-type' content='text/html; charset=iso-8859-1'>
<SCRIPT LANGUAGE='JavaScript'>
<!--
var N = (document.all) ? 0 : 1;
var ob = null;
var over = false;
var change = "";
var kbdTarget = null;
var moveTarget = null;
var editfield = "";
var movespeed = 1
var help = false;
var crosshair = false;
var hand = false;
var waiting = false;
var textmode = false;
var moving = false;
var arrowup = false;
var arrowdown = false;
var arrowleft = false;
var arrowright = false;
/*
cursor: auto the default cursor
cursor: crosshair gun-style cross
cursor: default no change
cursor: hand the normal link-hand
cursor: wait the hourglass (non-animated, sadly)
cursor: text the text-selecting 'I-beam' thing
cursor: help an arrow with a question-mark
cursor: move crosshair with arrows on the ends
cursor: n-resize an arrow pointing north
cursor: ne-resize an arrow pointing north-east
cursor: nw-resize an arrow pointing north-west
cursor: e-resize an arrow pointing east
cursor: w-resize an arrow pointing west
cursor: s-resize an arrow pointing south
cursor: se-resize an arrow pointing south-east
cursor: sw-resize an arrow pointing south-west
*/
function toHTML(s)
{
var i = 0;
var r = "";
var ch;
for( ; i < s.length; i++ )
{
ch = s.substring( i, i+1 );
if ( ch == " " )
{
r += " ";
}
else
if ( ch == ">" )
{
r += ">";
}
else
if ( ch == "<" )
{
r += "<";
}
else
if ( ch == "&" )
{
r += "&";
}
else
{
r += ch;
}
}
if ( r == "" )
{
r = " ";
}
window.status += "| Result["+ r +"]";
return r;
}
function KD(e)
{
var code;
var code;
var modifier;
var ch;
var len;
if (N)
{
code = e.which;
modifier = e.modifier;
ch = String.fromCharCode(code);
}
else
{
code = window.event.keyCode;
modifier = window.event.modifier;
ch = String.fromCharCode(code);
}
switch (code)
{
case 37:
arrowleft = true;
arrowright = false;
break;
case 38:
arrowup = true;
arrowdown = false;
break;
case 39:
arrowright = true;
arrowleft = false;
break;
case 40:
arrowdown = true;
arrowup = false;
break;
case 8: // BACKSPACE
len = editfield.length;
if ( len > 1 )
{
editfield = editfield.substring(0, len-1);
setContent( kbdTarget, toHTML( editfield ) );
document.form.code.value = getContent( kbdTarget );
}
else
{
editfield = "";
setContent( kbdTarget, " " );
document.form.code.value = getContent( kbdTarget );
}
break;
default:
break;
}
window.status = "KeyDown: Modifier[" + modifier + "] KeyCode[" + code +
"] Char[" + ch + "]";
if ( moveTarget != null )
{
moveElement( getElement( moveTarget ) );
// Reset cursor
arrowup = false;
arrowdown = false;
arrowleft = false;
arrowright = false;
}
}
function KP(e)
{
var code;
var modifier;
var ch;
if (N)
{
code = e.which;
modifier = e.modifier;
ch = String.fromCharCode(code);
}
else
{
code = window.event.keyCode;
modifier = window.event.modifier;
ch = String.fromCharCode(code);
}
editfield += ch;
window.status = "KeyPress: Modifier[" + modifier + "] KeyCode[" + code +
"] Char[" + ch + "]";
document.form.object.value = editfield;
if ( kbdTarget != null )
{
var value = '<new >';
document.form.code.value = getContent( kbdTarget );
setContent( kbdTarget, toHTML( editfield ) );
}
}
function MD(e)
{
if (over)
{
ob = getElement( 'panel' );
if (N)
{
X = e.layerX;
Y = e.layerY;
return false;
}
else
{
ob = ob.style;
X = event.offsetX;
Y = event.offsetY;
}
}
}
function MM(e)
{
if (ob)
{
if (N)
{
ob.style.top = e.pageY-Y;
ob.style.left = e.pageX-X;
}
else
{
ob.pixelLeft = event.clientX-X + document.body.scrollLeft;
ob.pixelTop = event.clientY-Y + document.body.scrollTop;
return false;
}
}
}
function MU()
{
ob = null;
}
function fixCursor()
{
if (waiting)
{
document.body.style.cursor = "wait";
}
else if (help)
{
document.body.style.cursor = "help";
}
else if (hand)
{
document.body.style.cursor = "hand";
}
else if (crosshair)
{
document.body.style.cursor = "crosshair";
}
else if (moving)
{
document.body.style.cursor = "move";
}
else if (arrowleft)
{
if (arrowup)
{
document.body.style.cursor = "nw-resize";
}
else if (arrowdown)
{
document.body.style.cursor = "sw-resize";
}
else
{
document.body.style.cursor = "w-resize";
}
}
else if (arrowright)
{
if (arrowup)
{
document.body.style.cursor = "ne-resize";
}
else if (arrowdown)
{
document.body.style.cursor = "se-resize";
}
else
{
document.body.style.cursor = "e-resize";
}
}
else if (arrowup)
{
document.body.style.cursor = "n-resize";
}
else if (arrowdown)
{
document.body.style.cursor = "s-resize";
}
else if (textmode)
{
document.body.style.cursor = "text";
}
else
{
document.body.style.cursor = "auto";
}
//setTimeout("document.body.style.cursor='default'", 100);
}
function getElement(name)
{
var d;
if (!N)
{
d = document.all[name];
}
else
{
d = document.getElementById(name);
}
return d;
}
function setContent(name, value)
{
var d = getElement(name);
d.innerHTML = value;
}
function getContent(name)
{
var d = getElement(name);
return d.innerHTML;
}
function cpos(pos)
{
return parseInt(pos.substring(0, pos.length - 2));
}
function moveElement(moveme)
{
if (arrowleft)
{
moveme.style.left = cpos(moveme.style.left) - movespeed;
if (cpos(moveme.style.left) < 0)
moveme.style.left = 0;
}
if (arrowup)
{
moveme.style.top = cpos(moveme.style.top) - movespeed;
if (cpos(moveme.style.top) < 0)
moveme.style.top = 0;
}
if (arrowright)
{
moveme.style.left = cpos(moveme.style.left) + movespeed;
if (cpos(moveme.style.left) > window.screen.availWidth)
moveme.style.left = window.screen.availWidth;
}
if (arrowdown)
{
moveme.style.top = cpos(moveme.style.top) + movespeed;
if (cpos(moveme.style.top) > window.screen.availHeight)
moveme.style.top = window.screen.availHeight;
}
}
//////////////////////////////////////////////////////////////////////////////
if (N)
{
document.captureEvents(Event.MOUSEDOWN | Event.MOUSEMOVE | Event.MOUSEUP |
Event.KEYPRESS | Event.KEYDOWN);
}
document.onmousedown = MD;
document.onmousemove = MM;
document.onmouseup = MU;
document.onkeydown = KD;
/ -->
</script>
<style>
<!--
.UML
{
border:1px solid #990033;
background-color: #FFFFCC;
font-family:Arial;
font-size:12;
}
.UML-division
{
border-top:1px solid #990033;
background-color: #FFFFCC;
font-family:Arial;
font-size:12;
}
-->
</style>
</head>
<body style='cursor:auto' >
<FORM name="form">
<table border='0' cellspacing='0' cellpadding='0' width='100px'
class='UML' id='panel'
style='position:absolute; left:100px; top:40px; cursor:move'
onmouseover='javascript: over=true;'
onmouseout='javascript: over=false;'
onkeypress='javascript: KP(this);'
onclick='javascript: moveTarget="panel"; editfield=""; '
>
<tr height='20px'
ondblclick='javascript: alert("Show class property");'
>
<td height='20px' id='class0'
style='text-align:center; cursor:text;'
onclick='javascript: change="Arial aliased"; kbdTarget="class0";
moveTarget="panel"; editfield="";'
>Arial aliased</td>
</tr>
<tr height='20px'
ondblclick='javascript: alert("Show attribute property");'
>
<td class='UML-division'>
<table border='0' cellspacing='0' cellpadding='0'>
<tr>
<td width='12px'><nobr> <img
src='attribute.gif'> </nobr></td>
<td id='attr0'
style='text-align:left; cursor:text;'
width='*'
onclick='javascript: change="Attribute"; kbdTarget="attr0";
moveTarget="panel"; editfield="";'
>Attribute</td>
<td width='12px'> </td>
</tr>
</table>
</td>
</tr>
<tr height='20px'
ondblclick='javascript: alert("Show function property");'
>
<td class='UML-division'>
<table border='0' cellspacing='0' cellpadding='0'>
<tr>
<td width='12px'><nobr> <img
src='function.gif'> </nobr></td>
<td id='fn0'
width='*'
style='text-align:left; cursor:text;'
onclick='javascript: change="Function"; kbdTarget="fn0";
moveTarget="panel"; editfield="";'
>Function</td>
<td width='12px'> </td>
</tr>
</table>
</td>
</tr>
</table>
<textarea name="object"
onkeypress=''
style='position:absolute; left:100px; top:200px;'
>
</textarea>
<textarea name="code"
onkeypress=''
style='position:absolute; left:100px; top:250px;'
rows='20' cols='80'
>
</textarea>
</FORM>
</body>
</html>
<!----------------------------------------------------------------------------------------------->
SVG version with PHP4, without Move/Edit Javascript
Beta version fast prototype
<!----------------------------------------------------------------------------------------------->
<!DOCTYPE HTML PUBLIC "-//IETF/DTD HTML//EN">
<html>
<head>
<meta http-equiv='content-type' content='text/html; charset=iso-8859-1'>
<?php
////////////////////////////////////////////////////////////////////////////
// GOTCHA:
//
////////////////////////////////////////////////////////////////////////////
// This script will OVERWRITE this file for outputting purposes!
//
// Make sure this file exist with 666 or -rw-rw-rw permissions
//
// before running this PHP4 script
//
////////////////////////////////////////////////////////////////////////////
$filename = "./~php~temp.svg";
////////////////////////////////////////////////////////////////////////////
if ( !$x ) { $x = 100; }
if ( !$y ) { $y = 100; }
if ( !$w ) { $w = 800; }
if ( !$h ) { $h = 400; }
if ( !$op ) { $op = 'fill'; }
if ( $op == 'frame' ) { writeFrame(); }
else if ( $op == 'blank' ) { writeBlank(); }
else if ( $op == 'fill' ) { writeSVG(); }
else if ( $op == 'display' ) { writeDisplay(); }
function writeFrame()
{
?>
<FRAMESET COLS='*,0' BORDER='0' FRAMESPACING='0'>
<FRAME NAME='main' SRC='<?echo $PHP_SELF ."?op=fill"
."&x=$x&y=$y&h=$h&w=$w"; ?>' MARGINHEIGHT='1' MARGINWIDTH='1'>
<FRAME NAME='data' SRC='<?echo $PHP_SELF ."?op=blank"
."&x=$x&y=$y&h=$h&w=$w"; ?>' MARGINHEIGHT='1' MARGINWIDTH='1' NORESIZE>
</FRAMESET>
</head>
<body><?php
}
function writeSVG()
{
global $x, $y, $h, $w, $op, $filename;
//<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">'."
$svg_head = '<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE svg SYSTEM
"http://www.w3.org/TR/2000/03/WD-SVG-20000303/DTD/svg-20000303-stylable.dtd">'."
<svg enableZoomAndPanControls='false' height='$h' width='$w'>
<!-- ?xml-stylesheet type='tspan/css' href='file.css' ? -->
<style type='text/css'>
<![CDATA[
.RationalRose-beige { fill: #FFFFCC; }
.RationalRose-gray { fill: #808080; }
.RationalRose-red { fill: #990033; }
.RationalRose-cyan { fill: #00FFFF; }
.RationalRose-purple { fill: #FF00FF; }
.white { fill: #FFFFFF; }
.red { fill: #FF0000; }
.green { fill: #00FF00; }
.blue { fill: #0000FF; }
.black { fill: #000000; }
.UML-box-lined { fill: #FFFFCC;
stroke: #990033;
stroke-width: 2;
fill-opacity: 1;
opacity: 1;
stroke-opacity: 1;
stroke-linejoin: mitter;
}
.UML-box-blank { fill: #FFFFCC;
stroke: #FFFFCC;
stroke-width: 0;
fill-opacity: 1;
opacity: 1;
stroke-opacity: 1;
stroke-linejoin: mitter;
}
]]>
</style>
";
?><?php
$svg_def_uml = "
<defs>
<filter height='200%' width='200%' y='-50%' x='-50%'
filterUnits='objectBoundingBox' id='closeDropShadow'>
<feGaussianBlur result='blur' stdDeviation='2'
in='SourceAlpha' />
<feOffset result='offsetGraphic' dy='-2' dx='-2'
in='SourceGraphic' />
<feMerge>
<feMergeNode in='blur'/>
<feMergeNode in='offsetGraphic'/>
</feMerge>
</filter>
<g id='UML_lock'
onmousemove='DoOnMouseMove(evt)'
onmouseover='DoOnMouseOver(evt)'
onmouseup='DoOnMouseUp(evt)'
onmousedown='DoOnMouseDown(evt)'
onmouseout='DoOnMouseOut(evt)'
clone='false'
drag='false'>
<!-- Bitmap derived version -->
<path style='fill:#040404' d='M6 2 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#040404' d='M7 2 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#040404' d='M9 2 l0 1 l-1 0 l-1 0 l0 -1 l2 0 z'/>
<path style='fill:#040404' d='M5 3 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#888888' d='M6 3 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#888888' d='M9 3 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#040404' d='M10 3 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#040404' d='M4 4 l0 1 l0 1 l0 1 l-1 0 l0 -1 l0 -1
l0 -1 l1 0 z'/>
<path style='fill:#888888' d='M5 4 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#888888' d='M6 4 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#040404' d='M8 4 l0 1 l-2 0 l0 -1 l2 0 z'/>
<path style='fill:#888888' d='M9 4 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#888888' d='M10 4 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#040404' d='M11 4 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#888888' d='M5 5 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#040404' d='M6 5 l0 1 l0 1 l-1 0 l0 -1 l0 -1 l1 0
z'/>
<path style='fill:#040404' d='M9 5 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#888888' d='M10 5 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#040404' d='M11 5 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#040404' d='M5 6 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#040404' d='M8 6 l0 1 l-1 0 l-1 0 l0 -1 l2 0 z'/>
<path style='fill:#040404' d='M9 6 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#000000' d='M10 6 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#040404' d='M11 6 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#040404' d='M3 7 l0 1 l0 1 l0 1 l-1 0 l0 -1 l0 -1
l0 -1 l1 0 z'/>
<path style='fill:#888888' d='M11 7 l0 2 l-1 0 l0 -1 l0 -1 l1 0 z'/>
<path style='fill:#040404' d='M12 7 l0 1 l0 1 l0 3 l-1 0 l0 -1 l0 -1
l0 -1 l0 -2 l1 0 z'/>
<path style='fill:#888888' d='M4 8 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#888888' d='M6 8 l0 1 l-1 1 l-1 0 l0 -1 l0 -1 l2 0
z'/>
<path style='fill:#888888' d='M7 8 l1 0 l0 1 l-2 0 l0 -1 l1 0 z'/>
<path style='fill:#888888' d='M9 8 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#888888' d='M10 8 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#888888' d='M4 9 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#888888' d='M6 9 l0 1 l-1 0 l1 -1 z'/>
<path style='fill:#101010' d='M8 9 l0 1 l-1 0 l-1 0 l0 -1 l2 0 z'/>
<path style='fill:#bbbbbb' d='M9 9 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#808080' d='M10 9 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#999999' d='M11 9 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#111111' d='M3 10 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#aaaaaa' d='M4 10 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#999999' d='M5 10 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#cdcdcd' d='M6 10 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#707070' d='M7 10 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#111111' d='M8 10 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#d0d0d0' d='M9 10 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#8c8c8c' d='M10 10 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#8c8c8c' d='M11 10 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#040404' d='M3 11 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#777777' d='M4 11 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#777777' d='M5 11 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#777777' d='M6 11 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#777777' d='M7 11 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#808080' d='M8 11 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#777777' d='M9 11 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#808080' d='M10 11 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#808080' d='M11 11 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#040404' d='M4 12 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#040404' d='M5 12 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#040404' d='M6 12 l1 0 l0 1 l-2 0 l0 -1 l1 0 z'/>
<path style='fill:#040404' d='M8 12 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#040404' d='M9 12 l0 1 l-1 0 l0 -1 l1 0 z'/>
<path style='fill:#040404' d='M10 12 l1 0 l0 1 l-1 0 l-1 0 l0 -1 l1
0 z'/>
<!-- top cadenas light -->
<path style='fill:#ffffff' d='M7 3 l1 0 l0 1 l-2 0 l0 -1 l1 0 z'/>
<!-- inner light -->
<path style='fill:#ffffff' d='M7 5 l1 0 l0 1 l-2 0 l0 -1 l1 0 z'/>
<!-- light filled -->
<path style='fill:#ffffff' d='M 4 7 l1 0 l0 1 l-2 0 l0 -1 l1 0 z'/>
<path style='fill:#cccccc' d='M 6 7 l1 0 l0 1 l-2 0 l0 -1 l1 0 z'/>
<path style='fill:#bbbbbb' d='M 8 7 l1 0 l0 1 l-2 0 l0 -1 l1 0 z'/>
<path style='fill:#999999' d='M10 7 l1 0 l0 1 l-2 0 l0 -1 l1 0 z'/>
<path style='fill:#cccccc' d='M 3 7 l0 2 l.5 0 l0 -2 z'/>
</g>
<g id='UML_attribute'
onmousemove='DoOnMouseMove(evt)'
onmouseover='DoOnMouseOver(evt)'
onmouseup='DoOnMouseUp(evt)'
onmousedown='DoOnMouseDown(evt)'
onmouseout='DoOnMouseOut(evt)'
clone='false'
drag='false'>
<path style='fill:#7777FF; stroke:#000000' d='M 5 0 L 8 4 L 3 9 L 0
6 z' />
<path style='fill:#00FFFF; stroke:#7777FF' d='M 5 0 L 8 3 L 3 8 L 0
5 z' />
<path style='fill:#99FFFF; stroke:#99FFFF' d='M 7.8 2.4 L 5 0 L 0.5
4.5 L 3 6.5 z' />
</g>
<!-- Public function - purple square -->
<g id='UML_function'
onmousemove='DoOnMouseMove(evt)'
onmouseover='DoOnMouseOver(evt)'
onmouseup='DoOnMouseUp(evt)'
onmousedown='DoOnMouseDown(evt)'
onmouseout='DoOnMouseOut(evt)'
clone='false'
drag='false'>
<path style='fill:#7777FF; stroke:#000000' d='M 8 6 L 5 9 L 0 4 L 3
1 z' />
<path style='fill:#FF66FF; stroke:#CC00CC' d='M 3 0 L 8 5 L 5 8 L 0
3 z' />
<path style='fill:#FF66FF; stroke:#FF66FF' d='M 8 5 L 3 0 L 0 3' />
</g>
</defs>
"; ?><?php
$svg_foot = "
<defs>
<g id='Component'>
<rect x='0' y='0' width='100' height='60' class='UML-box-lined'/>
<rect x='0' y='0' width='100' height='60' class='UML-box-blank'/>
<rect x='0' y='20' width='100' height='20' class='UML-box-lined'/>
<rect x='0' y='20' width='100' height='20' class='UML-box-blank'/>
<rect x='0' y='40' width='100' height='20' class='UML-box-lined'/>
<rect x='0' y='40' width='100' height='20' class='UML-box-blank'/>
<text x='10' y='13.5' style='font-family: Arial; font-size: 12; '>
Component
</text>
<!-- Corner: (+1.0, +1.0) -->
<use xlink:href='#UML_lock' x='1' y='21' />
<!-- Corner: (+9.0, +8.0) Lock dist: (+8.0, +7.0) -->
<use xlink:href='#UML_attribute' x='9' y='28' />
<!-- Corner: (+9.0, +8.0) -->
<use xlink:href='#UML_function' x='9' y='48' />
<!-- Corner: (+20.0, +13.5) -->
<text x='20' y='33.5' style='font-family: Arial; font-size: 12; '>
Attribute
</text>
<!-- Corner: (+20.0, +13.5) -->
<text x='20' y='53.5' style='font-family: Arial; font-size: 12; '>
Function
</text>
</g>
</defs>
<use xlink:href='#Component' x='$x' y='$y' />
</svg>
";
$svg = $svg_head . $svg_def_uml . $svg_foot;
$file = fopen( $filename, "w+" );
if ( !$file ) die( "Cannot create/write the file " . $filename );
rewind( $file );
fputs( $file, $svg );
fclose( $file );
?><META HTTP-EQUIV='Refresh' CONTENT='0; URL=<?php
echo $PHP_SELF ."?op=display". "&x=$x&y=$y&h=$h&w=$w";
?>'></head><?php
// echo "<body><br><br><br><center><h1>File saved
$filename</center><br>";
} // End of writeSVG
function writeDisplay()
{
global $x, $y, $h, $w, $op, $filename;
$width = 600;
if ( $w < 1600 )
{
$c1 = "<div align='center'><center>";
$c2 = "</center></div>";
}
else
{
$c1 = "";
$c2 = "";
}
?><title>Title</title>
</head>
<body>
<FORM name='form' ACTION='<?php echo $PHP_SELF; ?>' METHOD='POST'>
<INPUT NAME='op' TYPE='hidden' value='fill'>
<div align='center'><center>
<table border='0'><tr><td>
<!-- script language='JavaScript' src='drag3.js'></script -->
<table border='0' bgcolor='#0000AA'>
<tr><td><table border='1' cellspacing='5'
cellpadding='0'><tr><td><EMBED
SRC='<?php echo $filename; ?>'
NAME='svgEmbed'
TYPE='image/svg+xml'
width='<?php echo $w; ?>'
height='<?php echo $h; ?>'
PLUGINSPAGE='http://www.adobe.com/svg/viewer/install/'
></td></tr></table></td></tr></table>
</td></tr></table>
</center></div>
<?php echo $c1; ?>
<table border='0' width='<?php echo $width; ?>'><tr><td>
<div align='center'><center>
<table border='0'>
<tr>
<td><b> X: </b></td>
<td><INPUT NAME='x' TYPE='text' value='<?php echo $x;
?>'></td>
<td> </td>
<td><b> Y: </b></td>
<td><INPUT NAME='y' TYPE='text' value='<?php echo $y;
?>'></td>
</tr>
<tr>
<td><b> W: </b></td>
<td><INPUT NAME='w' TYPE='text' value='<?php echo $w;
?>'></td>
<td> </td>
<td><b> H: </b></td>
<td><INPUT NAME='h' TYPE='text' value='<?php echo $h;
?>'></td>
</tr>
<tr>
<td colspan='5'><center><INPUT
NAME=' Save ' TYPE='submit'
VALUE=' Save ' ></center></td>
</tr>
<!----------------------------------------------------------------------->
<tr>
<td>move </td>
<td>up </td>
<td>down </td>
<td>out </td>
<td>over </td>
</tr>
<tr>
<td><INPUT NAME='move' TYPE='text' value='<?php echo
$move; ?>'></td>
<td><INPUT NAME='up' TYPE='text' value='<?php echo
$up; ?>'></td>
<td><INPUT NAME='down' TYPE='text' value='<?php echo
$down; ?>'></td>
<td><INPUT NAME='out' TYPE='text' value='<?php echo
$out; ?>'></td>
<td><INPUT NAME='over' TYPE='text' value='<?php echo
$over; ?>'></td>
</tr>
<!----------------------------------------------------------------------->
<tr>
<td>click </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td><INPUT NAME='click' TYPE='text' value='<?php echo
$click; ?>'></td>
</tr>
</table>
</center></div>
</td></tr></table>
<?php echo $c2; ?>
</FORM>
<?php
}
function writeBlank()
{
echo '</head><body>';
}
?>
</body>
</html>
<!----------------------------------------------------------------------------------------------->
Hope this elucidate some problems faced in an industrial/professional usage
of SVG.
Sincerely yours,
Fred P.
_________________________________________________________________
STOP MORE SPAM with the new MSN 8 and get 2 months FREE*
http://join.msn.com/?page=features/junkmail
Received on Saturday, 12 April 2003 08:42:06 UTC