/** \page WHIPusersGuidePage WHIP! Toolkit Users Guide
What is WHIP! data? WHIP! data is the new name given to classic DWF (Design Web Format) files of version 0.55 and earlier. WHIP! data was developed because widely accepted 2D vector file standards did not address the needs of Internet aware applications. In addition, commercial formats were too closely tied to specific proprietary data structures to support the exchange of illustrations among systems.
WHIP! data is a format for the standardized description of 2D, vector-based drawings and illustrations, intended for encapsulation within a DWF package file. WHIP! data files of version 6.0 and greater are not intended to be used as stand-alone files, but rather a data channel within a DWF package file. The DWF 6 format is described in detail in the DWF Specification document accompanying this distribution. See also the DWF Toolkit document.
The WHIP! toolkit is a set of C++ classes that accept drawing calls from an application and convert, "serialize," them into a WHIP! data stream. The toolkit also performs the inverse operation of reading a WHIP! data stream and converting, "materializing," it back into a set of objects suitable for hooking up to drawing calls in a rendering application. WHIP! data is described in detail in the WHIP! Data Specification document accompanying this distribution.
By abstraction, the toolkit is not dependent upon any particular operating system or graphics API and instead requires the application to supply low-level "glue" code for input/output functionality and graphics handling.
This guide does not fully describe all of the classes and functions of the WHIP! Toolkit. Instead, this is intended only to be a basic orientation and overview of the toolkit.
There are some basic toolkit conventions:
The WHIP! toolkit is distributed in source code form. You have to build the libraries yourself. The two primary usage scenarios are static libraries and dynamic link libraries (DLLs). (Note, we primarily use static libraries in-house to minimize the deployment footprint of products using the toolkit, and to avoid DLL conflicts.)
For VC7, open the whiptool.sln solution file. For VC6, open the whiptool_vc6.dsw workspace. Build the configuration you desire. Several different configuration types have been provided for you in VC7, such as a full blown read/write library, a static runtime or a DLL runtime, or a reader-only library. Only full-blown read/write library configurations have been provided in VC6.
You can control "how much" goes into the WHIP! library through the CODE_NOT_WANTED preprocessor macro. You can "turn off" the writing code so that it's not built into the library. Note, the toolkit has not been instrumented to remove reading code. See %whipcore.h for the exact values, but as an example, if you set CODE_NOT_WANTED=0x20000000 in your configuration, the WHIP! output code would not be built into the library.
Regardless of the configuration you choose, there are some things you need to setup in your application project in order to link to the WHIP! toolkit:
For VC7 and VC6, the whiptool.sln and whiptool_vc6.sln solution/workspace (respectively) also contain configuratinos / projects for building the WHIP! toolkit as a DLL. Build the configuration you desire. Only debug and release configurations have been created in the solution and workspace. These are full-blown read/write configurations.
You can control "how much" goes into the WHIP! library through the CODE_NOT_WANTED preprocessor macro. You can "turn off" the writing code so that it's not built into the library. Note, the toolkit has not been instrumented to remove reading code. See %whipcore.h for the exact values, but as an example, if you set CODE_NOT_WANTED=0x20000000 in your configuration, the WHIP! output code would not be built into the library.
Regardless of the configuration you choose, there are some things you need to setup in your application project in order to link to the WHIP! toolkit:
Of the many classes and methods in the WHIP! Toolkit, you only need to understand a small set in order to generate WHIP! data. For simplicity the toolkit is designed such that almost every option and setting has a usable default value.
The process for writing a WHIP! data includes these steps:
If no action routines are supplied by the application, the WT_File object uses a default set of C++ standard file input/output routines (fopen, fwrite, fclose, and so forth). An need for areplacing these I/O functions would be when an application seeks input from a stream (i.e. an IStream from an Internet session) rather than from a file.The phrase "action routine" is defined as any application replaceable toolkit function, but more typically refers to those routines which perform file I/O and object/drawable/attribute processing. Every action routine has a default action, a procedure, that is inside the toolkit. An application can override this default action by passing the toolkit a pointer to an application-specific procedure that should be called instead.
Example heuristics that can be specified include: whether the toolkit should perform data compression of the WHIP! data, whether the toolkit should output a readable ASCII WHIP! data or more compact binary WHIP! data, or whether the toolkit should transform the vertices of objects before recording them to the WHIP! data.If no heuristics are specified, a default set of heuristics is used. These defaults are documented individually under each opcode in the WHIP! Specification document included with this distribution.
The state of these drawing attributes is contained in the grouping class WT_Rendition. The WT_File object contains two instances of this WT_Rendition class: one instance that holds the desired attribute state for the next drawable, and one instance for the actual state of the attributes as has been previously written to the file. When the WT_File object is initially created, both the desired rendition and the actual rendition hold the default values for each attribute.The application using the toolkit only modifies the attribute settings contained in the desired rendition. When a drawable is written to the file, the toolkit automatically updates the actual rendition, as well as the file contents, with only those attributes that have changed and those that the drawable cares about. For example, triangles don't care about the "marker size" attribute. The overall effect is to minimize the WHIP! data size by only storing attribute changes that are absolutely necessary.
Generally, WHIP! data writers interact only with the desired rendition, whereas WHIP! data readers interact only with the actual rendition.
To do this an application tessellates the objects in its own private database and converts them into geometric primitives that the toolkit understands. The application does this by creating instances of toolkit drawables (see \ref groupDrawable "Drawable objects"), such as the WT_Polyline, WT_Polymarker, and the WT_Polytriangle classes. Each of these objects has its own "serialize" method which records any needed attributes and the drawable itself into the WHIP! data. The process of setting the desired attribute state and of serializing drawables repeats for each geometric primitive that the application wishes to record.
The WHIP! Toolkit does not validate return values from the underlying code operations. It is the responsibly of each developer to perform all necessary validation for their application.
A Simple Example of a WHIP! Data Writing Application
To demonstrate the simplicity of using the toolkit, the following program and notes are included on storing a single line into WHIP! data: \ex SingleLine.cpp Notes:
FILE *my_whip_file_pointer=NULL;
my_whip_file_pointer = (FILE*)_wfopen(myfile.filename(),
myfile.set_stream_user_data(my_whip_file_pointer);
The process for reading a WHIP! data file includes these steps:
If none are supplied by the application, the WT_File object uses a default set of C++ standard file input routines (fopen, fread, fclose, and so forth). An example of the application replacing these I/O functions occurs when the application wants to get input from the Internet rather than from a file.
For example, an heuristic that could be specified includes whether the toolkit should transform the vertices of objects as they are read from the WHIP! data. If no heuristics are specified, a default set of heuristics is used.
Each object in the toolkit (either a drawable object or an attribute object) has a materialize method and a process method. Normally when WHIP! data is read, each object in the file is first materialized (parsed) and then its process method is called. The default "process" action for attribute objects is to update their value in the WT_File object's current rendition. The default process action for drawables is to do nothing.Normally an application using the toolkit does not change the "process" action routines for attribute objects, but specifies process routines for those drawable objects it cares about. When the toolkit reads, decodes, materializes, and processes a drawable, the application's action routine is called with the object at which time the application could convert and store the drawable into its own private database — such as a display list.
Example WHIP! Data Reading Application
The following program and notes show the basic structure of a WHIP! data reading application: \ex DataReading.cpp Notes:
FILE *my_whip_file_pointer=NULL;
my_whip_file_pointer = (FILE*)_wfopen(myfile.filename(),
myfile.set_stream_user_data(my_whip_file_pointer);
NOTE, THE FOLLOWING BLOCKREF FUNTIONALITY HAS BEEN DEPRECATED IN VERSION 6.0 AND IS MENTIONED HERE ONLY FOR LEGACY COMPATABILITY. %WT_File & Blocks - DEPRECATED The WT_File WHIP! Toolkit class for writing and reading WHIP! data provides three additional modes for opening WHIP! data with version 0.55. Version 0.50 or lesser toolkit releases were originally supporting reading and writing WHIP! data content as opcodes. Version 0.55 supports reading and writing WHIP! data contents not only as opcodes but also as blocks. Basically, a group of opcodes represents a block. There are 14 different types of blocks that are possible in WHIP! data. For more detailed information on blocks, see the WHIP! Specification's description of the BlockRef opcode (implemented via WT_BlockRef). Each block will be preceded by a BlockRef which holds some meta-data pertaining to the kind of block it represents or references. The following 3 fragments of code illustrate the block mode of writing, reading, and appending WHIP! data contents.
|