PDA

View Full Version : Opengl and scalable vector graphics (svg)



technomage
04-08-2006, 04:52 PM
Hi everyone

Does anyone have or know if a good implementation fo svg which targets opengl. I have seen sdl_svg but that is limited to rendering to sdl surfaces.

I had a think about this and svg looks like a good way to get really nice gui's in games, it's vector based to will scale easily and has script elements to embed api calls to a scripting system to handle button clicks etc.

Anyway, if anyone know's of any good libraries (c++ or oop) let me know :)

Dean

noeska
04-08-2006, 10:13 PM
All that needs to be done is translate the basic objects of svg into opengl calls and you are done, the bad part is that that is a lot of work.

Here is a starter ( i stopped because of lack of time, but feel free to continue it under the license used for amaya, wich a kind of bsd license, as that is where most source comes from translated from c to pascal)



unit dglSvg;

interface

procedure GL_SetForeground (fg: integer);
procedure GL_SetPicForeground ();
procedure InitDrawing (style: integer; thick: integer; fg: integer);
procedure GL_VideoInvert (width: integer; height: integer; x: integer; y: integer);
procedure GL_DrawEmptyRectangle (fg: integer; x: single; y: single; width: single; height: single; thick: single);
procedure GL_DrawRectangle (fg: integer; x: single; y: single; width: single; height: single);
procedure GL_DrawLine (x1: integer; y1: integer; x2: integer; y2: integer; round: boolean);

procedure GL_DrawArc (x: single; y: single; w: single; h: single; startAngle: integer; sweepAngle: integer; filled: boolean);

procedure DrawOval (frame: integer; thick: integer; style: integer; x: integer; y: integer; width: integer;
height: integer; rx: integer; ry: integer; fg: integer; bg: integer; pattern: integer);

implementation

uses dglOpenGL;

const
M_PI = 3.14159265358979323846;
CSLICES = 360;
SLICES_SIZE = 361;


var
S_thick: integer;
Opacity: GLubyte = 255;
FillOpacity: GLubyte = 255;
StrokeOpacity: GLubyte = 255;
Fill_style: boolean = TRUE;
X_Clip: integer = 0;
Y_Clip: integer = 0;
Width_Clip: integer = 0;
Height_Clip: integer = 0;


(*----------------------------------------------------------------------
GL_SetForeground : set color before drawing a or many vertex
----------------------------------------------------------------------*)
procedure GL_SetForeground (fg: integer);
var
red, green, blue: byte;
us_opac: GLubyte;
begin
if (Fill_style) then
us_opac := FillOpacity
else
begin
us_opac := StrokeOpacity;
Fill_style := TRUE;
end;
// TtaGiveThotRGB (fg, &red, &green, &blue);
red:=0;
green:=0;
blue:=255;

glColor4ub ( GLubyte( red ), GLubyte( green ), GLubyte ( blue ), us_opac );
end;

(*----------------------------------------------------------------------
GL_SetPicForeground : set opacity before drawing a or many vertex
----------------------------------------------------------------------*)
procedure GL_SetPicForeground ();
var
us_opac: GLubyte;
begin
us_opac := FillOpacity;
glColor4ub ( 255, 255, 255, us_opac);
end;

(*----------------------------------------------------------------------
InitDrawing update the Graphic Context accordingly to parameters.
The parameter fg indicates the drawing color
----------------------------------------------------------------------*)
procedure InitDrawing (style: integer; thick: integer; fg: integer);
begin
if (style >= 5) then
begin
// solid
if (thick>0) then
begin
S_thick := thick;
glLineWidth ( thick );
glPointSize ( thick );
end
else
begin
glLineWidth ( 0.5 );
glPointSize ( 0.5 );
end;
glDisable (GL_LINE_STIPPLE);
end
else
begin
if (thick>0) then
begin
S_thick := thick;
if (style = 3) then
begin
// dotted
glLineStipple (thick, $5555);
glEnable (GL_LINE_STIPPLE);
end
else
begin
// dashed
glLineStipple (thick, $1F1F);
glEnable (GL_LINE_STIPPLE);
end;
glLineWidth ( thick );
glPointSize ( thick );
end
else
begin
glLineWidth ( 0.5 );
glPointSize ( 0.5 );
end;

end;
Fill_style := FALSE;
GL_SetForeground (fg);
end;

