SVF v2.0 Write API





About SVF Design Criteria Specification SVF XML API SVF Products

Table of Contents


Project Files

file contents use with C++ use with C
svf_outb.cpp output binary SVF * *
svf_outc.cpp C API wrapper around C++ API *
svf_outg.cpp general SVF support * *
svf_outx.cpp output XML SVF * *
svfout.hpp C++ API definition * *
svfout.h C API definition *
svfcom.h command and enum definitions * *

To use the C++ API, include svfout.hpp. To use the C API, include svfout.h.

If you're compiling on a machine with big-endian architecture (such as a Mac using a 680x0 chip, a Sun, etc.), you should define BIGENDIAN for svfout.cpp. If your machine is little-endian (such as a Pentium), you should define LITTLEENDIAN.

By default, strings passed to the C and C++ APIs are UTF-8 encoded Unicode (see strings for more information), thus simple character arrays that just consist of lower ASCII are valid parameters. If you wish to specify all strings as arrays of 16-bit shorts, define SVF_UTF16 for all the SVF project files and all files which include the SVF header files.


Simple Example

The following C++ code creates an SVF file named "myfile.svf" and writes a single line from (10,20) to (200,150).

	#include "svfout.hpp"

	cFileOutput file;
	if (!file.Open("myfile.svf", FALSE))
		return;

	cSVFWrite *write = cSVFWrite::CreateBinaryOutput(&file);
	write->HandleStart();
	write->HandleMoveToI(10,20);
	write->HandleLineToI(200,150);
	write->HandleEnd();
	delete write;

The following C example does the same thing. The C API hides the use of cFileOutput and HandleStart but at the expense of not being able to do generic output or reuse the SVF class object.

	#include "svfout.h"

	sSVFObject *svf = SVFOpen("myfile.svf");
	if (svf == NULL)
		return;
	SVFOutputMoveTo(svf,10,20);
	SVFOutputLineTo(svf,200,150);
	SVFClose(svf);

To output XML from C++, pass TRUE to cFileOutput::Open and call cSVFWrite::CreateXMLOutput. To output XML from C, call SVFOpenXML instead of SVFOpen.

Note that these examples are based on default values for extents, color, layer, etc. See the defaults table for more specifics. The most important default to override is the extents of the image. This describes the minimum and maximum coordinate values contained in the SVF file. If the SVF image contains a line from (0,0) to (1000,1000), the extents should be at least that big.

	write->HandleStart();
	write->HandleExtentsI(0,0, 1000,1000);
	write->HandleMoveToI(0,0);
	write->HandleLineToI(1000,1000);
	write->HandleEnd();

Upgrading from the 1.1 API

The 1.1 API was only available in C. With one change, code written to the old API should continue to work as is. Previously SVFOpen() returned a FILE* but now it returns an sSVFObject*. Code that looked like the following...

	FILE *fp = SVFOpen("myfile.svf");
	if (fp == NULL)
		return;
	SVFOutputMoveTo(fp,10,20);
	SVFOutputLineTo(fp,200,150);
	SVFClose(fp);

...will work with the new API simply by changing FILE to sSVFObject as in the following example:

	sSVFObject *fp = SVFOpen("myfile.svf");
	if (fp == NULL)
		return;
	SVFOutputMoveTo(fp,10,20);
	SVFOutputLineTo(fp,200,150);
	SVFClose(fp);

General Information

Strings

SVF supports the Unicode character set which allows for most characters from most languages in a platform independent manner (see strings in the SVF specification for more information).

The C/C++ API allows the programmer to pass strings using either the UTF-8 or UTF-16 encoding of Unicode. By default, strings are defined as char* and interpreted as UTF-8. This allows you to pass lower ASCII characters without modification yet any Unicode character can still be passed. If you wish to use 2 byte characters, define SVF_UTF16 for your project. Then strings are defined as unsigned short* and interpreted as UTF-16. This allows you to pass 2 byte Unicode characters to the API yet it still allows Unicode values that can't fit in 2 bytes. Note that all strings passed to the API must be null terminated.

To allow the programmer to work with the UTF-8 and UTF-16 encodings of Unicode with minimal effort, several API functions are provided for converting between various encodings. UCS-4 is the 4 byte version of Unicode and can be stored in a long in C. UCS-2 is the 2 byte version of Unicode and can be stored in a short in C. cGenericOutput::UCS4toUTF8 converts a UCS-2 or UCS-4 character into UTF-8. cGenericOutput::UTF16toUCS4 converts a UTF-16 string into UCS-4. cGenericOutput::IsValidUTF8 can be used to make sure a string is valid UTF-8.

	// default string method - strings are UTF-8
	write->HandleName("This is a normal ASCII string.");

	// build up a UTF-8 string out of Unicode characters
	char utf8[20];
	int len = cGenericOutput::UCS4toUTF8(0xa9, utf8);	// copyright symbol
	len += cGenericOutput::UCS4toUTF8(0x2264, &utf8[len]);	// <= math symbol
	utf8[len] = 0;
	write->HandleTextI(0,utf8);

