Andraz Tori wrote:

On sob, 2006-05-27 at 15:57 -0400, Joe Stewart wrote:
On Saturday 27 May 2006 03:51 pm, Andraz Tori wrote:
great!

The question that remains is ... wouldn't it be great if we could treat
SVGs as first class citizens, similar to JPG or PNG...

ah, but that's asking for too much :)

This is a base for anyone that wants to run with it:

Attached patch (and files) are very hardcoded, but lets you load an SVG file. Yes, it's done not as a picture, but as a "video" stream, but that's only because I was familiar with that File class so I could do it faster (and eventually if animated svg's were to be used). Lots of work needs to be done to actually finish the patch. Screenshot at:

http://cinelerra.org/~baver/svg/firsttestscreen.png

Test file at:

http://cinelerra.org/~baver/svg/test.svg


Requires librsvg, which in turn requires glib, and gsf, and croco. So dependencies are a little crazy, but like I said, more for something as a base if anyone wants to run with it.

Have fun...

Richard
#include "asset.h"
#include "bcsignals.h"
#include "byteorder.h"
#include "edit.h"
#include "file.h"
#include "filesvg.h"
#include "guicast.h"
#include "interlacemodes.h"
#include "language.h"
#include "mwindow.inc"
#include "quicktime.h"
#include "vframe.h"
#include "videodevice.inc"
#include "cmodel_permutation.h"

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

#include <iostream>

FileSVG::FileSVG(Asset *asset, File *file)
 : FileBase(asset, file)
{
	video_position = 0;
}

FileSVG::~FileSVG()
{
}

void FileSVG::get_parameters(BC_WindowBase *parent_window,
	Asset *asset,
	BC_WindowBase* &format_window,
	int audio_options,
	int video_options)
{
	if(audio_options)
	{
		SVGConfigAudio *window = new SVGConfigAudio(parent_window, asset);
		format_window = window;
		window->create_objects();
		window->run_window();
		delete window;
	}
	else
	if(video_options)
	{
		SVGConfigVideo *window = new SVGConfigVideo(parent_window, asset);
		format_window = window;
		window->create_objects();
		window->run_window();
		delete window;
	}

}

int FileSVG::reset_parameters_derived()
{
	video_position = 0;
	
UNTRACE
	return 0;
}

int FileSVG::open_file(int rd, int wr)
{
TRACE("FileSVG::open_file 10")


	if(wr)
	{
		stream = fopen(asset->path, "w+");
TRACE("FileSVG::open_file 20")
	}
	else
	{
		xmlNodePtr node;
		stream = fopen(asset->path, "r");
		xmlDoc = xmlParseFile(asset->path);
		
		if(stream == NULL || xmlDoc == NULL)
		{
			fprintf(stderr, "Unable to open file: %s\n", asset->path);
			if(xmlDoc != NULL)
				xmlFreeDoc(xmlDoc);
			return 1;
		}
		
		// Use libXML to get width/height info
		node = xmlDocGetRootElement(xmlDoc);
		
		if(node == NULL)
		{
			fprintf(stderr, "Empty document\n");
			xmlFreeDoc(xmlDoc);
			return 1;
		}

		// Check that this is an svg file
		if(xmlStrcmp(node->name, (const xmlChar *) "svg") != 0)
		{
			fprintf(stderr, "Not an svg file: %s\n", asset->path);
			xmlFreeDoc(xmlDoc);
			return 1;
		}

		// Get the parameters
		xmlChar *attr;

		// TODO: this currently assumes width and height are in "pt"'s
		// Width
		attr = xmlGetProp(node, (const xmlChar *) "width");
		if(attr != NULL)
			asset->width = atoi((const char *)attr);
		xmlFree(attr);

		// Height
		attr = xmlGetProp(node, (const xmlChar *) "height");
		if(attr != NULL)
			asset->height = atoi((const char *)attr);
		xmlFree(attr);

		asset->video_data = 1;
		asset->layers = 1;
		asset->frame_rate = 29.97;		// Just default to this for now.
		asset->video_length = 300;		// Just default to ~ 10 s for now
	}

UNTRACE
	return 0;
}

int FileSVG::check_sig(Asset *asset)
{
	xmlDocPtr doc;
	xmlNodePtr rootNode;
	
	doc = xmlParseFile(asset->path);
	
	if(doc == NULL)
		return 0;		// Unable to parse file; not an svg file.
							// TODO: gzip'd SVG files
	
	rootNode = xmlDocGetRootElement(doc);
	
	if(rootNode == NULL)
	{
		// Empty document
		xmlFreeDoc(doc);
		return 0;
	}
	
	if(xmlStrcmp(rootNode->name, (const xmlChar *) "svg") != 0)
	{
		// XML file, but not an svg file
		xmlFreeDoc(doc);
		return 0;
	}

	return 1;
}

int FileSVG::close_file_derived()
{
	if(stream) fclose(stream);

	handle = 0;
	stream = 0;

	return 0;
}

int64_t FileSVG::get_video_position()
{
	return video_position;
}

int FileSVG::set_video_position(int64_t x)
{
	video_position = x;
	return 0;
}

int FileSVG::write_frames(VFrame ***frames, int len)
{
	return 0;
}

int FileSVG::read_compressed_frame(VFrame *buffer)
{
	return 0;
}

int FileSVG::write_compressed_frame(VFrame *buffer)
{
	return 0;
}

int64_t FileSVG::compressed_frame_size()
{
	return 0;
}

int FileSVG::read_frame(VFrame *frame)
{
	unsigned char **row_pointers = frame->get_rows();
	GError *error = NULL;
	GdkPixbuf *pixbuf = rsvg_pixbuf_from_file(asset->path, &error);

	if(error)
	{
		fprintf(stderr, "Error creating pixbuf: %s\n", error->message);
		return 1;
	}

	if(pixbuf == NULL)
	{
		fprintf(stderr, "Error creating pixbuf: Unknown\n");
		return 1;
	}
	
/*	int frame_size = gdk_pixbuf_get_bits_per_sample(pixbuf) * 
							gdk_pixbuf_get_n_channels(pixbuf) *
							asset->width *
							asset->height;
*/	
	printf("Bits per sample: %d Channels per sample: %d\n", 
				gdk_pixbuf_get_bits_per_sample(pixbuf),
				gdk_pixbuf_get_n_channels(pixbuf));
	unsigned char *data = gdk_pixbuf_get_pixels(pixbuf);
	unsigned char **temp_pointers = new unsigned char*[asset->height];
	int row_width = gdk_pixbuf_get_rowstride(pixbuf);
	
	for(int i = 0; i < asset->height; i++)
		temp_pointers[i] = data + row_width * i;

	cmodel_transfer(row_pointers,
		temp_pointers,
		row_pointers[0],
		row_pointers[1],
		row_pointers[2],
		temp_pointers[0],
		temp_pointers[1],
		temp_pointers[2],
		0,
		0,
		asset->width,
		asset->height,
		0,
		0,
		asset->width,
		asset->height,
		BC_RGBA8888,
		frame->get_color_model(),
		0,
		asset->width,
		asset->width);
	
	delete[] temp_pointers;

	if(error)
		free(error);
	return 0;	
}

int FileSVG::colormodel_supported(int colormodel)
{
	return colormodel;
}

int FileSVG::can_copy_from(Edit *edit, int64_t position)
{
	if(edit->asset->format == FILE_SVG)
		return 1;

	return 0;
}

int FileSVG::get_best_colormodel(Asset *asset, int driver)
{
	return BC_RGB888;
}













SVGConfigAudio::SVGConfigAudio(BC_WindowBase *parent_window, Asset *asset)
 : BC_Window(PROGRAM_NAME ": Audio Compression",
	parent_window->get_abs_cursor_x(1),
	parent_window->get_abs_cursor_y(1),
	350,
	250)
{
	this->parent_window = parent_window;
	this->asset = asset;
}

SVGConfigAudio::~SVGConfigAudio()
{

}

int SVGConfigAudio::create_objects()
{
	add_tool(new BC_Title(10, 10, _("There are no audio options for this format")));
	add_subwindow(new BC_OKButton(this));
	return 0;
}

int SVGConfigAudio::close_event()
{
	set_done(0);
	return 1;
}






SVGConfigVideo::SVGConfigVideo(BC_WindowBase *parent_window, Asset *asset)
 : BC_Window(PROGRAM_NAME ": Video Compression",
	parent_window->get_abs_cursor_x(1),
	parent_window->get_abs_cursor_y(1),
	350,
	250)
{
	this->parent_window = parent_window;
	this->asset = asset;
}

SVGConfigVideo::~SVGConfigVideo()
{

}

int SVGConfigVideo::create_objects()
{
	add_tool(new BC_Title(10, 10, _("There are no video options for this format")));
	add_subwindow(new BC_OKButton(this));
	return 0;
}

int SVGConfigVideo::close_event()
{
	set_done(0);
	return 1;
}
#ifndef FILESVG_H
#define FILESVG_H

#include <librsvg/rsvg.h>
#include <libxml/parser.h>
#include <gdk-pixbuf/gdk-pixbuf.h>

#include "../config.h"
#include "filebase.h"
#include "file.inc"

class FileSVG : public FileBase
{
public:
	FileSVG(Asset *asset, File *file);
	~FileSVG();

	static void get_parameters(BC_WindowBase *parent_window,
		Asset *asset,
		BC_WindowBase* &format_window,
		int audio_options,
		int video_options);
	
	int reset_parameters_derived();
	int open_file(int rd, int wr);

	static int check_sig(Asset *asset);
	int close_file_derived();
	
	int64_t get_video_position();
	
	int set_video_position(int64_t x);

	int write_frames(VFrame ***frames, int len);
	
	int read_compressed_frame(VFrame *buffer);
	int write_compressed_frame(VFrame *buffers);
	
	int64_t compressed_frame_size();
	
	int read_frame(VFrame *frame);
	
	int colormodel_supported(int colormodel);
	
	int can_copy_from(Edit *edit, int64_t position);
	
	static int get_best_colormodel(Asset *asset, int driver);
	
private:
	FILE *stream;

	int64_t video_position;
	
	unsigned char *video_buffer;

	RsvgHandle *handle;
	xmlDocPtr xmlDoc;
	
};


class SVGConfigAudio: public BC_Window
{
public:
	SVGConfigAudio(BC_WindowBase *parent_window, Asset *asset);
	~SVGConfigAudio();

	int create_objects();
	int close_event();

private:
	Asset *asset;
	BC_WindowBase *parent_window;
};



class SVGConfigVideo: public BC_Window
{
public:
	SVGConfigVideo(BC_WindowBase *parent_window, Asset *asset);
	~SVGConfigVideo();

	int create_objects();
	int close_event();

private:
	Asset *asset;
	BC_WindowBase *parent_window;
};


#endif
Index: file.C
===================================================================
--- file.C	(revision 802)
+++ file.C	(working copy)
@@ -21,6 +21,7 @@
 #include "fileogg.h"
 #include "filepng.h"
 #include "filesndfile.h"
+#include "filesvg.h"
 #include "filetga.h"
 #include "filethread.h"
 #include "filetiff.h"
@@ -335,6 +336,11 @@
 				fclose(stream);
 				file = new FileDV(this->asset, this);
 			}