(*----------------------------------------------------------------------
GL_VideoInvert :
using a transparent yellow instead of inverting... much simpler !
----------------------------------------------------------------------*)
procedure GL_VideoInvert (width: integer; height: integer; x: integer; y: integer);
begin
(*a blend func like that could be coool ?
(GL_ONE_MINUS_DST_COLOR,GL_ZERO) *)
glColor4ub (127, 127, 127, 80);
glBegin (GL_QUADS);
glVertex2i (x, y);
glVertex2i (x + width, y);
glVertex2i (x + width, y + height);
glVertex2i (x, y + height);
glEnd ();
end;


(*----------------------------------------------------------------------
GL_DrawEmptyRectangle Outlined rectangle
----------------------------------------------------------------------*)
procedure GL_DrawEmptyRectangle (fg: integer; x: single; y: single; width: single; height: single; thick: single);
begin
GL_SetForeground (fg);
if ((thick - 1)=0) then
begin
glBegin (GL_LINE_LOOP);
glVertex2f (x, y );
glVertex2f (x + width, y);
glVertex2f (x + width, y + height);
glVertex2f (x, y + height);
end
else
begin
thick := thick / 2;
glBegin (GL_QUADS);

glVertex2f (x - thick, y - thick);
glVertex2f (x + thick + width, y - thick);
glVertex2f (x + thick + width, y + thick);
glVertex2f (x - thick, y + thick);

glVertex2f (x - thick, y - thick + height);
glVertex2f (x + thick + width, y - thick + height);
glVertex2f (x + thick + width, y + thick + height);
glVertex2f (x - thick, y + thick + height);

glVertex2f (x - thick, y - thick);
glVertex2f (x + thick, y - thick);
glVertex2f (x + thick, y + thick + height);
glVertex2f (x - thick, y + thick + height);

glVertex2f (x - thick + width, y - thick);
glVertex2f (x + thick + width, y - thick);
glVertex2f (x + thick + width, y + thick + height);
glVertex2f (x - thick + width, y + thick + height);
end;
glEnd ();
end;

(*----------------------------------------------------------------------
GL_DrawRectangle
(don't use glrect because it's exactly the same but require opengl 1.2)
----------------------------------------------------------------------*)
procedure GL_DrawRectangle (fg: integer; x: single; y: single; width: single; height: single);
begin
GL_SetForeground (fg);
glBegin (GL_QUADS);
glVertex2f (x, y);
glVertex2f (x + width, y);
glVertex2f (x + width, y + height);
glVertex2f (x, y + height);
glEnd ();
end;

(*----------------------------------------------------------------------
GL_DrawLine
----------------------------------------------------------------------*)
procedure GL_DrawLine (x1: integer; y1: integer; x2: integer; y2: integer; round: boolean);
begin
if ( (S_thick > 1) AND round) then
begin
// round line join
glBegin (GL_POINTS);
glVertex2i (x1, y1);
glVertex2i (x2, y2);
glEnd ();
end;
glBegin (GL_LINES) ;
glVertex2i (x1, y1);
glVertex2i (x2, y2);
glEnd ();
end;

(*----------------------------------------------------------------------
GL_DrawArc : Draw an arc
----------------------------------------------------------------------*)
procedure GL_DrawArc (x: single; y: single; w: single; h: single; startAngle: integer; sweepAngle: integer; filled: boolean);
var
i, slices: GLint;
angleOffset: single;
sinCache: array[0..SLICES_SIZE] of single;
cosCache: array[0..SLICES_SIZE] of single;
y_cache: array[0..SLICES_SIZE] of single;
x_cache: array[0..SLICES_SIZE] of single;
angle: single;
fastx, fasty, width, height: single;
begin


width := (w) / 2;
height := (h) / 2;
fastx := (x) + width;
fasty := (y) + height;
if &#40;w < 10&#41; AND &#40;h < 10&#41; then
begin
glPointSize &#40; 0.1 &#41;;
slices &#58;= 36;
end
else
slices &#58;= CSLICES;

startAngle &#58;= startAngle;
sweepAngle &#58;= sweepAngle;

// Cache is the vertex locations cache
angleOffset &#58;= &#40;startAngle / 180.0 * M_PI&#41;;
for i &#58;= 0 to slices do
begin
angle &#58;= angleOffset + &#40;&#40;M_PI * sweepAngle&#41; / 180.0&#41; * i / slices;
cosCache&#91;i&#93; &#58;= COS&#40;angle&#41;;
sinCache&#91;i&#93; &#58;= SIN&#40;angle&#41;;
end;

