/** \page WHIPusersGuidePage WHIP! Toolkit Users Guide

Introduction

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.

Toolkit Conventions

There are some basic toolkit conventions:

  1. All toolkit class names and type definitions begin with the identifier WT_...(originally, for WHIP! Toolkit) to prevent name collisions with other applications.
  2. All toolkit definitions and constants begin with the identifier WD_... (originally, for WHIP! Definition)to prevent name collisions.
  3. The most common type definitions are contained in the header file %whipcore.h.
  4. Any application file that uses the toolkit should include the header file whip_toolkit.h.
Setting up to use the WHIP! Toolkit

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.)

  1. Static Libraries

    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:


  2. Dynamic Link Libraries (DLLs)

    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:

Writing WHIP! data

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:

  1. Creating an instance of the WT_File class.
  2. Optionally providing the created WT_File object with a set of application supplied input and output handler routines, called "action" routines.
    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.

  3. Optionally specifying heuristics to the WT_File object to instruct it in what style the WHIP! data should be written.
    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.

  4. Setting the drawing attributes (drawable color, line weight, visibility, and so forth) to the state desired for the next drawable (a geometric primitive such as a line, a triangle, a circle, and so forth) that is about to be recorded to the file.
    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.

  5. Recording "drawables" (geometric primitives) to the file.
    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.
  6. When all drawables have been serialized, the "close" method of the WT_File object is called, after which the WT_File object may be deleted (or allowed to go out of scope.) Validation

    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:

Reading WHIP! Data

The process for reading a WHIP! data file includes these steps:

  1. Creating an instance of the WT_File class.
  2. Optionally providing the created WT_File object with a set of application supplied input handler routines.
    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.
  3. Optionally specifying heuristics to the WT_File object to instruct it how the WHIP! data should be read in.
    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.
  4. Replacing the desired action routines of those toolkit objects that the application cares about.
    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.

  5. Calling the WT_File object's; process_next_object() method repeatedly until the end of the WHIP! data is reached. This method reads the next opcode from the WHIP! data, creates an object instance, materializes the object, and calls the appropriate action routine to process the object.
  6. When all drawables have been materialized and processed, the close method of the WT_File object is called, after which the WT_File object may be deleted.
  7. Validation is the responsibility of each developer.

    Example WHIP! Data Reading Application

    The following program and notes show the basic structure of a WHIP! data reading application: \ex DataReading.cpp Notes:


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.

Writing WHIP! Data Content as Blocks - DEPRECATED

To write WHIP! data content as blocks, open WHIP! data in Block_Write mode and invoke the write_block api after setting the appropriate WT_BlockRef rendition attribute to signal the beginning of a new block.

This first example shows the writing of WHIP! data content as blocks. Assume in this example that the WHIP! data files c:\\test1.dwf and c:\\test2.dwf already exist. Also, suppose that we want to merge those files to WHIP! data files as different blocks in a single WHIP! data file with c:\\test.dwf, the first file, as an embedded font block and the second file as an overlay block. The following fragment of code illustrates how this is done: \ex WriteBlocks.cpp

The following code fragment explains how to write a blocked file containing only redline information: \ex WriteRedline.cpp

Reading through WHIP! Data Content as Blocks - DEPRECATED

To read through WHIP! data content as blocks, open the WHIP! data file in Block_Read mode and loop through all the BlockRefs (contained as part of directory); then, invoke the read_block api passing in BlockRefs one by one.

The second code example attempts to read the WHIP! data contents as blocks using the Block_Read file mode. Assume that c:\\test.dwf already exists and it is a WHIP! data file versioned 0.55. Also assume that c:\\test.dwf has its contents grouped as blocks with a valid block directory towards the end. Then the following code fragment attempts to open the WHIP! data file in Block_Read mode and extracts two blocks in to two different WHIP! data file — c:\\test1.dwf contains the first block and c:\\test2.dwf contains the second block. \ex ReadTwoBlocks.cpp This additional code fragment will output individual blocks into separate WHIP! data files, given an input WHIP! data file which has its contents organized in individual blocks: \ex OutputBlocks.cpp

Opening WHIP! Data in Block_Append Mode - DEPRECATED

To append overlay blocks to existing WHIP! data, open the WHIP! data in Block_Append mode and invoke the write_block api after setting the appropriate WT_BlockRef rendition attribute to signal the beginning of the new overlay block.

The third fragment of code, following, best illustrates the usage of opening WHIP! data in Block_Append mode. The new information is appended to existing WHIP! data by opening the WT_File object in Block_Append. Assuming that c:\\test1.dwf and c:\\test2.dwf already exist and are valid WHIP! data files and version == 0.55, the following code attempts to append the contents of c:\\test2.dwf to c:\\test1.dwf as a new overlay block. \ex AppendBlocks.cpp

The Directory Opcode & Blocks - DEPRECATED

Directory information is written automatically by the WHIP! Toolkit for version 0.55 data. As the WT_BlockRef rendition attribute changes, BlockRefs are serialized in WHIP! data and are automatically accumulated in the toolkit as part of the m_directory member variable of the WT_File toolkit object. Towards the end, when the WHIP! data closes, directory information is serialized with proper file offset and block size information for all BlockRefs.





*/