In the following example, SVF_UTF16 is defined for the project. In C, L can be used as a string prefix to indicate that characters in the string are 2 byte values.

	// all strings are UTF-16
	write->HandleName(L"This is a normal Unicode string.");

	unsigned short utf16[] = { 0xa9, 0x2264, 0 };
	write->HandleTextI(0,utf16);

Precision

Most commands can store their parameters in 1, 2, 4 or 8 bytes of precision as appropriate to make the file more compact. Coordinates and distances can store their values as 1, 2 or 4 byte integers or 8 byte floating point values. These functions use a postfix of I for integers and D for double floating point values (e.g. HandlePointI and HandlePointD). Generally the integer functions can automatically choose the minimum precision necessary for storage with the exception of angles and polylines. For these functions you can pass the desired precision, which defaults to 2 byte integers.

	// automatically writes 1 byte integers
	write->HandlePointI(100,100);
	// automatically writes 2 byte integers
	write->HandlePointI(1000,1000);
	// automatically writes 4 byte integers
	write->HandlePointI(100000,100000);
	// writes 8 byte floating point
	write->HandlePointD(3.14,1.414);

	// writes 2 byte integers
	write->HandleArcI(7000, 0.707, 3.142);
	// writes 4 byte integers
	write->HandleArcI(7000, 0.707, 3.142, 4);

	// write a 2 point polyline using 2 byte integers
	write->HandlePolylineStart(2);
	write->HandlePolyPointI(2000,2200);
	write->HandlePolyPointI(3000,3200);
	// write a 2 point polyline using 8 byte floating point
	write->HandlePolylineStart(2,8);
	write->HandlePolyPointD(4.23,3.21);
	write->HandlePolyPointD(7.13,0.9);

Current State

Graphic objects in SVF are drawn based on the current state of such properties as location, color, layer, etc. These values start with a default value. Then various commands can be used to change these values.

	write->HandleStart();
	write->HandleMoveToI(50,50);
	// circle of radius 10 centered at current point (50,50)
	//	using current color, layer, etc.
	write->HandleCircleI(10);
	// all subsequent objects drawn in red until the next color change
	write->HandleSetColor(SVFC_Red);
	// circle centered at current point (50,50) in red
	write->HandleCircleI(20);
	write->HandleEnd();

Header

SVF is designed so it can be streamed well, that is, the image can be displayed immediately before the whole file has been downloaded. A viewer doesn't need to make a pass through the file first to find information necessary for displaying. Thus the header portion of an SVF file can contain extents, layers, colors, fonts, data types, and other information. This information should be written out before any graphic objects are written.

Colors

By default, SVF references a 256 color table of RGB values by index (see colors for information on this table). The enumerated type eSVFDefaultColors in svfcom.h provides some default color values. Or, if you know the RGB value of the color, you can use cSVFWrite::GetClosestColor to find the closest match in the default color table. Colors are specified as RGB (red/green/blue) values which range from 0, black, to 255, pure color.

	write->HandleSetColor(SVFC_Black);
	write->HandleSetColor(SVFC_White);
	write->HandleSetColor(SVFC_Red);

	svfvalue mycolor = cSVFWrite::GetClosestColor(30,192,115);
	write->HandleSetColor(mycolor);

Alternately, you can build your own color table for optimizing the colors on a system which uses a palette (such as 256 color graphics card). The number passed to HandleBackground, HandleTransparent or HandleSetColor would then be an index into your custom color table.

	write->HandleColorTable(256);
	// create a palette that just consists of shades of green
	for (int i=0; i<256; i++)
		write->HandleColorEntry(0,i,0);
	// have the image use a black (entry 0) background
	write->HandleBackground(0);

A third option is to reference colors by RGB value. Each value ranges from 0 (dark) to 255 (bright).

	write->HandleSetColor(255,0,0);		// pure red
	write->HandleSetColor(50,50,50);	// dark gray
	write->HandleSetColor(255,255,255);	// white

Generic Output

The cSVFWrite derived classes write to a cGenericOutput object which handles architecture specific output and Unicode encoding issues. Derived from cGenericOutput is cFileOutput which can write to a file. If you need to send output somewhere else, a memory buffer, a network socket, etc., derive from cGenericOutput and override the two protected write functions. Then pass this object to one of the create SVF functions in cSVFWrite.

	class cMyOutput : public cGenericOutput
	{
	protected:
		virtual bool write(char v);
		virtual bool write(void *v, int length);
	};