if &#40;abs &#40;sweepAngle - 360.0&#41; < 0.0001&#41; then
begin
sinCache&#91;slices&#93; &#58;= sinCache&#91;0&#93;;
cosCache&#91;slices&#93; &#58;= cosCache&#91;0&#93;;
end;

for i &#58;= 0 to slices do
begin
x_cache&#91;i&#93; &#58;= fastx + &#40;width * cosCache&#91;i&#93;&#41;;
y_cache&#91;i&#93; &#58;= fasty - &#40;height * sinCache&#91;i&#93;&#41;;
end;

if &#40;filled&#41; then
begin
glBegin &#40;GL_TRIANGLE_FAN&#41;;
// The center
glVertex2d &#40;fastx, fasty&#41;;
for i &#58;= 0 to slices do
glVertex2d &#40;x_cache&#91;i&#93;, y_cache&#91;i&#93;&#41;;
glEnd&#40;&#41;;
end;

if &#40;filled=FALSE&#41; then
begin
if &#40;w < 20&#41; AND &#40;h < 20&#41; then
glBegin&#40;GL_POINTS&#41;
else
glBegin&#40;GL_LINE_STRIP&#41;;

slices &#58;= slices -1;
for i &#58;= 0 to slices do
glVertex2d &#40;x_cache&#91;i&#93;, y_cache&#91;i&#93;&#41;;

glEnd&#40;&#41;;
end;
end;

&#40;*----------------------------------------------------------------------
GL_Point &#58;
Draw a point using GL primitives
----------------------------------------------------------------------*&#41;
procedure GL_Point &#40;fg&#58; integer; width&#58; single; x&#58; single; y&#58;single&#41;;
begin
GL_SetForeground &#40;fg&#41;;
glPointSize &#40;width&#41;;
glBegin &#40;GL_POINTS&#41;;
glVertex2f &#40;x, y&#41;;
glEnd &#40;&#41;;
end;

type tarc = record
width&#58; integer;
height&#58; integer;
x&#58; integer;
y&#58; integer;
angle1&#58; integer;
angle2&#58; integer;
end;

tseg = record
x1&#58; integer;
x2&#58; integer;
y1&#58; integer;
y2&#58; integer;
end;

tpoint = record
x&#58; integer;
y&#58; integer;
end;

&#40;*----------------------------------------------------------------------
GL_DrawSegments
----------------------------------------------------------------------*&#41;
procedure GL_DrawSegments &#40;var point&#58; array of tseg; npoints&#58; integer&#41;;
var
i&#58; integer;
begin

if &#40;S_thick > 1&#41; then
begin
glBegin &#40;GL_POINTS&#41;;
for i&#58;=0 to npoints-1 do
begin
glVertex2f &#40; point&#91;i&#93;.x1 ,
point&#91;i&#93;.y1 &#41;;
glVertex2f &#40;point&#91;i&#93;.x2 ,
point&#91;i&#93;.y2 &#41;;
end;
glEnd &#40;&#41;;
end;
glBegin &#40;GL_LINES&#41; ;
for i&#58;=0 to npoints-1 do
begin
glVertex2f &#40; point&#91;i&#93;.x1 ,
point&#91;i&#93;.y1&#41;;
glVertex2f &#40; point&#91;i&#93;.x2 ,
point&#91;i&#93;.y2&#41;;
end;
glEnd &#40;&#41;;
end;

&#40;*----------------------------------------------------------------------
GL_DrawPolygon &#58; tesselation handles
convex, concave and polygon with holes
----------------------------------------------------------------------*&#41;
procedure GL_DrawPolygon &#40;var points&#58; array of tpoint; npoints&#58; integer&#41;;
begin
//MakefloatMesh &#40;points, npoints&#41;;
end;


