summaryrefslogtreecommitdiff
path: root/amiga
diff options
context:
space:
mode:
authorChris Young <chris@unsatisfactorysoftware.co.uk>2009-05-19 07:23:56 +0000
committerChris Young <chris@unsatisfactorysoftware.co.uk>2009-05-19 07:23:56 +0000
commit6f120338edb03bbdf7224f1b4d5560caf61bb002 (patch)
tree90161e3be8f111dc224a0c1b0c98e61098abeee1 /amiga
parentefe2151c9a1d811b7b28d2f8c169688e7615ea11 (diff)
downloadnetsurf-6f120338edb03bbdf7224f1b4d5560caf61bb002.tar.gz
netsurf-6f120338edb03bbdf7224f1b4d5560caf61bb002.tar.bz2
Add ability to copy SVGs to the clipboard and save in IFF DR2D format.
svn path=/trunk/netsurf/; revision=7523
Diffstat (limited to 'amiga')
-rwxr-xr-xamiga/clipboard.c14
-rwxr-xr-xamiga/clipboard.h1
-rwxr-xr-xamiga/context_menu.c31
-rw-r--r--amiga/download.c16
-rwxr-xr-xamiga/gui.c4
-rw-r--r--amiga/iff_dr2d.c395
-rw-r--r--amiga/iff_dr2d.h105
-rwxr-xr-xamiga/menu.c22
8 files changed, 576 insertions, 12 deletions
diff --git a/amiga/clipboard.c b/amiga/clipboard.c
index 51b8e3100..fd4289d06 100755
--- a/amiga/clipboard.c
+++ b/amiga/clipboard.c
@@ -30,6 +30,7 @@
#include <datatypes/pictureclass.h>
#include <proto/datatypes.h>
#include "amiga/bitmap.h"
+#include "amiga/iff_dr2d.h"
struct IFFHandle *iffh = NULL;
@@ -245,3 +246,16 @@ bool ami_easy_clipboard_bitmap(struct bitmap *bitmap)
DisposeDTObject(dto);
}
}
+
+bool ami_easy_clipboard_svg(struct content *c)
+{
+ if(c->type != CONTENT_SVG) return false;
+
+ if(!(OpenIFF(iffh,IFFF_WRITE)))
+ {
+ ami_svg_to_dr2d(iffh,c->source_data,c->source_size,c->url);
+ CloseIFF(iffh);
+ }
+
+ return true;
+}
diff --git a/amiga/clipboard.h b/amiga/clipboard.h
index 806420566..9fccf01d0 100755
--- a/amiga/clipboard.h
+++ b/amiga/clipboard.h
@@ -23,4 +23,5 @@ void ami_clipboard_init(void);
void ami_clipboard_free(void);
bool ami_easy_clipboard(char *text);
bool ami_easy_clipboard_bitmap(struct bitmap *bitmap);
+bool ami_easy_clipboard_svg(struct content *c);
#endif
diff --git a/amiga/context_menu.c b/amiga/context_menu.c
index b5f02f0da..7f60d4963 100755
--- a/amiga/context_menu.c
+++ b/amiga/context_menu.c
@@ -33,6 +33,7 @@
#include <proto/asl.h>
#include "desktop/textinput.h"
#include "amiga/bitmap.h"
+#include "amiga/iff_dr2d.h"
uint32 ami_context_menu_hook(struct Hook *hook,Object *item,APTR reserved);
@@ -280,9 +281,18 @@ uint32 ami_context_menu_hook(struct Hook *hook,Object *item,APTR reserved)
case CMID_CLIPOBJ:
object = (struct content *)userdata;
- object->bitmap->url = object->url;
- object->bitmap->title = object->title;
- ami_easy_clipboard_bitmap(object->bitmap);
+ if(object->bitmap)
+ {
+ object->bitmap->url = object->url;
+ object->bitmap->title = object->title;
+ ami_easy_clipboard_bitmap(object->bitmap);
+ }
+#ifdef WITH_NS_SVG
+ else if(object->type == CONTENT_SVG)
+ {
+ ami_easy_clipboard_svg(object);
+ }
+#endif
break;
case CMID_SAVEOBJ:
@@ -322,9 +332,18 @@ uint32 ami_context_menu_hook(struct Hook *hook,Object *item,APTR reserved)
char fname[1024];
strlcpy(&fname,savereq->fr_Drawer,1024);
AddPart(fname,savereq->fr_File,1024);
- object->bitmap->url = object->url;
- object->bitmap->title = object->title;
- bitmap_save(object->bitmap,fname,0);
+ if(object->bitmap)
+ {
+ object->bitmap->url = object->url;
+ object->bitmap->title = object->title;
+ bitmap_save(object->bitmap,fname,0);
+ }
+#ifdef WITH_NS_SVG
+ else if(object->type == CONTENT_SVG)
+ {
+ ami_save_svg(object,fname);
+ }
+#endif
SetComment(fname,object->url);
ami_update_pointer(gwin->win,GUI_POINTER_DEFAULT);
}
diff --git a/amiga/download.c b/amiga/download.c
index fe9f370f5..5eeeccab1 100644
--- a/amiga/download.c
+++ b/amiga/download.c
@@ -31,6 +31,7 @@
#include "amiga/options.h"
#include "amiga/save_complete.h"
#include "amiga/bitmap.h"
+#include "amiga/iff_dr2d.h"
#include "content/fetch.h"
@@ -368,10 +369,19 @@ void ami_drag_save(struct Window *win)
case GUI_SAVE_OBJECT_NATIVE:
{
struct content *c = drag_save_data;
- c->bitmap->url = c->url;
- c->bitmap->title = c->title;
AddPart(path,c->title,1024);
- bitmap_save(c->bitmap,path,0);
+ if(c->bitmap)
+ {
+ c->bitmap->url = c->url;
+ c->bitmap->title = c->title;
+ bitmap_save(c->bitmap,path,0);
+ }
+#ifdef WITH_NS_SVG
+ else if(c->type == CONTENT_SVG)
+ {
+ ami_save_svg(c,path);
+ }
+#endif
}
break;
}
diff --git a/amiga/gui.c b/amiga/gui.c
index e8b3743f2..6526811d4 100755
--- a/amiga/gui.c
+++ b/amiga/gui.c
@@ -2797,7 +2797,11 @@ void gui_window_new_content(struct gui_window *g)
OffMenu(g->shared->win,AMI_MENU_CLEAR);
OffMenu(g->shared->win,AMI_MENU_FIND);
+#ifdef WITH_NS_SVG
+ if(c->bitmap || c->type == CONTENT_SVG)
+#else
if(c->bitmap)
+#endif
{
OnMenu(g->shared->win,AMI_MENU_COPY);
OnMenu(g->shared->win,AMI_MENU_SAVEAS_IFF);
diff --git a/amiga/iff_dr2d.c b/amiga/iff_dr2d.c
new file mode 100644
index 000000000..4779e3241
--- /dev/null
+++ b/amiga/iff_dr2d.c
@@ -0,0 +1,395 @@
+/*
+ * Copyright 2009 Chris Young <chris@unsatisfactorysoftware.co.uk>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef WITH_NS_SVG
+
+#include <stdio.h>
+#include <svgtiny.h>
+#include <proto/exec.h>
+#include <string.h>
+#include "iff_dr2d.h"
+#include <proto/dos.h>
+
+struct ColorRegister cm[1000];
+ULONG numcols;
+
+ULONG findcolour(ULONG newcol)
+{
+ ULONG i;
+ ULONG colour = 0xFFFFFFFF;
+ UBYTE red,grn,blu;
+
+ red = svgtiny_RED(newcol);
+ grn = svgtiny_GREEN(newcol);
+ blu = svgtiny_BLUE(newcol);
+
+ for(i=0;i<numcols;i++)
+ {
+ if((cm[i].red == red) && (cm[i].green == grn) && (cm[i].blue == blu))
+ colour = i;
+ }
+
+ return colour;
+}
+
+void addcolour(ULONG newcol)
+{
+ int i;
+ ULONG colour;
+ UBYTE red,grn,blu;
+
+ colour = findcolour(newcol);
+
+ if(colour == 0xFFFFFFFF)
+ {
+ cm[numcols].red = svgtiny_RED(newcol);
+ cm[numcols].green = svgtiny_GREEN(newcol);
+ cm[numcols].blue = svgtiny_BLUE(newcol);
+
+ numcols++;
+ }
+}
+
+bool ami_svg_to_dr2d(struct IFFHandle *iffh,char *buffer, uint32 size, char *url)
+{
+ struct svgtiny_diagram *diagram;
+ svgtiny_code code;
+ unsigned int i;
+ unsigned int j;
+ BOOL fons_written = FALSE;
+ struct fons_struct *fons;
+ struct stxt_struct *stxt;
+ struct attr_struct *attr;
+
+ /* create svgtiny object */
+ diagram = svgtiny_create();
+ if (!diagram) {
+ fprintf(stderr, "svgtiny_create failed\n");
+ return 1;
+ }
+
+ /* parse */
+ code = svgtiny_parse(diagram, buffer, size, url, 1000, 1000);
+ if (code != svgtiny_OK) {
+ fprintf(stderr, "svgtiny_parse failed: ");
+ switch (code) {
+ case svgtiny_OUT_OF_MEMORY:
+ fprintf(stderr, "svgtiny_OUT_OF_MEMORY");
+ break;
+ case svgtiny_LIBXML_ERROR:
+ fprintf(stderr, "svgtiny_LIBXML_ERROR");
+ break;
+ case svgtiny_NOT_SVG:
+ fprintf(stderr, "svgtiny_NOT_SVG");
+ break;
+ case svgtiny_SVG_ERROR:
+ fprintf(stderr, "svgtiny_SVG_ERROR: line %i: %s",
+ diagram->error_line,
+ diagram->error_message);
+ break;
+ default:
+ fprintf(stderr, "unknown svgtiny_code %i", code);
+ break;
+ }
+ fprintf(stderr, "\n");
+ }
+
+ if(!(PushChunk(iffh,ID_DR2D,ID_FORM,IFFSIZE_UNKNOWN)))
+ {
+ if(!(PushChunk(iffh,0,ID_NAME,IFFSIZE_UNKNOWN)))
+ {
+ WriteChunkBytes(iffh,url,strlen(url));
+ PopChunk(iffh);
+ }
+
+ if(!(PushChunk(iffh,0,ID_ANNO,18)))
+ {
+ WriteChunkBytes(iffh,"Created by NetSurf",18);
+ PopChunk(iffh);
+ }
+
+ if(!(PushChunk(iffh,0,ID_DRHD,16)))
+ {
+ struct drhd_struct drhd;
+ drhd.XLeft = (float) 0.0;
+ drhd.YTop = (float) 0.0;
+ drhd.XRight = (float) diagram->width;
+ drhd.YBot = (float) diagram->height;
+
+ WriteChunkBytes(iffh,&drhd,16);
+ PopChunk(iffh);
+ }
+
+ if(!(PushChunk(iffh,0,ID_DASH,IFFSIZE_UNKNOWN)))
+ {
+ struct dash_struct dash;
+ dash.DashID = 1;
+ dash.NumDashes = 0;
+
+ WriteChunkBytes(iffh,&dash,sizeof(struct dash_struct));
+ PopChunk(iffh);
+ }
+
+ if(!(PushChunk(iffh,0,ID_CMAP,IFFSIZE_UNKNOWN)))
+ {
+ for (i = 0; i != diagram->shape_count; i++) {
+ if(diagram->shape[i].fill != svgtiny_TRANSPARENT)
+ {
+ addcolour(diagram->shape[i].fill);
+ }
+
+ if(diagram->shape[i].stroke != svgtiny_TRANSPARENT)
+ {
+ addcolour(diagram->shape[i].stroke);
+ }
+ }
+
+ WriteChunkBytes(iffh,cm,3*numcols);
+ PopChunk(iffh);
+ }
+
+ for (i = 0; i != diagram->shape_count; i++) {
+ attr = AllocVec(sizeof(struct attr_struct),MEMF_CLEAR | MEMF_PRIVATE);
+ if (diagram->shape[i].fill == svgtiny_TRANSPARENT)
+ attr->FillType = FT_NONE;
+ else
+ {
+ attr->FillType = FT_COLOR;
+ attr->FillValue = findcolour(diagram->shape[i].fill);
+ }
+ if (diagram->shape[i].stroke == svgtiny_TRANSPARENT)
+ attr->DashPattern = 0;
+ else
+ {
+ attr->DashPattern = 1;
+ attr->EdgeValue = findcolour(diagram->shape[i].stroke);
+ }
+ attr->EdgeThick = (float) diagram->shape[i].stroke_width;
+
+ if(!(PushChunk(iffh,0,ID_ATTR,IFFSIZE_UNKNOWN)))
+ {
+ WriteChunkBytes(iffh,attr,14);
+ PopChunk(iffh);
+ }
+ FreeVec(attr);
+
+ if (diagram->shape[i].path) {
+ union {
+ float PolyPoints;
+ ULONG val;
+ } poly[(diagram->shape[i].path_length)*2];
+
+ USHORT NumPoints;
+ long type;
+ float curx,cury;
+
+ curx = 0.0;
+ cury = 0.0;
+ NumPoints = 0;
+ type = ID_OPLY;
+
+ for (j = 0;
+ j != diagram->shape[i].path_length; ) {
+ switch ((int) diagram->shape[i].path[j]) {
+ case svgtiny_PATH_MOVE:
+ if(j != 0)
+ {
+ poly[NumPoints*2].val = INDICATOR;
+ poly[(NumPoints*2)+1].val = IND_MOVETO;
+ NumPoints++;
+ }
+ poly[(NumPoints*2)].PolyPoints = diagram->shape[i].path[j + 1];
+ poly[(NumPoints*2)+1].PolyPoints = diagram->shape[i].path[j + 2];
+ NumPoints++;
+ curx = (float) diagram->shape[i].path[j + 1];
+ cury = (float) diagram->shape[i].path[j + 2];
+
+ j += 3;
+ break;
+ case svgtiny_PATH_CLOSE:
+ type = ID_CPLY;
+ j += 1;
+ break;
+ case svgtiny_PATH_LINE:
+ poly[(NumPoints*2)].PolyPoints = (float) diagram->shape[i].path[j + 1];
+ poly[(NumPoints*2)+1].PolyPoints = (float) diagram->shape[i].path[j + 2];
+ NumPoints++;
+ curx = (float) diagram->shape[i].path[j + 1];
+ cury = (float) diagram->shape[i].path[j + 2];
+ j += 3;
+ break;
+ case svgtiny_PATH_BEZIER:
+ poly[NumPoints*2].val = INDICATOR;
+ poly[(NumPoints*2)+1].val = IND_CURVE;
+ NumPoints++;
+ poly[(NumPoints*2)].PolyPoints = curx;
+ poly[(NumPoints*2)+1].PolyPoints = cury;
+ NumPoints++;
+ poly[(NumPoints*2)].PolyPoints = (float) diagram->shape[i].path[j + 1];
+ poly[(NumPoints*2)+1].PolyPoints = (float) diagram->shape[i].path[j + 2];
+ NumPoints++;
+ poly[(NumPoints*2)].PolyPoints = (float) diagram->shape[i].path[j + 3];
+ poly[(NumPoints*2)+1].PolyPoints = (float) diagram->shape[i].path[j + 4];
+ NumPoints++;
+ poly[(NumPoints*2)].PolyPoints = (float) diagram->shape[i].path[j + 5];
+ poly[(NumPoints*2)+1].PolyPoints = (float) diagram->shape[i].path[j + 6];
+ curx = poly[(NumPoints*2)].PolyPoints;
+ cury = poly[(NumPoints*2)+1].PolyPoints;
+ NumPoints++;
+ j += 7;
+ break;
+ default:
+ printf("error\n");
+ j += 1;
+ }
+ }
+ if(!(PushChunk(iffh,0,type,IFFSIZE_UNKNOWN)))
+ {
+ WriteChunkBytes(iffh,&NumPoints,sizeof(USHORT));
+ WriteChunkBytes(iffh,poly,NumPoints*2*4);
+ PopChunk(iffh);
+ }
+ } else if (diagram->shape[i].text) {
+ stxt = AllocVec(sizeof(struct stxt_struct),MEMF_CLEAR);
+ stxt->BaseX = diagram->shape[i].text_x;
+ stxt->BaseY = diagram->shape[i].text_y;
+ stxt->NumChars = strlen(diagram->shape[i].text);
+ if(!fons_written)
+ {
+ fons = AllocVec(sizeof(struct fons_struct),MEMF_CLEAR);
+ if(!(PushChunk(iffh,0,ID_FONS,IFFSIZE_UNKNOWN)))
+ {
+ WriteChunkBytes(iffh,fons,sizeof(struct fons_struct));
+ WriteChunkBytes(iffh,"Topaz",5);
+ PopChunk(iffh);
+ }
+ FreeVec(fons);
+ fons_written = TRUE;
+ }
+
+ if(!(PushChunk(iffh,0,ID_STXT,IFFSIZE_UNKNOWN)))
+ {
+ WriteChunkBytes(iffh,stxt,26);
+ WriteChunkBytes(iffh,diagram->shape[i].text,strlen(diagram->shape[i].text));
+ PopChunk(iffh);
+ }
+ FreeVec(stxt);
+ }
+ }
+
+ PopChunk(iffh);
+ }
+
+ svgtiny_free(diagram);
+
+ return 0;
+}
+
+#ifndef AMIGA_DR2D_STANDALONE
+bool ami_save_svg(struct content *c,char *filename)
+{
+ struct IFFHandle *iffh;
+
+ if(iffh = AllocIFF())
+ {
+ if(iffh->iff_Stream = Open(filename,MODE_NEWFILE))
+ {
+ InitIFFasDOS(iffh);
+ }
+ else return false;
+ }
+
+ if((OpenIFF(iffh,IFFF_WRITE))) return false;
+
+ ami_svg_to_dr2d(iffh,c->source_data,c->source_size,c->url);
+
+ if(iffh) CloseIFF(iffh);
+ if(iffh->iff_Stream) Close((BPTR)iffh->iff_Stream);
+ if(iffh) FreeIFF(iffh);
+
+}
+#else
+/*
+ * This code can be compiled as a standalone program for testing etc.
+ * Use something like the following line:
+ * gcc -o svg2dr2d iff_dr2d.c -lauto -lsvgtiny -lxml2 -lpthread -lz -use-dynld
+ * -DWITH_NS_SVG -DAMIGA_DR2D_STANDALONE -D__USE_INLINE__
+ */
+const char USED ver[] = "\0$VER: svg2dr2d 1.1 (18.05.2009)\0";
+
+int main(int argc, char **argv)
+{
+ BPTR fh = 0;
+ char *buffer;
+ size_t n;
+ struct IFFHandle *iffh = NULL;
+ int64 size;
+ LONG rarray[] = {0,0};
+ struct RDArgs *args;
+ STRPTR template = "SVG=INPUT/A,DR2D=OUTPUT/A";
+ enum
+ {
+ A_SVG,
+ A_DR2D
+ };
+
+ args = ReadArgs(template,rarray,NULL);
+
+ if(!args)
+ {
+ printf("Required argument missing\n");
+ return 20;
+ }
+
+ if(fh = Open((char *)rarray[A_SVG],MODE_OLDFILE))
+ {
+ size = GetFileSize(fh);
+
+ buffer = AllocVec((uint32)size,MEMF_PRIVATE);
+
+ Read(fh,buffer,(uint32)size);
+ Close(fh);
+ }
+ else
+ {
+ printf("Unable to open file\n");
+ return 20;
+ }
+ FreeVec(buffer);
+
+ if(iffh = AllocIFF())
+ {
+ if(iffh->iff_Stream = Open((char *)rarray[A_DR2D],MODE_NEWFILE))
+ {
+ InitIFFasDOS(iffh);
+ }
+ else return 20;
+ }
+
+ if((OpenIFF(iffh,IFFF_WRITE))) return 20;
+
+ ami_svg_to_dr2d(iffh,buffer,size,(char *)rarray[A_SVG]);
+
+ if(iffh) CloseIFF(iffh);
+ if(iffh->iff_Stream) Close((BPTR)iffh->iff_Stream);
+ if(iffh) FreeIFF(iffh);
+ FreeArgs(args);
+}
+
+#endif // AMIGA_DR2D_STANDALONE
+#endif // WITH_NS_SVG
diff --git a/amiga/iff_dr2d.h b/amiga/iff_dr2d.h
new file mode 100644
index 000000000..19286a62b
--- /dev/null
+++ b/amiga/iff_dr2d.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2009 Chris Young <chris@unsatisfactorysoftware.co.uk>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef WITH_NS_SVG
+#ifndef AMIGA_IFF_DR2D_H
+#define AMIGA_IFF_DR2D_H
+#include <proto/iffparse.h>
+#include <datatypes/pictureclass.h>
+#include <stdbool.h>
+#ifndef AMIGA_DR2D_STANDALONE
+#include "content/content.h"
+#endif
+
+#define ID_DR2D MAKE_ID('D','R','2','D')
+#define ID_DRHD MAKE_ID('D','R','H','D')
+#define ID_ATTR MAKE_ID('A','T','T','R')
+#define ID_CPLY MAKE_ID('C','P','L','Y')
+#define ID_OPLY MAKE_ID('O','P','L','Y')
+#define ID_STXT MAKE_ID('S','T','X','T')
+#define ID_DASH MAKE_ID('D','A','S','H')
+//#define ID_CMAP MAKE_ID('C','M','A','P') in dt/pictureclass
+//#define ID_NAME MAKE_ID('N','A','M','E') in dt/datatypes
+#define ID_ANNO MAKE_ID('A','N','N','O')
+#define ID_FONS MAKE_ID('F','O','N','S')
+
+struct drhd_struct {
+ float XLeft, YTop, XRight, YBot;
+};
+
+struct poly_struct {
+ USHORT NumPoints;
+// float PolyPoints[]; // 2*numpoints
+};
+
+#define INDICATOR 0xFFFFFFFF
+#define IND_SPLINE 0x00000001
+#define IND_MOVETO 0x00000002
+#define IND_CURVE 0x00000001
+
+struct fons_struct {
+ UBYTE FontID; /* ID the font is referenced by */
+ UBYTE Pad1; /* Always 0 */
+ UBYTE Proportional; /* Is it proportional? */
+ UBYTE Serif; /* does it have serifs? */
+};
+
+struct stxt_struct {
+ UBYTE Pad0; /* Always 0 (for future expansion) */
+ UBYTE WhichFont; /* Which font to use */
+ float CharW, CharH, /* W/H of an individual char */
+ BaseX, BaseY, /* Start of baseline */
+ Rotation; /* Angle of text (in degrees) */
+ uint16 NumChars;
+ //char TextChars[NumChars];
+};
+
+/* Various fill types */
+#define FT_NONE 0 /* No fill */
+#define FT_COLOR 1 /* Fill with color from palette */
+#define FT_OBJECTS 2 /* Fill with tiled objects */
+
+struct attr_struct {
+ UBYTE FillType; /* One of FT_*, above */
+ UBYTE JoinType; /* One of JT_*, below */
+ UBYTE DashPattern; /* ID of edge dash pattern */
+ UBYTE ArrowHead; /* ID of arrowhead to use */
+ USHORT FillValue; /* Color or object with which to fill */
+ USHORT EdgeValue; /* Edge color index */
+ USHORT WhichLayer; /* ID of layer it's in */
+ float EdgeThick; /* Line width */
+};
+
+/* Join types */
+#define JT_NONE 0 /* Don't do line joins */
+#define JT_MITER 1 /* Mitered join */
+#define JT_BEVEL 2 /* Beveled join */
+#define JT_ROUND 3 /* Round join */
+
+struct dash_struct {
+ USHORT DashID; /* ID of the dash pattern */
+ USHORT NumDashes; /* Should always be even */
+// IEEE Dashes[NumDashes]; /* On-off pattern */
+};
+
+bool ami_svg_to_dr2d(struct IFFHandle *iffh,char *buffer, uint32 size, char *url);
+#ifndef AMIGA_DR2D_STANDALONE
+bool ami_save_svg(struct content *c,char *filename);
+#endif
+#endif // AMIGA_IFF_DR2D_H
+#endif // WITH_NS_SVG
diff --git a/amiga/menu.c b/amiga/menu.c
index b25c861ea..b96321372 100755
--- a/amiga/menu.c
+++ b/amiga/menu.c
@@ -43,6 +43,7 @@
#include "amiga/search.h"
#include "amiga/history_local.h"
#include "amiga/bitmap.h"
+#include "amiga/iff_dr2d.h"
#include "amiga/clipboard.h"
#include "content/fetch.h"
@@ -526,9 +527,18 @@ void ami_menupick(ULONG code,struct gui_window_2 *gwin,struct MenuItem *item)
strlcpy(&fname,savereq->fr_Drawer,1024);
AddPart(fname,savereq->fr_File,1024);
ami_update_pointer(gwin->win,GUI_POINTER_WAIT);
- gwin->bw->current_content->bitmap->url = gwin->bw->current_content->url;
- gwin->bw->current_content->bitmap->title = gwin->bw->current_content->title;
- bitmap_save(gwin->bw->current_content->bitmap,fname,0);
+ if(gwin->bw->current_content->bitmap)
+ {
+ gwin->bw->current_content->bitmap->url = gwin->bw->current_content->url;
+ gwin->bw->current_content->bitmap->title = gwin->bw->current_content->title;
+ bitmap_save(gwin->bw->current_content->bitmap,fname,0);
+ }
+#ifdef WITH_NS_SVG
+ else if(gwin->bw->current_content->type == CONTENT_SVG)
+ {
+ ami_save_svg(gwin->bw->current_content,fname);
+ }
+#endif
SetComment(fname,gwin->bw->current_content->url);
ami_update_pointer(gwin->win,GUI_POINTER_DEFAULT);
}
@@ -587,6 +597,12 @@ void ami_menupick(ULONG code,struct gui_window_2 *gwin,struct MenuItem *item)
gwin->bw->current_content->bitmap->title = gwin->bw->current_content->title;
ami_easy_clipboard_bitmap(gwin->bw->current_content->bitmap);
}
+#ifdef WITH_NS_SVG
+ else if(gwin->bw->current_content->type == CONTENT_SVG)
+ {
+ ami_easy_clipboard_svg(gwin->bw->current_content);
+ }
+#endif
break;
case 1: // paste