3DPublish/3DPublish_UTF8.cpp

This sample shows how to create a 3D DWF (DWFToolkit::DWFModel, DWFToolkit::DWFPackagePublisher), use the include library (DWFToolkit::DWFIncludeSegment), texture shells (DWFToolkit::DWFTexture), build a navigable object tree (DWFToolkit::DWFSegment), embed fonts (DWFToolkit::DWFEmbeddedFont), add a thumbnail (DWFToolkit::DWFImage), add end-user adjustable items like spotlights (TK_Spot_Light) and cutting planes (TK_Cutting_Plane) and more.

00001 //
00002 //  Copyright (c) 2006 by Autodesk, Inc.
00003 //
00004 //  By using this code, you are agreeing to the terms and conditions of
00005 //  the License Agreement included in the documentation for this code.
00006 //
00007 //  AUTODESK MAKES NO WARRANTIES, EXPRESS OR IMPLIED,
00008 //  AS TO THE CORRECTNESS OF THIS CODE OR ANY DERIVATIVE
00009 //  WORKS WHICH INCORPORATE IT.
00010 //
00011 //  AUTODESK PROVIDES THE CODE ON AN "AS-IS" BASIS
00012 //  AND EXPLICITLY DISCLAIMS ANY LIABILITY, INCLUDING
00013 //  CONSEQUENTIAL AND INCIDENTAL DAMAGES FOR ERRORS,
00014 //  OMISSIONS, AND OTHER PROBLEMS IN THE CODE.
00015 //
00016 //  Use, duplication, or disclosure by the U.S. Government is subject to
00017 //  restrictions set forth in FAR 52.227-19 (Commercial Computer Software
00018 //  Restricted Rights) and DFAR 252.227-7013(c)(1)(ii) (Rights in Technical
00019 //  Data and Computer Software), as applicable.
00020 //
00021 
00022 // SimpleEnumReader.cpp : Defines the entry point for the console application.
00023 //
00024 
00025 #include "stdafx.h"
00026 
00027 #include "dwf/package/ContentManager.h"
00028 #include "dwf/package/EPlotSection.h"
00029 #include "dwf/publisher/model/Model.h"
00030 #include "dwf/publisher/impl/DWF6PackagePublisher.h"
00031 #include "dwf/publisher/impl/DWFXPackagePublisher.h"
00032 
00033 using namespace std;
00034 using namespace DWFCore;
00035 using namespace DWFToolkit;
00036 
00037 void setResourceStreamFromFile( DWFResource* pResource, const DWFString& zFilename )
00038     throw( DWFException )
00039 {
00040     //
00041     // most importantly - bind a stream to the resource
00042     // in this case, we have a file on disk so we open the
00043     // file with a streaming descriptor.  we will also
00044     // create everything on the heap since the package writer
00045     // will not use the stream immediately, he will need to own
00046     // these resources.
00047     //
00048     DWFFile oResourceFilename( zFilename );
00049     DWFStreamFileDescriptor* pResourceFile = DWFCORE_ALLOC_OBJECT( DWFStreamFileDescriptor(oResourceFilename, L"rb") );
00050 
00051     if (pResourceFile == NULL)
00052     {
00053         DWFCORE_FREE_OBJECT( pResource );
00054 
00055         _DWFCORE_THROW( DWFMemoryException, L"Failed to allocate file descriptor" );
00056     }
00057 
00058     DWFFileInputStream* pResourceFilestream = DWFCORE_ALLOC_OBJECT( DWFFileInputStream );
00059 
00060     if (pResourceFilestream == NULL)
00061     {
00062         DWFCORE_FREE_OBJECT( pResource );
00063         DWFCORE_FREE_OBJECT( pResourceFile );
00064 
00065         _DWFCORE_THROW( DWFMemoryException, L"Failed to allocate file stream" );
00066     }
00067 
00068     //
00069     // open the file and bind it to the stream
00070     //
00071     pResourceFile->open();
00072     pResourceFilestream->attach( pResourceFile, true );
00073 
00074     //
00075     // hand the stream off to the resource
00076     // NOTE: since we don't already know the filesize (in the application space - of course we can look on disk...)
00077     // leave the second parameter (nBytes) default as zero, this will tell the package writer
00078     // to use the number of bytes it processed through the stream as the size attribute in the descriptor.
00079     //
00080     pResource->setInputStream( pResourceFilestream );
00081 }
00082 
00083 //
00084 //
00085 // Some of this sample code is taken from the HOOPS/Stream toolkit (v.10.00) samples
00086 //
00087 //
00088 
00089 #define  USE_NEW_CONTENT_DEFINITION_FOR_3D_PUBLISH
00090 
00091 void CreateSphere( float *center, 
00092                    float radius, 
00093                    int numsides, 
00094                    int *pcount_out, 
00095                    float **points_out, 
00096                    int *flistlen_out, 
00097                    int **faces_out );
00098 
00099 void do_model( DWFModel& rModel,
00100                bool bIncludeNormals );
00101 
00102 void do_publishProxyGraph( DWFPackagePublisher* pPackagePublisher );
00103 
00104 #ifdef   TEST_MULTIPLE_DECAL_TEXTURES
00105 // create images
00106 static unsigned const width = 256;
00107 static unsigned const height = 256;
00108 static unsigned char pixel_data1[height][width][4];
00109 static unsigned char pixel_data2[height][width][4];
00110 static char mybuffer[4096];
00111 
00112 void gen_top_img(unsigned const w,
00113                                  unsigned const h,
00114                                  unsigned char * const pixel_data)
00115 {
00116         unsigned row, col;
00117 
00118         for(row = 0; row < h; ++row){
00119                 for(col = 0; col < w; ++col){
00120                         if(row / 8 % 2){
00121                                 pixel_data[4*row*w+4*col+0] = 0xff;    // r
00122                                 pixel_data[4*row*w+4*col+1] = 0xff;    // g
00123                                 pixel_data[4*row*w+4*col+2] = 0xff;    // b
00124                                 pixel_data[4*row*w+4*col+3] = 0x30;    // alpha, 50% transparence
00125                         } else {
00126                                 pixel_data[4*row*w+4*col+0] = 0x00;    // r
00127                                 pixel_data[4*row*w+4*col+1] = 0x00;    // g
00128                                 pixel_data[4*row*w+4*col+2] = 0x00;    // b
00129                                 pixel_data[4*row*w+4*col+3] = 0x00;    // alpha, 100% transparence
00130                         }
00131                 }
00132         }
00133 }
00134 
00135 void gen_bot_img(unsigned const w,
00136                                  unsigned const h,
00137                                  unsigned char * const pixel_data)
00138 {
00139         unsigned row, col;
00140 
00141         for(row = 0; row < h; ++row){
00142                 for(col = 0; col < w; ++col){
00143                         if(col / 8 % 2){
00144                                 pixel_data[4*row*w+4*col+0] = 0xff;    // r
00145                                 pixel_data[4*row*w+4*col+1] = 0xff;    // g
00146                                 pixel_data[4*row*w+4*col+2] = 0xff;    // b
00147                                 pixel_data[4*row*w+4*col+3] = 0x30;    // alpha, 50% transparence
00148                         } else {
00149                                 pixel_data[4*row*w+4*col+0] = 0x00;    // r
00150                                 pixel_data[4*row*w+4*col+1] = 0x00;    // g
00151                                 pixel_data[4*row*w+4*col+2] = 0x00;    // b
00152                                 pixel_data[4*row*w+4*col+3] = 0x00;    // alpha, 100% transparence
00153                         }
00154                 }
00155         }
00156 }
00157 #endif
00158 
00159 int main(int argc, char* argv[])
00160 {
00161 
00162     if (argc < 2)
00163     {
00164         wcout << L"Usage:" << argv[0] << L" [options] OUTPUTFILENAME" << endl;
00165         wcout << "Try " << argv[0] << "--help for more information" << endl;
00166         return ( 0 );
00167     }
00168 
00169     if (DWFCORE_COMPARE_ASCII_STRINGS_NO_CASE( argv[1], "--help" ) == 0 ||
00170         DWFCORE_COMPARE_ASCII_STRINGS_NO_CASE( argv[1], "-h" ) == 0)
00171     {
00172         wcout << "Usage:" << argv[0] << L" [options] file.dwf" << endl << endl;
00173         wcout << "  --package-type=dwfx\t specifies that a dwfx package should be created" << endl;
00174         return 0;
00175     }
00176 
00177     char* zFileName = NULL;
00178     bool bCreateDWF6Package = true;
00179 
00180     for (int i = 1; i < argc; i++)
00181     {
00182         if (argv[i][0] != L'-')
00183         {
00184             zFileName = argv[i];
00185         }
00186         else if (DWFCORE_COMPARE_ASCII_STRINGS_NO_CASE(argv[i] , "--package-type=dwfx") == 0)
00187         {
00188             bCreateDWF6Package = false;
00189         }
00190     }
00191 
00192     if (zFileName == NULL)
00193     {
00194         wcout << "Missing output filename" << endl;
00195         wcout << "Try " << argv[0] << "--help for more information" << endl;
00196         return 0;
00197     }
00198 
00199     try
00200     {
00201 
00202 
00203         //
00204         // start with a new model
00205         //
00206         DWFModel oModel( L"3D Publish Model Test", L"3DPublish.cpp" );
00207 
00208 #ifdef  USE_NEW_CONTENT_DEFINITION_FOR_3D_PUBLISH
00209         //
00210         //  The content is required by the model. The publisher will take care of deleting
00211         //  the content manager and the content.
00212         //
00213         DWFContentManager* pContentManager = DWFCORE_ALLOC_OBJECT( DWFContentManager );
00214         DWFContent* pContent = pContentManager->getContent();
00215 
00216         oModel.open( pContent,
00217                      DWFModel::eHandednessNone,
00218                      DWFUnits::eCentimeters,
00219                      NULL,                                  // transform
00220                      true,                                  // default lights
00221                      false,                                 // published edges
00222                      true,                                  // silhouettes
00223                      0,
00224                      DWFPublisher::ePublishContentDefinition ); 
00225 #else
00226         oModel.open( NULL,
00227                      DWFModel::eHandednessNone,
00228                      DWFUnits::eCentimeters,
00229                      NULL,                                  // transform
00230                      true,                                  // default lights
00231                      false,                                 // published edges
00232                      true,                                  // silhouettes
00233                      0,
00234                      DWFPublisher::ePublishObjectDefinition ); 
00235 #endif
00236 
00237         W3DCamera oDefault;
00238         oDefault.setProjection( W3DCamera::eOrthographic );
00239         oDefault.setPosition( 0.0f, 0.0f, -15.0f );
00240         oDefault.setTarget( 1.0f, 1.4f, -0.1f );
00241         oDefault.setUpVector( 1.0f, 1.0f , 0.1f );
00242         oDefault.setField( 15.0f, 15.0f );
00243 
00244         oModel.createView( "default", oDefault );
00245 
00246         //
00247         // create the graphics, etc.
00248         //
00249         do_model( oModel, true );
00250 
00251         //
00252         // add some properties that apply to the model as a whole
00253         //
00254         oModel.addProperty( DWFCORE_ALLOC_OBJECT(DWFProperty(L"Cutting Plane", L"Hide", L"View Modifier")), true );
00255         oModel.addProperty( DWFCORE_ALLOC_OBJECT(DWFProperty(L"Origin", L"DWFToolkit Sample Applications", L"General")), true );
00256         oModel.addProperty( DWFCORE_ALLOC_OBJECT(DWFProperty(L"Project", L"Bianchi", L"General")), true );
00257 
00258         //
00259         // close the model
00260         //
00261         oModel.close();
00262 
00263         //
00264         //  Create the DWFFile to which the package will be saved, and the publisher to use.
00265         //
00266         DWFFile oDWF( zFileName );
00267         DWFPackagePublisher* pPackagePublisher = NULL;
00268         if (bCreateDWF6Package)
00269         {
00270             pPackagePublisher = DWFCORE_ALLOC_OBJECT( DWF6PackagePublisher( oDWF ) );
00271         }
00272         else
00273         {
00274             pPackagePublisher = DWFCORE_ALLOC_OBJECT( DWFXPackagePublisher( oDWF ) );
00275             
00276             //
00277             //  publishing proxy graph for XPS viewer.
00278             //
00279             do_publishProxyGraph( pPackagePublisher );
00280         }
00281         
00282 
00283         //
00284         // publish the model "into" the publisher.
00285         //
00286         oModel.publish( *pPackagePublisher );
00287 
00288         //
00289         // create the DWF
00290         //
00291         pPackagePublisher->publish();
00292 
00293         DWFCORE_FREE_OBJECT( pPackagePublisher );
00294     }
00295     catch (DWFException& ex)
00296     {
00297         wcout << ex.type() << L": " << ex.message() << endl;
00298         wcout << L"(function) " << ex.function() << endl;
00299         wcout << L"(file) " << ex.file() << endl;
00300         wcout << L"(line) " << ex.line() << endl;
00301     }
00302 
00303         return 0;
00304 }
00305 
00306 
00307 #define countof(x) (int)(sizeof(x)/sizeof(x[0]))
00308 
00309 
00310 class HPoint 
00311 { 
00312 public:
00313     float        x;     
00314     float        y;     
00315     float        z;     
00316     inline void Set(float X,float Y,float Z=0.0) { x=X,y=Y,z=Z; }
00317 
00318 }; 
00319 
00320 const float PI=3.1415926f;
00321 
00322 
00323 void CreateSphere( float *center, 
00324                    float radius, 
00325                    int numsides, 
00326                    int *pcount_out, 
00327                    float **points_out, 
00328                    int *flistlen_out, 
00329                    int **faces_out )
00330 {
00331     int i, j, htile, wtile, pts_cnt, flist_cnt;
00332     float theta, phi, dt, dp, x, y, z;
00333     HPoint *points;
00334     int *faces;
00335 
00336     htile = numsides/2;
00337     wtile = numsides;
00338     pts_cnt = htile*wtile;
00339     points = new HPoint[ pts_cnt ];
00340     // faces need wtile + 1 numbers to specify each sphere end cap
00341     // and 5*numsides numbers for each strip between the end caps.
00342     // There will be numsides/2-1 of these strips.
00343     flist_cnt = (wtile+1)*2 + 5*(htile-1)*wtile;
00344     faces = new int[ flist_cnt ];
00345 
00346     dt = 2.0f * PI / wtile;
00347     dp = 1.0f * PI / (htile+1);
00348     phi = dp;
00349     for( i = 0 ; i < htile ; i++ ) {
00350         theta = 0;
00351         for( j = 0 ; j < wtile ; j++ ) {
00352             x = radius * (float)cos(theta) * (float)sin(phi);
00353             y = radius * (float)cos(phi);
00354             z = radius * (float)sin(theta) * (float)sin(phi);
00355             points[ i*wtile + j ].Set( center[0] + x, center[1] + y, center[2] + z );
00356             theta += dt;
00357         }
00358         phi += dp;
00359     }
00360 
00361     // set the number of points in the end caps of the sphere in the connectivity list
00362     faces[5*(htile-1)*wtile] = wtile;
00363     faces[5*(htile-1)*wtile+wtile+1] = wtile;
00364     for (i = 0; i < (htile-1); i++)
00365     {
00366         for (j = 0; j < wtile; j++)
00367         {
00368             // generate the connectivity list for the side quads of the cylinder
00369             faces[(i*wtile + j)*5] = 4; // number of points in this polygon
00370             faces[(i*wtile + j)*5+1]=i*wtile + j;
00371             faces[(i*wtile + j)*5+2]=i*wtile + (j+1)%wtile; //next point along circle; wrap at numsides
00372             faces[(i*wtile + j)*5+3]=(i+1)*wtile + (j+1)%wtile;  // correcsponding point at top of cylinder
00373             faces[(i*wtile + j)*5+4]=(i+1)*wtile + j; //next point along circle; wrap at numsides
00374         }
00375     }
00376     for (j = 0; j < wtile; j++)
00377     {
00378         // generate the connectivity list for the ends of the cylinder
00379         faces[(htile-1)*wtile*5 + j + 1]= (wtile - j - 1);
00380         faces[(htile-1)*wtile*5 + j + 1 + wtile + 1]= wtile*(htile-1) + j;
00381     }
00382     *pcount_out = pts_cnt;
00383     *points_out = (float *)points;
00384     *flistlen_out = flist_cnt;
00385     *faces_out = (int *)faces;
00386 }
00387 
00388 
00389 void do_model( DWFModel& rModel,
00390                bool bIncludeNormals )
00391 {
00392     //
00393     // 
00394     //
00395     DWFProperty oProperty( L"", L"" );
00396 
00397     HPoint center; center.Set( 0.0, 0.0, 0.0 );
00398 
00399     float radius = 1.0f;
00400     float bbox[6];
00401     float *points, *normals;
00402     int p_count, flist_length, *flist, i;
00403 
00404     //
00405     // the first thing to do is create an include segment
00406     // that defines a collection of graphics that will be
00407     // reused throughout the model
00408     //
00409     DWFIncludeSegment oSphere_include = rModel.openIncludeSegment();
00410 
00411     //
00412     // segments are always first acquired from their aggregating component (i.e. Model or another Segment)
00413     // and then opened.  Include segments must be opened with a name. 
00414     //
00415     oSphere_include.open( "Sphere" );
00416     {
00417         //
00418         // we will define our sphere as a shell
00419         // notice that the handler is returned as a reference
00420         // be sure to obtain it this way; if you try and copy
00421         // it, you will get a compile time error since there
00422         // is no copy constructor defined for these objects
00423         //
00424         TK_Shell& rSphere = oSphere_include.getShellHandler();
00425         {
00426             //
00427             // it's always a good idea to set the bounding volume on your shells.
00428             //
00429             bbox[0] = center.x - radius;
00430             bbox[1] = center.y - radius;
00431             bbox[2] = center.z - radius;
00432             bbox[3] = center.x + radius;
00433             bbox[4] = center.y + radius;
00434             bbox[5] = center.z + radius;
00435             rSphere.SetBounding( bbox );
00436 
00437             //
00438             // Original HOOPS/Stream comment:
00439             // This is where you will go out to your gfx database and get the data defining the shell.
00440             // We're using a simple sphere generator to create a point cloud and some connectivity
00441             //
00442             CreateSphere( (float *)&center, radius, 30, &p_count, &points, &flist_length, &flist );
00443             
00444             //
00445             // set the vertex list for the shell
00446             //
00447             rSphere.SetPoints( p_count, points );
00448 
00449             //
00450             // set the face list for the shell
00451             //
00452             rSphere.SetFaces( flist_length, flist );
00453 
00454                 //
00455                 // HOOPS 3DGS will calculate simple average normals from the faces
00456                 // usually this adequate and saves space if we don't need to store
00457                 // normals data in the file.  Edge normals should always be defined
00458                 // with original data.  Also, normals are quantized by default to save
00459                 // space while preserving visual fidelity.  A sphere is going to be
00460                 // the worst case scenario for this compression mechanism but it is
00461                 // worth adjusting this parameter as much as possible to acheive the
00462                 // best visual results in the smallest file.
00463                 //
00464             if (bIncludeNormals)
00465             {
00466                 normals = new float[ 3 * p_count ];
00467                 for ( i = 0 ; i < p_count * 3 ; i += 3) 
00468                 {
00469                     normals[ i + 0 ] = points[ i + 0 ] - center.x;
00470                     normals[ i + 1 ] = points[ i + 1 ] - center.y;
00471                     normals[ i + 2 ] = points[ i + 2 ] - center.z;
00472                 }
00473              
00474                 rSphere.SetVertexNormals( normals );
00475 
00476                 //
00477                 // NOTE here that the opcode handlers will always
00478                 // copy the data that they are given
00479                 //
00480                 delete [] normals;
00481             }
00482 
00483             //
00484             // clean up
00485             //
00486             //delete [] indices;
00487             delete [] points;
00488             delete [] flist;
00489         }
00490         
00491         //
00492         // once we are completely finished with a handler,
00493         // we must call serialize().  this will write all
00494         // of our graphics into the stream and reset the handler
00495         // for future use
00496         //
00497         rSphere.serialize();
00498 
00499         //
00500         // let's create a property on this segment
00501         //
00502         oProperty.setName( L"Material" );
00503         oProperty.setValue( L"Plastic" );
00504 
00505         //
00506         // add the property to the segment
00507         //
00508         oSphere_include.addProperty( oProperty );
00509 
00510         //
00511         // also add a set of properties 
00512         //
00513         DWFPropertySet* pProperties = DWFCORE_ALLOC_OBJECT( DWFPropertySet );
00514 
00515         oProperty.setName( L"Cost" );
00516         oProperty.setValue( L"$4.44" );
00517         oProperty.setCategory( L"Sphere Properties" );
00518         pProperties->addProperty( &oProperty, false );
00519 
00520         oProperty.setName( L"Vendor" );
00521         oProperty.setValue( L"Foo Ball" );
00522         pProperties->addProperty( &oProperty, false );
00523 
00524         oProperty.setName( L"Manufacturer" );
00525         oProperty.setValue( L"Ball Co." );
00526         pProperties->addProperty( &oProperty, false );
00527 
00528         //
00529         // add the property set to the segment
00530         //
00531         oSphere_include.addPropertyContainer( pProperties );
00532     }
00533 
00534     //
00535     // close the segment - this will serialize everything about the segment
00536     // into the graphics stream. we can now use this segment as a reference
00537     // part in our scene graph
00538     //
00539     oSphere_include.close();
00540 
00541 
00542     //
00543     // it is preferrable to "side-stream" texture images
00544     // in the DWF package rather than embedded them directly
00545     // in the graphics channel
00546     // so let's add our texture images up here
00547     //
00548     //
00549     // first, create the texture resource and add it to the model
00550     // here we load an image from disk...
00551     //
00552     DWFStreamFileDescriptor* pTextureFile = DWFCORE_ALLOC_OBJECT( DWFStreamFileDescriptor("hank.jpg", "rb") );
00553     pTextureFile->open();
00554 
00555     DWFFileInputStream* pTextureStream = DWFCORE_ALLOC_OBJECT( DWFFileInputStream );
00556     pTextureStream->attach( pTextureFile, true );
00557 
00558     DWFTexture* pTexture = DWFCORE_ALLOC_OBJECT( DWFTexture("hank",
00559                                                              DWFMIME::kzMIMEType_JPG,
00560                                                              24, 320, 240) );
00561 
00562     pTexture->attach( pTextureStream, true );
00563     rModel.addResource( pTexture );
00566 
00567     //
00568     // create a simple scene
00569     //
00570     DWFSegment oRootSegment = rModel.openSegment();
00571     
00572     //
00573     // segments don't have to be named - in this case
00574     // we will set up some attributes that will affect
00575     // the entire scene unless overridden in subsegments
00576     //
00577     oRootSegment.open();
00578     {
00579         TK_Color_RGB& rColor = oRootSegment.getColorRGBHandler();
00580         
00581         //
00582         // red lines
00583         //
00584         rColor.SetGeometry( TKO_Geo_Line );
00585         rColor.SetRGB( 1.0f, 0.0f, 0.0f );
00586         rColor.serialize();
00587 
00588         //
00589         // we can reuse the handler 
00590         // green text
00591         //
00592         rColor.SetGeometry( TKO_Geo_Text );
00593         rColor.SetRGB( 0.0f, 0.8f, 0.1f );
00594         rColor.serialize();
00595 
00596         //
00597         // we can reuse the handler 
00598         // blue faces
00599         //
00600         rColor.SetGeometry( TKO_Geo_Face );
00601         rColor.SetRGB( 0.0f, 0.0f, 0.75f );
00602         rColor.serialize();
00603 
00604         //
00605         // a simple set of properties
00606         //
00607         DWFPropertySet* pPartProperties = DWFCORE_ALLOC_OBJECT( DWFPropertySet );
00608 
00609         oProperty.setName( L"Cost" );
00610         oProperty.setValue( L"$23.55" );
00611         oProperty.setCategory( L"Part Properties" );
00612         pPartProperties->addProperty( &oProperty, false );
00613 
00614 
00615         //
00616         // now let's create a segment that will show up in the nav tree
00617         // note that this is built off the root segment not the model
00618         //
00619         DWFSegment oPart1 = oRootSegment.openSegment();
00620 
00621         //
00622         // open with a name, this will show in the nav tree
00623         //
00624         oPart1.open( L"First Part" );
00625         {
00626             //
00627             // add the sphere from our include library
00628             // since the segment that we are including the spehere in
00629             // is already named, it will "become" a part of this segment.
00630             // that is, selecting "First Part" in the tree will highlight the
00631             // sphere and vice-versa - there will be no tree node called "Sphere"
00632             //
00633             oPart1.include( oSphere_include );
00634 
00635             //
00636             // let's draw some lines
00637             // these lines will finish the element named "First Part"
00638             // all of the geometry built into this segment will be
00639             // treated as a single selected part
00640             //
00641             TK_Line& rLine = oPart1.getLineHandler();
00642 
00643             rLine.SetPoints( 0.0f,
00644                              0.0f,
00645                              0.0f,
00646                              center.x + 2.0f*radius,
00647                              center.y + 2.0f*radius,
00648                              center.z + 2.0f*radius );
00649 
00650             rLine.serialize();
00651 
00652             rLine.SetPoints( center.x - 2.0f*radius,
00653                              center.y - 2.0f*radius,
00654                              center.z - 2.0f*radius,
00655                              0.0f,
00656                              0.0f,
00657                              0.0f );
00658 
00659             rLine.serialize();
00660 
00661             oPart1.addPropertyContainer( pPartProperties );
00662             //
00663             // test textures
00664             //
00665             DWFSegment oTexturePart = oPart1.openSegment();
00666             oTexturePart.open( L"Hank Box" );
00667             {
00668                 //
00669                 // make a cube
00670                 //
00671                 float anPoints[24] = {  0.0f, 0.0f, 6.67f,
00672                                         0.0f, 6.67f, 6.67f,
00673                                         6.67f, 6.67f, 6.67f,
00674                                         6.67f, 0.0f, 6.67f,
00675                                         0.0f, 0.0f, 13.34f,
00676                                         0.0f, 6.67f, 13.34f,
00677                                         6.67f, 6.67f, 13.34f,
00678                                         6.67f, 0.0f, 13.34f };
00679 
00680                 int anFaces[30] = { 4, 0, 1, 2, 3,
00681                                     4, 1, 5, 6, 2,
00682                                     4, 5, 4, 7, 6,
00683                                     4, 4, 0, 3, 7,
00684                                     4, 3, 5, 6, 7,
00685                                     4, 1, 0, 4, 5 };
00686 
00687                 TK_Shell& rCube = oTexturePart.getShellHandler();
00688                 rCube.SetPoints( 8, anPoints );
00689                 rCube.SetFaces( 30, anFaces );
00690                 rCube.SetVertexParameters( anPoints );
00691                 rCube.serialize();
00692                   
00693 #ifdef   TEST_MULTIPLE_DECAL_TEXTURES
00694                 // create images
00695                 gen_top_img(width, height, (unsigned char* const)pixel_data1);
00696                 gen_bot_img(width, height, (unsigned char* const)pixel_data2);
00697 
00698                 TK_Image& image1 = oTexturePart.getImageHandler();
00699                 image1.SetName("top_image");
00700                 image1.SetFormat(TKO_Image_RGBA);
00701                 image1.SetSize(width,height);
00702                 image1.SetBytes(sizeof(pixel_data1), (char const*)pixel_data1);
00703                 image1.serialize();
00704 
00705                 TK_Image& image2 = oTexturePart.getImageHandler();
00706                 image2.SetName("bot_image");
00707                 image2.SetFormat(TKO_Image_RGBA);
00708                 image2.SetSize(width,height);
00709                 image2.SetBytes(sizeof(pixel_data2), (char const*)pixel_data2);
00710                 image2.serialize();
00711 
00712                 // Set Visibility for images off, faces on.
00713                 TK_Visibility& vis = oTexturePart.getVisibilityHandler();
00714                 vis.SetGeometry(TKO_Geo_Image | TKO_Geo_Face);
00715                 vis.SetValue(TKO_Geo_Face);
00716                 vis.serialize();
00717 #endif
00718 
00719                 //
00720                 // texture the cube
00721                 //
00722                 TK_Texture& rShellTexture = oTexturePart.getTextureHandler();
00723 
00724                 //
00725                 // this creates a texture from our earlier image
00726                 // NOTE: the image is required to exist already
00727                 //
00728 #ifdef   TEST_MULTIPLE_DECAL_TEXTURES
00729                                 int flags( TKO_Texture_Param_Source | TKO_Texture_Param_Offset | TKO_Texture_Decal );
00730 #else
00731                                 int flags( 0 );
00732 #endif
00733                 rShellTexture.SetFlags( flags );
00734                 rShellTexture.SetImage( "hank" );
00735                 rShellTexture.SetName( "hank texture" );
00736                 rShellTexture.serialize();
00737 
00738 #ifdef   TEST_MULTIPLE_DECAL_TEXTURES
00739                 // add the second and third
00740                 TK_Texture& rShellTexture1 = oTexturePart.getTextureHandler();
00741                 rShellTexture1.SetFlags( TKO_Texture_Param_Source | TKO_Texture_Param_Offset | TKO_Texture_Decal );
00742                 rShellTexture1.SetImage( "top_image" );
00743                 rShellTexture1.SetName( "top_texture" );
00744                 rShellTexture1.serialize();
00745 
00746                 TK_Texture& rShellTexture2 = oTexturePart.getTextureHandler();
00747                 rShellTexture2.SetFlags( TKO_Texture_Param_Source | TKO_Texture_Param_Offset | TKO_Texture_Decal );
00748                 rShellTexture2.SetImage( "bot_image" );
00749                 rShellTexture2.SetName( "bot_texture" );
00750                 rShellTexture2.serialize();
00751 #endif
00752 
00753                 TK_Color& rTextureColor = oTexturePart.getColorHandler();
00754 
00755                 //
00756                 // set the attribute for this DWFSegment such that
00757                 // faces are "colored" with our new (named) texture
00758                 // NOTE: the texture is required to exist already
00759                 //
00760                 rTextureColor.SetGeometry( TKO_Geo_Face );
00761                 rTextureColor.SetChannels( 1 << TKO_Channel_Diffuse );  
00762 
00763 #ifdef   TEST_MULTIPLE_DECAL_TEXTURES
00764                 char diff_text_name[] = { "hank texture, top_texture, bot_texture" };
00765 #else
00766                                 char diff_text_name[] = { "hank texture" };
00767 #endif
00768                 rShellTexture.SetFlags( flags );
00769 
00770                 rTextureColor.SetDiffuseName( diff_text_name );
00771                 rTextureColor.serialize();
00772             }
00773             oTexturePart.close();
00774         }
00775         oPart1.close();
00776 
00777         //
00778         // create another part
00779         //
00780         DWFSegment oPart2 = oRootSegment.openSegment();
00781 
00782         oPart2.open( L"Second Part" );
00783         {
00784             //
00785             // let's first reposition everything in this segment
00786             //
00787             float anTransform[16] = { 1.0f, 0.0f, 0.0f, 0.0f,
00788                                       0.0f, 1.0f, 0.0f, 0.0f,
00789                                       0.0f, 0.0f, 1.0f, 0.0f,
00790                                       2.33f, 0.67f, 0.0f, 1.0f };
00791 
00792             TK_Matrix& rMatrix = oPart2.getModellingMatrixHandler();
00793             rMatrix.SetMatrix( anTransform );
00794             rMatrix.serialize();
00795 
00796             //
00797             // open an unnamed segment
00798             //
00799             DWFSegment oSubpart = oPart2.openSegment();
00800             oSubpart.open();
00801             {
00802                 //
00803                 // add our sphere - this time, the sphere will appear
00804                 // as it's own element in the nav tree.  this is due
00805                 // to the fact that we are referencing the sphere
00806                 // in an unnamed segment.  we could rename this element
00807                 // if we wanted to. regardless, the behavior here is that
00808                 // we are using a named part to build up the higher level
00809                 // element, i.e. "Second Part"
00810                 //
00811                 oSubpart.include( oSphere_include );
00812 
00813                 //
00814                 // note that since we didn't name the segment into which this
00815                 // part was included, we cannot modify the properties on JUST
00816                 // the sphere, since the next named node up the tree is "Second Part"
00817                 // any properties we add would end up there. 
00818                 //
00819             }
00820             oSubpart.close();
00821 
00822             //
00823             // let's add a text box - use it's own segment or else
00824             // we will affect the included sphere - well it's not really
00825             // a text box but rather a polygon with some text in front of it
00826             //
00827             oSubpart = oSubpart.openSegment();
00828             oSubpart.open();
00829             {
00830                 //
00831                 // face
00832                 //
00833                 rColor.SetGeometry( TKO_Geo_Face );
00834                 rColor.SetRGB( 0.11f, 0.88f, 0.44f );
00835                 rColor.serialize();
00836 
00837                 //
00838                 // solid face
00839                 //
00840                 TK_Enumerated& rPatternEnum = oSubpart.getFacePatternHandler();
00841                 rPatternEnum.SetIndex( TKO_Fill_Pattern_Solid );
00842                 rPatternEnum.serialize();
00843 
00849                 //TK_Linear_Pattern& rLinePattern = oSubpart.getEdgePatternHandler();
00850                 //rLinePattern.SetPattern( TKO_Line_Pattern_Solid );
00851                 //rLinePattern.serialize();
00852 
00853                 //
00854                 // edge weight
00855                 // by the way, be sure to turn on edges in the viewer -
00856                 // "Shaded with Edges" since they are off by default
00857                 //
00858                 TK_Size& rPatternSize = oSubpart.getEdgeWeightHandler();
00859                 rPatternSize.SetSize( 5.0f, TKO_Generic_Size_Points );
00860                 rPatternSize.serialize();
00861 
00862                 //
00863                 // the polygon
00864                 //
00865                 TK_Polypoint& rPolygon = oSubpart.getPolygonHandler();
00866 
00867                 float anBox[15] = { 2.0, 2.0, 2.0,
00868                                     2.0, 1.0, 2.0,
00869                                     1.0, 1.0, 2.0,
00870                                     1.0, 2.0, 2.0,
00871                                     2.0, 2.0, 2.0 };
00872 
00873                 rPolygon.SetPoints( 5, anBox );
00874                 rPolygon.serialize();
00875 
00876                 //
00877                 // override the green text with black
00878                 //
00879                 rColor.SetGeometry( TKO_Geo_Text );
00880                 rColor.SetRGB( 0.0f, 0.0f, 0.0f );
00881                 rColor.serialize();
00882 
00883                 //
00884                 // draw some text on the polygon
00885                 //
00886                 TK_Text& rText = oSubpart.getTextWithEncodingHandler();
00887                 rText.SetEncoding( TKO_Enc_Unicode );
00888                 rText.SetPosition( 1.5f, 1.5f, 1.5f );
00889                 rText.SetString( (unsigned short const*)(L"3D DWF") );
00890                 rText.serialize();
00891 
00892                 //
00893                 // by default, HOOPS draws text in 'annotation' mode only
00894                 // we can turn this off and make our text part of the scene:
00895                 //
00896                 TK_Text_Font& rFont = oSubpart.getTextFontHandler();
00897                 rFont.SetTransforms( TKO_Font_Transform_Full );
00898                 
00899                 rFont.SetMask( TKO_Font_Transforms );
00900                 rFont.serialize();
00901             }
00902             oSubpart.close();
00903 
00904             //
00905             // let's make this kind of look like our first part and add some lines
00906             // this time we will make them a selectable unit
00907             //
00908             DWFSegment oLinesPart = oPart2.openSegment();
00909             
00910             oLinesPart.open( L"Lines" );
00911             {
00912                 TK_Line& rLine = oLinesPart.getLineHandler();
00913 
00914                 rLine.SetPoints( 0.0f,
00915                                  0.0f,
00916                                  0.0f,
00917                                  center.x + 2.0f*radius,
00918                                  center.y + 2.0f*radius,
00919                                  center.z + 2.0f*radius );
00920 
00921                 rLine.serialize();
00922 
00923                 rLine.SetPoints( center.x - 2.0f*radius,
00924                                  center.y - 2.0f*radius,
00925                                  center.z - 2.0f*radius,
00926                                  0.0f,
00927                                  0.0f,
00928                                  0.0f );
00929 
00930                 rLine.serialize();
00931             }
00932             oLinesPart.close();
00933 
00934             //
00935             // add the property set to the part (by reference - part 1 owns it)
00936             //
00937             oPart2.referencePropertyContainer( *pPartProperties );
00938 
00939         }
00940         oPart2.close();
00941 
00942         //
00943         // create another part
00944         //
00945         DWFSegment oPart3 = oRootSegment.openSegment();
00946 
00947         oPart3.open( L"Third Part" );
00948         {
00949             //
00950             // red faces
00951             //
00952             rColor.SetGeometry( TKO_Geo_Face );
00953             rColor.SetRGB( 0.67f, 0.0f, 0.05f );
00954             rColor.serialize();
00955 
00956             //
00957             // let's first reposition everything in this segment
00958             //
00959             float anTransform[16] = { 1.0f, 0.0f, 0.0f, 0.0f,
00960                                       0.0f, 1.0f, 0.0f, 0.0f,
00961                                       0.0f, 0.0f, 1.0f, 0.0f,
00962                                       -4.33f, -1.34f, -0.134f, 1.0f };
00963 
00964             TK_Matrix& rMatrix = oPart3.getModellingMatrixHandler();
00965             rMatrix.SetMatrix( anTransform );
00966             rMatrix.serialize();
00967 
00968             //
00969             // expliciting naming the segment
00970             //
00971             DWFSegment oSubpart1 = oPart3.openSegment();
00972             oSubpart1.open( L"Ball 1" );
00973             {
00974                 //
00975                 // add our sphere 
00976                 //
00977                 oSubpart1.include( oSphere_include );
00978 
00979                 //
00980                 // override the sphere properties
00981                 //
00982                 //oProperty.setName( L"Cost" );
00983                 //oProperty.setValue( L"$3.00" );
00984                 //oProperty.setCategory( L"Sphere Properties" );
00985                 oProperty.setName( L"いくらですか?" );
00986                 oProperty.setValue( L"さんぜん円" );
00987                 oProperty.setCategory( L"プロプルチズ" );
00988                 oSubpart1.addProperty( oProperty );
00989 
00990                 oProperty.setName( L"Vendor" );
00991                 oProperty.setValue( L"Dun & Broadstreet" );
00992                 oSubpart1.addProperty( oProperty );
00993             }
00994             oSubpart1.close();
00995 
00996             //
00997             // unnamed segment
00998             //
00999             DWFSegment oSubpart2 = oPart3.openSegment();
01000             oSubpart2.open();
01001             {
01002                 float anTransform[16] = { 1.0f, 0.0f, 0.0f, 0.0f,
01003                                           0.0f, 1.0f, 0.0f, 0.0f,
01004                                           0.0f, 0.0f, 1.0f, 0.0f,
01005                                           1.0f, 1.0f, 1.0f, 1.0f };
01006 
01007                 TK_Matrix& rMatrix = oPart3.getModellingMatrixHandler();
01008                 rMatrix.SetMatrix( anTransform );
01009                 rMatrix.serialize();
01010 
01011                 //
01012                 // including with a different name
01013                 //
01014                 oSubpart2.include( oSphere_include, DWFString(L"Ball 2") );
01015             }
01016             oSubpart2.close();
01017 
01018             DWFSegment oSubpart3 = oPart3.openSegment();
01019             oSubpart3.open( L"Ball 3" );
01020             {
01021                 float anTransform[16] = { 1.0f, 0.0f, 0.0f, 0.0f,
01022                                           0.0f, 1.0f, 0.0f, 0.0f,
01023                                           0.0f, 0.0f, 1.0f, 0.0f,
01024                                           1.0f, -1.0f, -1.0f, 1.0f };
01025 
01026                 TK_Matrix& rMatrix = oPart3.getModellingMatrixHandler();
01027                 rMatrix.SetMatrix( anTransform );
01028                 rMatrix.serialize();
01029 
01030                 //
01031                 // including with a different name
01032                 //
01033                 oSubpart3.include( oSphere_include );
01034             }
01035             oSubpart3.close();
01036 
01037             //
01038             // 
01039             //
01040             DWFSegment oCut = oPart3.openSegment();
01041             oCut.open( L"Cutting Plane" );
01042             {
01043                 TK_Cutting_Plane& rCut = oCut.getCuttingPlaneHandler();
01044                 rCut.SetPlane( -1.0f, -1.0f, 0.0f, 0.0f );
01045                 rCut.serialize();
01046             }
01047             oCut.close();
01048 
01049         }
01050         oPart3.close();
01051 
01052         //
01053         // test embedded fonts 
01054         //
01055         DWFSegment oPart4 = oRootSegment.openSegment();
01056         oPart4.open();
01057         {
01058             //
01059             // we'll add some japanese text in MS PGothic
01060             // we aren't modifying the transform mask so this text will be billboarded
01061             //
01062             TK_Text_Font& rFont = oPart4.getTextFontHandler();
01063             rFont.SetNames( "MS PGothic" );
01064             rFont.SetMask( TKO_Font_Names );
01065             rFont.serialize();
01066 
01067             //
01068             // the text
01069             //
01070             TK_Text& rText = oPart4.getTextWithEncodingHandler();
01071             rText.SetEncoding( TKO_Enc_Unicode );
01072             rText.SetPosition( -2.0f, 4.0f, 0.0f );
01073             rText.SetString( (unsigned short const*)(L"日本語のテキスト") );
01074             rText.serialize();
01075 
01076             //
01077             // font handling is a platform specific issue
01078             // unfortunately right now
01079             //
01080 #ifdef  _DWFCORE_WIN32_SYSTEM
01081 
01082             //
01083             // now embed the font in the DWF package
01084             // notice that this is win32 specific code
01085             //
01086             HFONT hFont = CreateFontW(100, 0, 0, 0, FW_NORMAL, 0, 0, 0, 0, 0, 0, 0, 0, L"MS PGothic");
01087 
01088             DWFEmbeddedFontImpl_Win32* pImpl2 = new DWFEmbeddedFontImpl_Win32( hFont );
01089             DWFEmbeddedFont* pFont = new DWFEmbeddedFont( pImpl2 );
01090 
01091             //
01092             // add just the characters that were used
01093             //
01094             pFont->addCharacters( L"日本語のテキスト" );
01095 
01096             rModel.embedFont( pFont );
01097 #endif
01098 
01099         }
01100         oPart4.close();
01101 
01102     }
01103     oRootSegment.close();
01104 
01105     rModel.setBoundingSphere( 0.0f, 0.0f, 0.0f, 15.0f );
01106 
01107     //
01108     // we can also add a thumbnail image
01109     //
01110 
01111     //
01112     // open as a streaming binary file
01113     //
01114     DWFStreamFileDescriptor* pThumbnailFile = new DWFStreamFileDescriptor( "thumbnail.png", "rb" );
01115     pThumbnailFile->open();
01116 
01117     //
01118     // create a stream and attach the file descriptor
01119     //
01120     DWFFileInputStream* pThumbnailStream = new DWFFileInputStream;
01121     pThumbnailStream->attach( pThumbnailFile, false );
01122 
01123     //
01124     // create a thumbnail image and attach the file stream
01125     //
01126     DWFImage* pThumbnail = DWFCORE_ALLOC_OBJECT( DWFImage(DWFMIME::kzMIMEType_PNG, 
01127                                                           DWFImage::eThumbnail, 
01128                                                           24, 
01129                                                           218, 
01130                                                           213) );
01131 
01132     if (pThumbnail)
01133     {
01134         pThumbnail->attach( pThumbnailStream, true );
01135 
01136         //
01137         // add to the model
01138         //
01139         rModel.addResource( pThumbnail );
01140     }
01141 }
01142 
01143 void do_publishProxyGraph( DWFPackagePublisher* pPackagePublisher )
01144 {
01145     //
01146     // Add the proxy graphics section
01147     //
01148 
01149     double  fPaperWidth(8.5);
01150     double  fPaperHeight(11.0);
01151     int nImageWidth = 640;
01152     int nImageHeight = 480;
01153     double proxyTransform[4][4] = { 1, 0, 0, 0, 
01154                                     0, 1, 0, 0, 
01155                                     0, 0, 1, 0, 
01156                                     0, 0, 0, 1 };
01157 
01158     double anPaperClip[4] = { 0, 0, 11, 8.5 };
01159 
01160     DWFToolkit::DWFPaper proxyPaper( fPaperWidth, fPaperHeight, DWFToolkit::DWFPaper::eInches, 0x00ffffff, (const double*)anPaperClip );
01161 
01162     //
01163     // Create the page.
01164     //
01165     DWFPlot pProxyPlot( L"Proxy Page", L"3DDWFxPublish.cpp" );
01166 
01167     pProxyPlot.open( proxyPaper, (const double*)proxyTransform );
01168     //
01169     // Create the image resource.
01170     //
01171     DWFToolkit::DWFImageResource* pProxyImage = 
01172         DWFCORE_ALLOC_OBJECT(
01173             DWFToolkit::DWFImageResource(
01174                 L"Proxy Graphics Image",                // title
01175                 DWFXML::kzRole_RasterReference,         // role
01176                 DWFCore::DWFMIME::kzMIMEType_PNG,       // MIME type
01177                 L"Autodesk, Inc.",                      // author
01178                 L"Proxy Graphics Image",                // description
01179                 L"",                                    // creation time
01180                 L""                                     // modification time
01181             )
01182         ); 
01183 
01184     if(pProxyImage == NULL)
01185     {
01186         _DWFCORE_THROW( DWFMemoryException, L"Failed to allocate a DWFImageResource for the proxy content." );
01187     }
01188 
01189     //
01190     // configure the image
01191     //
01192 
01193     double anClip[4] = { 0, 0, fPaperWidth, fPaperHeight };
01194     double anOrigExtents[4] = { 0, 0, nImageWidth, nImageHeight };
01195 
01196     double imageTransform[4][4] = { 1, 0, 0, 0, 
01197                                     0, 1, 0, 0,
01198                                     0, 0, 1, 0, 
01199                                     0, 0, 0, 1 };
01200 
01201     pProxyImage->configureGraphic( (const double*)imageTransform,
01202                                     NULL,(const double*)anClip, true, 1 );
01203 
01204     pProxyImage->configureImage( 0, false, false, 0, anOrigExtents ); 
01205 
01206 
01207     //
01208     // extras for the image
01209     // here we note the image has 24 bpp (color depth)
01210     //
01211     pProxyImage->configureImage( 24 );
01212 
01213     //
01214     // set the resource's stream from the thumbnail file
01215     //
01216     setResourceStreamFromFile( pProxyImage, L"ProxyImage.png" );
01217 
01218     //
01219     // Request a particular name. The FixedPage content will refer to the image by this name.
01220     //
01221     char zProxyImageName[] = "ProxyGraphics.png";
01222     pProxyImage->setRequestedName(zProxyImageName);
01223 
01224     //
01225     // The hyperlink target.
01226     //
01227     char zHyperlinkTarget[] = "http://www.autodesk.com/designreview-xpsviewer";
01228 
01229     //
01230     // Add the proxy image to the plot
01231     //
01232 
01233     ((DWFResourceContainer&) pProxyPlot).addResource( pProxyImage, false );
01234 
01235     //
01236     // Produce the FixedPage content.
01237     //
01238     // It's easier to do this directly, rather than use the Whip/XAML toolkit.
01239     //
01240     // We use char instead of wchar_t, because we have to provide UTF-8 for the resource input stream.
01241     //
01242 
01243     char zWidth[64], zHeight[64];
01244     DWFString::DoubleToString(zWidth, 64, fPaperWidth, 17);
01245     DWFString::DoubleToString(zHeight, 64, fPaperHeight, 17);
01246 
01247     //
01248     // fit the image to the paper, reducing by a given factor
01249     // x-scale is paper_width / image_width_in_pixels
01250     // y-scale is paper_height / image_height_in_pixels
01251     // actual scale is the minimum of x & y - for uniform scaling
01252     // x-translation : (paper_width  - image_width_in_pixels  * scale) / 2; this centers along the x-axis
01253     // y-translation : (paper_height - image_height_in_pixels * scale) / 2; this centers along the y-axis
01254     //
01255     double reductionFactor = 1.0;
01256     double xScale = fPaperWidth  / nImageWidth;
01257     double yScale = fPaperHeight / nImageHeight;
01258     double scale = (fabs(xScale) < fabs(yScale) ? xScale : yScale) * reductionFactor;
01259     double xOffset = (fPaperWidth  - (nImageWidth  * scale))/2;
01260     double yOffset = (fPaperHeight - (nImageHeight * scale))/2;
01261 
01262     char zImageXMin[64], zImageXMax[64], zImageYMin[64], zImageYMax[64];
01263     DWFString::DoubleToString(zImageXMin, 64, xOffset, 17);
01264     DWFString::DoubleToString(zImageXMax, 64, fPaperWidth-xOffset, 17);
01265     DWFString::DoubleToString(zImageYMin, 64, yOffset, 17);
01266     DWFString::DoubleToString(zImageYMax, 64, fPaperHeight-yOffset, 17);
01267 
01268     char zFormatString[] =
01269         "<Path Data=\"M0,0 L%s,0 L%s,%s L0,%s z\" FixedPage.NavigateUri=\"%s\">"
01270         "<Path.Fill>"
01271         "<ImageBrush ImageSource=\"%s\" Viewport=\"%s,%s, %s,%s\" ViewportUnits=\"Absolute\" Viewbox=\"0,0, %d,%d\" ViewboxUnits=\"Absolute\"/>"
01272         "</Path.Fill>"
01273         "</Path>";
01274 
01275     //
01276     // Strangely, to prevent non-uniform scaling, we need to specify a *square* viewbox.
01277     // It has to be as big as the largest pixel dimension of the image.
01278     //
01279     int nMaxDimension = (nImageWidth>nImageHeight) ? nImageWidth : nImageHeight;
01280 
01281     char zBuffer[16384];
01282     int nChars = sprintf(
01283         zBuffer,
01284         zFormatString,
01285         zWidth,
01286         zWidth,
01287         zHeight,
01288         zHeight,
01289         zHyperlinkTarget,
01290         zProxyImageName,    // /dwf/documents/99FCDD74-9D2C-46B3-900E-5A69098233FC/sections/2B7879BD-CC9A-4A0A-B993-AB98BB077BB9.png
01291         zImageXMin,
01292         zImageYMin,
01293         zImageXMax,
01294         zImageYMax,
01295         nMaxDimension,
01296         nMaxDimension
01297         );
01298 
01299     //
01300     // Note, we do not need or want to carry along the null terminator, as
01301     // this buffer will be inserted into some surrounding XML by the DWFX
01302     // packager, and the null would make mal-formed XML.
01303     //
01304     char* pNewBuffer = DWFCORE_ALLOC_MEMORY(char, nChars);
01305     DWFCORE_COPY_MEMORY(pNewBuffer, zBuffer, nChars);
01306     DWFBufferInputStream* pFPIS = DWFCORE_ALLOC_OBJECT(DWFBufferInputStream(pNewBuffer, nChars, true));
01307 
01308     //
01309     // Attach the Stream to plot and close
01310     //
01311     pProxyPlot.attach(pFPIS, false);
01312     pProxyPlot.close();
01313 
01314     //
01315     // finally, drop the page into the writer
01316     //
01317     (( DWFXPackagePublisher *)pPackagePublisher)->addProxyGraphicsSection(&pProxyPlot, DWFToolkit::DWFXPackagePublisher::eIfOnlyPartialPageOutput);
01318 }

Generated on Tue Jan 6 22:40:01 2009 for Autodesk DWF Toolkit by  doxygen 1.4.5