&#40;*----------------------------------------------------------------------
DrawOval draw a rectangle with rounded corners.
Parameters fg, bg, and pattern are for drawing
color, background color and fill pattern.
----------------------------------------------------------------------*&#41;
procedure DrawOval &#40;frame&#58; integer; thick&#58; integer; style&#58; integer; x&#58; integer; y&#58; integer; width&#58; integer;
height&#58; integer; rx&#58; integer; ry&#58; integer; fg&#58; integer; bg&#58; integer; pattern&#58; integer&#41;;
var
i&#58; integer;
arc, dx, dy&#58; integer;
xf, yf&#58; integer;
xarc&#58; array&#91;0..4&#93; of tarc;
seg&#58; array&#91;0..4&#93; of tseg;
point&#58; array&#91;0..13&#93; of tpoint;
begin


//width &#58;= width - thick;
//height &#58;= height - thick;
//x &#58;= x+thick div 2;
//y &#58;= y+thick div 2;

y &#58;= y; //+FrameTable&#91;frame&#93;.FrTopMargin;

// radius of arcs
if &#40;rx = 0&#41; AND &#40;ry <> 0&#41; then
rx &#58;= ry
else if &#40;ry = 0&#41; AND &#40;rx <> 0&#41; then
ry &#58;= rx;
arc &#58;= width div 2;
if &#40;rx > arc&#41; then
rx &#58;= arc;
arc &#58;= height div 2;
if &#40;ry > arc&#41; then
ry &#58;= arc;
dx &#58;= rx;
dy &#58;= ry;
rx &#58;= rx * 2;
ry &#58;= ry * 2;
xf &#58;= x + width - 1;
yf &#58;= y + height - 1;

xarc&#91;0&#93;.x &#58;= x;
xarc&#91;0&#93;.y &#58;= y;
xarc&#91;0&#93;.width &#58;= rx;
xarc&#91;0&#93;.height &#58;= ry;
xarc&#91;0&#93;.angle1 &#58;= 90;
xarc&#91;0&#93;.angle2 &#58;= 90;

xarc&#91;1&#93;.x &#58;= xf - rx;
xarc&#91;1&#93;.y &#58;= xarc&#91;0&#93;.y;
xarc&#91;1&#93;.width &#58;= rx;
xarc&#91;1&#93;.height &#58;= ry;
xarc&#91;1&#93;.angle1 &#58;= 0;
xarc&#91;1&#93;.angle2 &#58;= xarc&#91;0&#93;.angle2;

xarc&#91;2&#93;.x &#58;= xarc&#91;0&#93;.x;
xarc&#91;2&#93;.y &#58;= yf - ry;
xarc&#91;2&#93;.width &#58;= rx;
xarc&#91;2&#93;.height &#58;= ry;
xarc&#91;2&#93;.angle1 &#58;= 180;
xarc&#91;2&#93;.angle2 &#58;= xarc&#91;0&#93;.angle2;

xarc&#91;3&#93;.x &#58;= xarc&#91;1&#93;.x;
xarc&#91;3&#93;.y &#58;= xarc&#91;2&#93;.y;
xarc&#91;3&#93;.width &#58;= rx;
xarc&#91;3&#93;.height &#58;= ry;
xarc&#91;3&#93;.angle1 &#58;= 270;
xarc&#91;3&#93;.angle2 &#58;= xarc&#91;0&#93;.angle2;

seg&#91;0&#93;.x1 &#58;= x + dx;
seg&#91;0&#93;.x2 &#58;= xf - dx;
seg&#91;0&#93;.y1 &#58;= y;
seg&#91;0&#93;.y2 &#58;= seg&#91;0&#93;.y1;

seg&#91;1&#93;.x1 &#58;= xf;
seg&#91;1&#93;.x2 &#58;= seg&#91;1&#93;.x1;
seg&#91;1&#93;.y1 &#58;= y + dy;
seg&#91;1&#93;.y2 &#58;= yf - dy;

seg&#91;2&#93;.x1 &#58;= seg&#91;0&#93;.x1;
seg&#91;2&#93;.x2 &#58;= seg&#91;0&#93;.x2;
seg&#91;2&#93;.y1 &#58;= yf;
seg&#91;2&#93;.y2 &#58;= seg&#91;2&#93;.y1;

seg&#91;3&#93;.x1 &#58;= x;
seg&#91;3&#93;.x2 &#58;= seg&#91;3&#93;.x1;
seg&#91;3&#93;.y1 &#58;= seg&#91;1&#93;.y1;
seg&#91;3&#93;.y2 &#58;= seg&#91;1&#93;.y2;