+			else if(FileSVG::check_sig(this->asset))
+			{
+				fclose(stream);
+				file = new FileSVG(this->asset, this);
+			}
 			else if(FileSndFile::check_sig(this->asset))
 			{
 // libsndfile
Index: file.inc
===================================================================
--- file.inc	(revision 802)
+++ file.inc	(working copy)
@@ -42,6 +42,7 @@
 #define FILE_YUV		29	// mjpegtools YUV4MPEG (aka YUV4MPEG2)
 #define FILE_VORBIS             31
 #define FILE_RAWDV		32
+#define FILE_SVG					33
 
 // For formats supported by plugins, the format number is the plugin number in the 
 // plugin list ORed with 0x8000.
Index: Makefile.am
===================================================================
--- Makefile.am	(revision 802)
+++ Makefile.am	(working copy)
@@ -95,6 +95,7 @@
 		    file.C \
 		    filecr2.C \
 		    filedv.C \
+			 filesvg.C \
 		    fileogg.C \
 		    fileexr.C \
 		    fileformat.C \
@@ -283,7 +284,12 @@
 INCLUDES = \
 	-I$(top_srcdir)/quicktime \
 	-I$(top_srcdir)/guicast \
-	-I$(top_srcdir)/libmpeg3
+	-I$(top_srcdir)/libmpeg3 \
+	-I/usr/include/libxml2 \
+	-I/usr/include/librsvg-2 \
+	-I/usr/include/glib-2.0 \
+	-I/usr/lib/glib-2.0/include \
+	-I/usr/include/gtk-2.0
 
 AM_CXXFLAGS = \
 	$(LARGEFILE_CFLAGS) \
@@ -291,11 +297,11 @@
 	$(SOUND_CFLAGS) \
 	$(XIPH_CFLAGS) \
 	$(MJPEG_CFLAGS) \
	$(OPENEXR_CFLAGS) \
 	$(LIBDV_CFLAGS) \
 	-DPLUGIN_DIR=\"$(plugindir)\"
 
-AM_LDFLAGS = -export-dynamic
+AM_LDFLAGS = -export-dynamic -lxml2 -lrsvg-2 -lglib-2.0
 
 noinst_HEADERS = aattachmentpoint.h \
 		 aautomation.h \
@@ -390,6 +396,7 @@
 		 file.h \
 		 filecr2.h \
 	    filedv.h \
+		 filesvg.h \
 	    fileogg.h \
 		 fileexr.h \
 		 filejpeg.h \
Index: main.C
===================================================================
--- main.C	(revision 802)
+++ main.C	(working copy)
@@ -13,6 +13,8 @@
 #include "preferences.h"
 #include "renderfarmclient.h"
 
+
+#include <librsvg/rsvg.h>
 #include <locale.h>
 #include <stdlib.h>
 #include <string.h>
@@ -184,9 +186,9 @@
 "certain conditions. There is absolutely no warranty for " PROGRAM_NAME ".\n");
 
 
+	rsvg_init();
 
 
-
 	switch(operation)
 	{
 		case DO_USAGE:
@@ -271,6 +273,8 @@
 		}
 	}
 
+	rsvg_term();
+
 	filenames.remove_all_objects();
 	return 0;
 }

Reply via email to