// Fill in the figure
if &#40;pattern = 2&#41; then
begin
// Polygone inscrit&#58; &#40;seg0&#41;
// 0--1
// 10-| |-3
// &#40;seg3&#41; | |&#40;seg1&#41;
// 9--| |-4
// 7--6
// &#40;seg2&#41;
point&#91;0&#93;.x &#58;= seg&#91;0&#93;.x1;
point&#91;0&#93;.y &#58;= seg&#91;0&#93;.y1;

point&#91;1&#93;.x &#58;= seg&#91;0&#93;.x2;
point&#91;1&#93;.y &#58;= point&#91;0&#93;.y;
point&#91;2&#93;.x &#58;= point&#91;1&#93;.x;
point&#91;2&#93;.y &#58;= seg&#91;1&#93;.y1;

point&#91;3&#93;.x &#58;= seg&#91;1&#93;.x1;
point&#91;3&#93;.y &#58;= point&#91;2&#93;.y;
point&#91;4&#93;.x &#58;= point&#91;3&#93;.x;
point&#91;4&#93;.y &#58;= seg&#91;1&#93;.y2;

point&#91;5&#93;.x &#58;= seg&#91;2&#93;.x2;
point&#91;5&#93;.y &#58;= point&#91;4&#93;.y;
point&#91;6&#93;.x &#58;= point&#91;5&#93;.x;
point&#91;6&#93;.y &#58;= seg&#91;2&#93;.y2;

point&#91;7&#93;.x &#58;= seg&#91;2&#93;.x1;
point&#91;7&#93;.y &#58;= point&#91;6&#93;.y;
point&#91;8&#93;.x &#58;= point&#91;7&#93;.x;
point&#91;8&#93;.y &#58;= seg&#91;3&#93;.y2;

point&#91;9&#93;.x &#58;= seg&#91;3&#93;.x2;
point&#91;9&#93;.y &#58;= point&#91;8&#93;.y;
point&#91;10&#93;.x &#58;= point&#91;9&#93;.x;
point&#91;10&#93;.y &#58;= seg&#91;3&#93;.y1;

point&#91;11&#93;.x &#58;= point&#91;0&#93;.x;
point&#91;11&#93;.y &#58;= point&#91;10&#93;.y;
point&#91;12&#93;.x &#58;= point&#91;0&#93;.x;
point&#91;12&#93;.y &#58;= point&#91;0&#93;.y;

GL_SetForeground &#40;bg&#41;;

GL_DrawPolygon &#40;point, 13&#41;; //not implemented yet

for i&#58;=0 to 3 do
begin
GL_DrawArc &#40;xarc&#91;i&#93;.x + thick/4, xarc&#91;i&#93;.y + thick/4,
xarc&#91;i&#93;.width - thick/4, xarc&#91;i&#93;.height-thick/4,
xarc&#91;i&#93;.angle1, xarc&#91;i&#93;.angle2,
TRUE&#41;;
end;
end;


// Draw the border
if &#40;thick > 0&#41; AND &#40;fg >= 0&#41; then
begin
InitDrawing &#40;style, thick, fg&#41;;
for i&#58;=0 to 3 do
GL_DrawArc &#40;xarc&#91;i&#93;.x, xarc&#91;i&#93;.y,
xarc&#91;i&#93;.width, xarc&#91;i&#93;.height,
xarc&#91;i&#93;.angle1, xarc&#91;i&#93;.angle2,
FALSE&#41;;
//GL_DrawSegments &#40;seg, 4&#41;;
end;
end;

end.

technomage
06-08-2006, 04:19 PM
Hi Noeska

Thanks for posting the code you have. I had a funny feeling it was going to be a write your own job :wink:

I'll have a look at your code, do you remember the c source of this :?:

Dean

noeska
07-08-2006, 08:08 PM
http://www.w3.org/Amaya/User/SourceDist.html

DJMaster
12-09-2016, 07:01 PM
You can take a look at LibRsvg + Cairo:

https://github.com/DJMaster/librsvg-fpc
https://github.com/DJMaster/cairo-fpc

Strongly tested under Windows. Other OSs will be available soon.


http://www.djmaster.com/images/freepascal/Tiger.png

phibermon
13-09-2016, 08:50 AM
Been through your header collection - very comprehensive and useful! thanks very much for sharing your work

DJMaster
13-09-2016, 05:06 PM
Thank you phibermon for your comment, really appreciated!



Been through your header collection - very comprehensive and useful! thanks very much for sharing your work