00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
00057 
00058 
00059 
00060 
00061 
00062 
00063 
00064 
00065 
00066 
00067 
00068 
00069 
00070 
00071 
00072 
00073 
00074 
00075 
00076 
00077 
00078 
00079 
00080 
00081 
00082 
00083 
00084 
00085 
00086 
00087 
00088 
00089 
00090 
00091 
00092 
00093 
00094 
00095 
00096 
00097 
00098 
00099 
00100 #include "camtypes.h"
00101 #include "cmxexdc.h"
00102 #include "cmxrendr.h"
00103 #include "cmxform.h"
00104 
00105 
00106 
00107 #include "colcontx.h"
00108 
00109 
00110 #include "fillramp.h"
00111 
00112 
00113 
00114 
00115 
00116 
00117 
00118 
00119 
00120 
00121 
00122 
00123 
00124 
00125 
00126 BOOL CMXExportDC::WriteBlankAttributes(INT32 Tag)
00127 {
00128     
00129     if(Tag != -1)
00130         if(!StartTag(Tag))
00131             return FALSE;
00132 
00133     
00134     WriteByte(0);
00135 
00136     
00137     if(Tag != -1)
00138         if(!EndTag())
00139             return FALSE;
00140     
00141     return TRUE;
00142 }
00143 
00144 
00145 
00146 
00147 
00148 
00149 
00150 
00151 
00152 
00153 
00154 
00155 
00156 
00157 
00158 BOOL CMXExportDC::WriteAttributes(CMXRenderRegion *pReg, INT32 Tag, DocCoord *Coords, INT32 NumCoords, BOOL ForceNoFill)
00159 {
00160     
00161     BOOL WasLens = FALSE;
00162     if(!WriteAttrCheckLens(pReg, Tag, Coords, NumCoords, &WasLens))
00163         return FALSE;
00164 
00165     
00166     if(WasLens)
00167         return TRUE;        
00168 
00169     
00170     if(Tag != -1)
00171         if(!StartTag(Tag))
00172             return FALSE;
00173 
00174     
00175     WriteByte((ForceNoFill?0:cmxRENDATTRMASK_FILL) | cmxRENDATTRMASK_OUTLINE);
00176 
00177     
00178     if(!ForceNoFill)
00179         if(!WriteFillSpec(pReg, Coords, NumCoords, ForceNoFill))
00180             return FALSE;
00181 
00182     
00183     if(!WriteOutlineSpec(pReg))
00184         return FALSE;
00185 
00186     
00187     if(Tag != -1)
00188         if(!EndTag())
00189             return FALSE;
00190     
00191     return TRUE;
00192 }
00193 
00194 
00195 
00196 
00197 
00198 
00199 
00200 
00201 
00202 
00203 
00204 
00205 
00206 
00207 BOOL CMXExportDC::WriteFillType(WORD FillID)
00208 {
00209     ExportFile->write(&FillID, sizeof(FillID));
00210 
00211     return TRUE;
00212 }
00213 
00214 
00215 
00216 
00217 
00218 
00219 
00220 
00221 
00222 
00223 
00224 
00225 
00226 
00227 BOOL CMXExportDC::WriteFillSpec(CMXRenderRegion *pReg, DocCoord *Coords, INT32 NumCoords, BOOL NoFill)
00228 {
00229     
00230     if(!StartNestedTag(cmxTAG_RenderAttr_FillSpec))
00231         return FALSE;
00232 
00233     if(NoFill)
00234     {
00235         if(!WriteFillType(cmxFILLID_NONE))
00236             return FALSE;
00237     }
00238     else
00239     {
00240         
00241         FillGeometryAttribute *pFillGeometry
00242                 = (FillGeometryAttribute *)pReg->GetCurrentAttribute(ATTR_FILLGEOMETRY);
00243 
00244         
00245         ERROR2IF(pFillGeometry == 0, FALSE, "No fill geometry");
00246         ERROR3IF(!pFillGeometry->IsKindOf(CC_RUNTIME_CLASS(FillGeometryAttribute)), "not one of them there fill geometries");
00247 
00248         
00249         if(pFillGeometry->IsAFlatFill())
00250         {
00251             
00252             DocColour *pCol = pFillGeometry->GetStartColour();
00253             ERROR2IF(pCol == NULL, FALSE, "not one of your earth colours");
00254             if(pCol->IsTransparent())
00255             {
00256                 
00257                 if(!WriteFillType(cmxFILLID_NONE))
00258                     return FALSE;
00259             }
00260             else
00261             {
00262                 
00263                 if(!WriteFillType(cmxFILLID_UNIFORM)
00264                     || !WriteFillSpecFlat(pReg, pFillGeometry))
00265                     return FALSE;
00266             }
00267         }
00268         else if(pFillGeometry->IsAKindOfBitmapFill())
00269         {
00270             
00271             if(!WriteFillType(9) 
00272                 || !WriteFillSpecBitmap(pReg, pFillGeometry, Coords, NumCoords))
00273                 return FALSE;
00274         }
00275         else if(pFillGeometry->IsAGradFill())
00276         {
00277             
00278             if(!WriteFillType(cmxFILLID_FOUNTAIN)
00279                 || !WriteFillSpecGrad(pReg, pFillGeometry, Coords, NumCoords))
00280                 return FALSE;
00281         }
00282         else
00283         {
00284             
00285             if(!WriteFillType(cmxFILLID_NONE))
00286                 return FALSE;
00287         }
00288     }
00289 
00290     
00291     if(!EndNestedTag())
00292         return FALSE;
00293     
00294     
00295     if(!WriteMinEndTag())
00296         return FALSE;
00297 
00298     return TRUE;
00299 }
00300 
00301 
00302 
00303 
00304 
00305 
00306 
00307 
00308 
00309 
00310 
00311 
00312 
00313 BOOL CMXExportDC::WriteFillSpecFlat(CMXRenderRegion *pReg, FillGeometryAttribute *pFill)
00314 {
00315     
00316     DocColour *pFillColour = pFill->GetStartColour();
00317     ERROR2IF(pFillColour == NULL, FALSE, "Wibble. No fill colour on this here flat fill");
00318 
00319     
00320     WORD FillReference = GetColourReference(pFillColour);
00321 
00322     
00323     struct {
00324         WORD FillReference;
00325         WORD ScreenReference;
00326     } filldef = {FillReference, cmxSCREENREFERENCE};
00327 
00328     if(!WriteNestedTag(cmxTAG_RenderAttr_FillSpec_Uniform, &filldef, sizeof(filldef))
00329         || !WriteMinEndTag())
00330         return FALSE;
00331 
00332     return TRUE;
00333 }
00334 
00335 
00336 
00337 
00338 
00339 
00340 
00341 
00342 
00343 
00344 
00345 
00346 
00347 
00348 
00349 
00350 
00351 BOOL CMXExportDC::WriteFillSpecGrad ( CMXRenderRegion *pReg,
00352                                       FillGeometryAttribute *pFill,
00353                                       DocCoord *Coords,
00354                                       INT32 NumCoords )
00355 {
00356     DocColour   StartColour;                
00357     DocColour   EndColour;                  
00358     DocColour   MidColour;                  
00359     BOOL        Radial          = FALSE;    
00360     BOOL        FourColour      = FALSE;    
00361 
00362     
00363     if ( pFill->IsARadialFill () )
00364     {
00365         
00366         
00367         StartColour = *( pFill->GetEndColour () );
00368         EndColour   = *( pFill->GetStartColour () );
00369 
00370         Radial = TRUE;
00371     }
00372     else if ( pFill->IsAConicalFill () || pFill->IsASquareFill () )
00373     {
00374         
00375         StartColour = *( pFill->GetStartColour () );
00376         EndColour   = *( pFill->GetEndColour () );
00377 
00378         Radial = TRUE;
00379     }
00380     else if ( pFill->IsAFourColFill () )
00381     {
00382         
00383         
00384         StartColour = *( pFill->GetStartColour () );
00385         EndColour   = *( pFill->GetEndColour3 () );
00386         MidColour.Mix ( pFill->GetEndColour (), pFill->GetEndColour2 (), 0.5f, NULL, FALSE, NULL );
00387 
00388         
00389         FourColour  = TRUE;
00390     }
00391     else if ( pFill->IsAThreeColFill () )
00392     {
00393         
00394         
00395         StartColour = *( pFill->GetStartColour () );
00396         EndColour.Mix ( pFill->GetEndColour (), pFill->GetEndColour2 (), 0.5f, NULL, FALSE, NULL );
00397     }
00398     else
00399     {
00400         
00401         StartColour = *( pFill->GetStartColour () );
00402         EndColour   = *( pFill->GetEndColour () );
00403     }
00404 
00405     
00406     WORD    StartColReference   = GetColourReference ( &StartColour );
00407     WORD    EndColReference     = GetColourReference ( &EndColour );
00408     WORD    MidColReference     = 0;
00409     WORD    FillMode            = cmxFILLMODE_RGB;
00410 
00411     
00412     
00413     if ( FourColour )
00414     {
00415         MidColReference = GetColourReference ( &MidColour );
00416     }
00417 
00418     
00419     FillEffectAttribute *pFillEff =
00420         (FillEffectAttribute *)pReg->GetCurrentAttribute(ATTR_FILLEFFECT);
00421     ERROR2IF(pFillEff == NULL || !pFillEff->IsKindOf(CC_RUNTIME_CLASS(FillEffectAttribute)), FALSE, "not a fill effect");
00422     BOOL Rainbow = FALSE, Alt = FALSE;
00423     if(IS_A(pFillEff, FillEffectRainbowAttribute))
00424         Rainbow = TRUE;
00425     if(IS_A(pFillEff, FillEffectAltRainbowAttribute))
00426         Rainbow = Alt = TRUE;
00427 
00428     if(Rainbow)
00429     {
00430         
00431         
00432         ColourContext *Conv = ColourContext::GetGlobalDefault(COLOURMODEL_HSVT);
00433 
00434         ColourHSVT StartC;
00435         ColourHSVT EndC;
00436 
00437         Conv->ConvertColour( &StartColour, (ColourGeneric *)&StartC);
00438         Conv->ConvertColour( &EndColour, (ColourGeneric *)&EndC);
00439 
00440         
00441         double Difference = (EndC.Hue.MakeDouble()) - (StartC.Hue.MakeDouble());
00442 
00443         BOOL ClockWise = (Difference < 0);
00444 
00445         if(fabs(Difference) >= 0.5)
00446             ClockWise = !ClockWise;
00447 
00448         if(Alt = TRUE)
00449             ClockWise = !ClockWise;
00450         
00451         
00452         if(ClockWise)
00453             FillMode = cmxFILLMODE_HSB_CW;
00454         else
00455             FillMode = cmxFILLMODE_HSB_CCW;
00456     }
00457 
00458     
00459     DocCoord StartPoint = *( pFill->GetStartPoint() );
00460     DocCoord EndPoint;
00461 
00462     
00463     if ( pFill->IsAFourColFill () )
00464     {
00465         
00466         EndPoint = *( pFill->GetEndPoint3 () );
00467     }
00468     else if ( pFill->IsAThreeColFill () )
00469     {
00470         
00471         EndPoint = *( pFill->GetEndPoint () ) +
00472                    *( pFill->GetEndPoint2 () ) -
00473                    *( pFill->GetStartPoint () );
00474     }
00475     else
00476     {
00477         
00478         EndPoint = *( pFill->GetEndPoint () );
00479     }
00480 
00481 
00482     
00483     DocRect cBBox;
00484     CalcCorelBBox(Coords, NumCoords, &cBBox);
00485 
00486     
00487     if ( StartPoint == EndPoint || cBBox.Width () == 0 || cBBox.Height () == 0 )
00488         return WriteFillSpecFlat(pReg, pFill);
00489 
00490     
00491     DocCoord Centre;
00492     Centre.x = cBBox.lo.x + cBBox.Width() / 2;
00493     Centre.y = cBBox.lo.y + cBBox.Height() / 2;
00494 
00495     
00496 
00497     
00498     double dx = EndPoint.x - StartPoint.x;
00499     double dy = EndPoint.y - StartPoint.y;
00500     double PointDist = sqrt(((dx * dx) + (dy * dy)));
00501 
00502     
00503     double Angle = atan2(dy, dx);
00504         
00505         
00506 
00507     INT32 StartPercent;
00508     INT32 EndPercent;
00509 
00510     cmxFillBase1 fb1;
00511     fb1.Padding = 0;
00512     cmxFillBase2 fb2;
00513     fb2.XOffset = 0;
00514     fb2.YOffset = 0;
00515 
00516     if(Radial)
00517     {
00518         
00519 
00520         
00521         
00522         DocCoord dCentre = StartPoint - Centre;
00523         fb2.XOffset = (dCentre.x * 100) / cBBox.Width();
00524         fb2.YOffset = (dCentre.y * 100) / cBBox.Height();
00525         
00526         if(fb2.XOffset > 100) fb2.XOffset = 100;
00527         if(fb2.XOffset < -100) fb2.XOffset = -100;
00528         if(fb2.YOffset > 100) fb2.YOffset = 100;
00529         if(fb2.YOffset < -100) fb2.YOffset = -100;
00530 
00531         
00532         
00533         double w = cBBox.Width(), h = cBBox.Height();
00534         double bboxdiagonal = sqrt(w*w + h*h);
00535         double cdx = dCentre.x, cdy = dCentre.y;
00536         double cendist = sqrt(cdx*cdx + cdy*cdy);
00537         double BodgeFactor = 1 + (cendist / (bboxdiagonal / 2));
00538         double targetradius = PointDist / BodgeFactor;
00539         double Pad = 50 * (1 - (2 * targetradius) / bboxdiagonal);
00540         
00541         if(Pad < 0) Pad = 0;
00542         if(Pad > 44) Pad = 44;
00543         
00544         fb1.Padding = (WORD)Pad;
00545 
00546         
00547         StartPercent = 0;
00548         EndPercent = 0;
00549 
00550         
00551         if(pFill->IsASquareFill())
00552         {
00553             WORD t = StartColReference;
00554             StartColReference = EndColReference;
00555             EndColReference = t;
00556         }
00557     } 
00558 
00559     else 
00560     {
00561         
00562 
00563         
00564         
00565 
00566         
00567         double cAngle = Angle;
00568         INT32 cAR = 0;
00569         while(cAngle > (PI/2))
00570         {
00571             cAngle -= PI/2;
00572             cAR++;
00573         }
00574 
00575         
00576         
00577         INT32 qdx = cBBox.Width() / 2;
00578         INT32 qdy = cBBox.Height() / 2;
00579         if((cAR & 1) != 0)
00580         {
00581             
00582             INT32 t = qdy;
00583             qdy = qdx;
00584             qdx = t;
00585         }
00586         DocCoord i;
00587         if(qdy == 0)
00588         {
00589             
00590             i.x = qdx;
00591             i.y = 0;
00592         }
00593         else
00594         {
00595             double predqdy = qdx * tan(cAngle);
00596             if(predqdy > qdy)
00597             {
00598                 
00599                 i.x = (INT32)(((double)qdy) / tan(cAngle));
00600                 i.y = qdy;
00601             }
00602             else
00603             {
00604                 
00605                 i.x = qdx;
00606                 i.y = (INT32)(((double)qdx) * tan(cAngle));
00607             }
00608         }
00609 
00610         
00611         
00612         
00613 
00614         
00615         
00616         INT32 linelength = (INT32)sqrt(((double)(i.x) * (double)(i.x)) + ((double)(i.y) * (double)(i.y)));
00617         
00618         if(linelength == 0)
00619             return WriteFillSpecFlat(pReg, pFill);
00620 
00621         
00622         DocCoord    dStartPoint = StartPoint - Centre;
00623         DocCoord    dEndPoint   = EndPoint - Centre;
00624 
00625         
00626         
00627         Matrix Mat(((- Angle) * 360.0) / (2*PI));   
00628         Mat.transform(&dStartPoint);
00629         Mat.transform(&dEndPoint);
00630 
00631         
00632         INT32 dStart = dStartPoint.x + linelength;
00633         INT32 dEnd = linelength - dEndPoint.x;
00634         if(dStart < 0) dStart = 0;
00635         if(dEnd < 0) dEnd = 0;
00636         INT32 dPad;     
00637         if(dStart < dEnd)
00638             dPad = dStart;
00639         else
00640             dPad = dEnd;
00641 
00642         INT32 padval = (dPad * 100) / (linelength * 2);
00643         if(padval < 0) padval = 0;
00644         if(padval > 44) padval = 44;
00645         fb1.Padding = (WORD)padval;
00646         
00647         
00648         linelength -= dPad;
00649 
00650         
00651         
00652         StartPercent = (INT32)((dStartPoint.x + linelength) * 100);
00653         EndPercent = (INT32)((dEndPoint.x + linelength) * 100);
00654         StartPercent /= (linelength * 2);
00655         EndPercent /= (linelength * 2);
00656 
00657         
00658         if(StartPercent < 0) StartPercent = 0;
00659         if(StartPercent > 100) StartPercent = 100;
00660         if(EndPercent < 0) EndPercent = 0;
00661         if(EndPercent > 100) EndPercent = 100;
00662         if(EndPercent < StartPercent)
00663         {
00664             INT32 t = StartPercent;
00665             StartPercent = EndPercent;
00666             EndPercent = t;
00667         }
00668     } 
00669 
00670     
00671     
00672     if(!StartNestedTag(cmxTAG_RenderAttr_FillSpec_Fountain_Base))
00673         return FALSE;
00674 
00675     if(pFill->IsARadialFill())
00676         fb1.Type = cmxFOUNTAINTYPE_RADIAL;
00677     else if(pFill->IsASquareFill())
00678         fb1.Type = cmxFOUNTAINTYPE_SQUARE;
00679     else if(pFill->IsAConicalFill())
00680         fb1.Type = cmxFOUNTAINTYPE_CONICAL;
00681     else
00682         fb1.Type = cmxFOUNTAINTYPE_LINEAR;
00683     fb1.Screen = cmxSCREENREFERENCE;
00684     
00685 
00686     
00687     fb2.StepCount = 0;
00688     fb2.FillMode = FillMode;
00689     fb2.RateMethod = 0;
00690     fb2.RateValue = 50;         
00691 
00692     if(!Radial)
00693     {
00694         if(FillMode == cmxFILLMODE_RGB)
00695         {
00696             
00697             
00698             
00699             fb2.FillMode = cmxFILLMODE_CUSTOM;
00700         }
00701         else
00702         {
00703             
00704             
00705             
00706             StartPercent = 0;
00707             EndPercent = 0;
00708         }
00709     }
00710 
00711     
00712     ExportFile->write(&fb1, sizeof(fb1));
00713 
00714     WriteAngle(Angle);
00715 
00716     if(ThirtyTwoBit)
00717     {
00718         ExportFile->write(&fb2, sizeof(fb2));
00719     }
00720     else
00721     {
00722         
00723         cmxFillBase2_16 b = {0, (SWORD)fb2.XOffset, (SWORD)fb2.YOffset,
00724             fb2.StepCount, fb2.FillMode};
00725 
00726         ExportFile->write(&b, sizeof(b));
00727     }
00728 
00729     
00730     if(!EndNestedTag())
00731         return FALSE;
00732 
00733     
00734     if(!StartNestedTag(cmxTAG_RenderAttr_FillSpec_Fountain_Color))
00735         return FALSE;
00736 
00737     cmxGradFillColour   col;
00738     ColourRamp          *pRamp  = pFill->GetColourRamp ();
00739     WORD                NCol    = 2 + ( ( StartPercent != 0 ) ? 1 : 0 ) +
00740                                   ( ( EndPercent != 100 ) ? 1 : 0 ) + ( FourColour ? 1 : 0 );
00741 
00742     
00743     if ( pRamp != NULL )
00744     {
00745         UINT32  FirstIndex  = 0;
00746         UINT32  LastIndex   = 0;
00747 
00748         
00749         
00750         pRamp->GetIndexRange ( &FirstIndex, &LastIndex );
00751 
00752         
00753         
00754         
00755         
00756         NCol += 1 + LastIndex - FirstIndex;
00757     }
00758 
00759     
00760     ExportFile->write ( &NCol, sizeof ( NCol ) );
00761 
00762     
00763     if(StartPercent != 0)
00764     {
00765         col.ColRef = StartColReference;
00766         col.ColPos = 0;
00767         ExportFile->write(&col, sizeof(col));
00768     }
00769 
00770     col.ColRef = StartColReference;
00771     col.ColPos = (WORD)StartPercent;
00772     ExportFile->write(&col, sizeof(col));
00773 
00774     
00775     if ( FourColour )
00776     {
00777         col.ColRef  = MidColReference;
00778         col.ColPos  = ( WORD ) ( ( StartPercent + EndPercent ) / 2 );
00779         ExportFile->write ( &col, sizeof ( col ) );
00780     }
00781 
00782     
00783     if ( pRamp != NULL )
00784     {
00785         ColRampItem *pColour = pRamp->GetFirstCol ();
00786 
00787         
00788         while ( pColour != NULL )
00789         {
00790             cmxGradFillColour   RampColour;
00791 
00792             
00793             RampColour.ColPos   = ( WORD ) ( 100.0f * pColour->GetPosition () );
00794             RampColour.ColRef   = GetColourReference ( &( pColour->GetColour () ) );
00795 
00796             
00797             ExportFile->write ( &RampColour, sizeof ( RampColour ) );
00798 
00799             
00800             pColour = pRamp->GetNextCol ( pColour );
00801         }
00802     }
00803 
00804     
00805     col.ColRef = EndColReference;
00806     col.ColPos = (WORD)EndPercent;
00807     ExportFile->write(&col, sizeof(col));
00808 
00809     if(EndPercent != 100)
00810     {
00811         col.ColPos = 100;
00812         ExportFile->write(&col, sizeof(col));
00813     }
00814 
00815     if(!EndNestedTag())
00816         return FALSE;
00817 
00818     
00819     if(!WriteMinEndTag())
00820         return FALSE;
00821 
00822     return TRUE;
00823 }
00824 
00825 
00826 
00827 
00828 
00829 
00830 
00831 
00832 
00833 
00834 
00835 
00836 
00837 
00838 BOOL CMXExportDC::WriteFillSpecBitmap(CMXRenderRegion *pReg, FillGeometryAttribute *pFill, DocCoord *Coords, INT32 NumCoords)
00839 {
00840     
00841     BitmapFillAttribute *pBFillAttr = (BitmapFillAttribute *)pFill;
00842     ERROR3IF(!pBFillAttr->IsKindOf(CC_RUNTIME_CLASS(BitmapFillAttribute)), "not a bitmap fill attr");
00843 
00844     
00845     DocColour *pStartColour = 0;
00846     DocColour *pEndColour = 0;
00847     EFFECTTYPE Effect = EFFECT_RGB;
00848 
00849     
00850     pStartColour = pFill->GetStartColour();
00851     pEndColour = pFill->GetEndColour();
00852     if(pStartColour == 0 || pEndColour == 0
00853         || pStartColour->IsTransparent()
00854         || pEndColour->IsTransparent())
00855     {
00856         pStartColour = 0;
00857         pEndColour = 0;
00858     }
00859     
00860     if(pStartColour != 0)
00861     {
00862         
00863         Effect = pReg->GetFillEffect();
00864     }
00865 
00866     
00867     KernelBitmap *pBitmap = pBFillAttr->BitmapRef.GetBitmap();
00868     WORD BitmapRef = GetBitmapReference(pBitmap, pStartColour, pEndColour, Effect);
00869 
00870     
00871     CMXReferBitmapFill *pBFill = new CMXReferBitmapFill(this);
00872     if(pBFill == 0)
00873         return FALSE;
00874     pBFill->Set(BitmapRef);
00875 
00876     
00877     ReferList.AddTail(pBFill);
00878 
00879     
00880     WORD BitmapFillProcReference = GetProcedureReference(pBFill);
00881 
00882     
00883     if(!StartNestedTag(cmxTAG_RenderAttr_FillSpec_ColorBM))
00884         return FALSE;
00885     
00886     ExportFile->write(&BitmapFillProcReference, sizeof(BitmapFillProcReference));
00887 
00888     
00889     if(!StartNestedTag(cmxTAG_Tiling))
00890         return FALSE;
00891 
00892     
00893     DocCoord *Start = pFill->GetStartPoint();
00894     DocCoord *End1 = pFill->GetEndPoint();
00895     DocCoord *End2 = pFill->GetEndPoint2();
00896 
00897     
00898     cmxTilingEnd tile;
00899 
00900     
00901     
00902     
00903     
00904     DocRect cBBox;
00905     double  TileWidth   = Start->Distance ( *End1 );
00906     double  TileHeight  = Start->Distance ( *End2 );
00907 
00908     
00909     CalcCorelBBox(Coords, NumCoords, &cBBox);
00910 
00911     
00912     
00913     if ( ThirtyTwoBit )
00914     {
00915         cmxTilingBegin32 Tile32;
00916         Tile32.Width    = static_cast<DWORD> ( Round ( TileWidth  * ScaleFactor ) );
00917         Tile32.Height   = static_cast<DWORD> ( Round ( TileHeight * ScaleFactor ) );
00918 
00919         WriteData ( &Tile32, sizeof ( Tile32 ) );
00920     }
00921     else
00922     {
00923         cmxTilingBegin16 Tile16;
00924         Tile16.Width    = static_cast<WORD> ( Round ( TileWidth  * ScaleFactor ) );
00925         Tile16.Height   = static_cast<WORD> ( Round ( TileHeight * ScaleFactor ) );
00926 
00927         WriteData ( &Tile16, sizeof ( Tile16 ) );
00928     }
00929 
00930     
00931     double  dX  = static_cast<double> ( Start->x - cBBox.lo.x );
00932     double  dY  = static_cast<double> ( cBBox.hi.y - Start->y );
00933 
00934     
00935     tile.XOffset = ( static_cast<WORD> ( Round ( ( dX * 100.0 ) / TileWidth  ) ) ) % 100;
00936     tile.YOffset = ( static_cast<WORD> ( Round ( ( dY * 100.0 ) / TileHeight ) ) ) % 100;
00937 
00938     tile.InterTileOffset = tile.TilingFlags = 0;
00939 
00940     
00941     ExportFile->write(&tile, sizeof(tile));
00942     if(!EndNestedTag() || !WriteMinEndTag())
00943         return FALSE;
00944 
00945     
00946     DocRect bbox = DocRect(0, 0, cmxBITMAPFILLTILESIZE_X, cmxBITMAPFILLTILESIZE_Y);
00947 
00948     if(!WriteBBox(&bbox, FALSE))
00949         return FALSE;
00950 
00951     if(!EndNestedTag() || !WriteMinEndTag())
00952         return FALSE;
00953 
00954     return TRUE;
00955 }
00956 
00957 
00958 
00959 
00960 
00961 
00962 
00963 
00964 
00965 
00966 
00967 
00968 
00969 
00970 
00971 
00972 
00973 BOOL CMXExportDC::WritePath ( DocCoord *Coords,
00974                               PathVerb *Verbs,
00975                               INT32 NumCoords,
00976                               BOOL Filled )
00977 {
00978     
00979 
00980     
00981     
00982     BOOL ForceNoFill = TRUE;
00983     for(INT32 p = 0; p < NumCoords; p++)
00984     {
00985         if((Verbs[p] & PT_CLOSEFIGURE) != 0)
00986             ForceNoFill = FALSE;
00987     }
00988     if(!Filled)
00989         ForceNoFill = TRUE;
00990 
00991     
00992     if(!StartCommand(cmxINSTR_PolyCurve))
00993         return FALSE;
00994 
00995     
00996     if(!WriteAttributes(pRenderRegion, cmxTAG_PolyCurve_RenderingAttr, Coords, NumCoords, ForceNoFill))
00997         return FALSE;
00998 
00999     
01000     if(!StartTag(cmxTAG_PolyCurve_PointList))
01001         return FALSE;
01002 
01003     
01004     
01005     DocRect bb;             
01006     DocCoord fc = Coords[0];
01007     pMatrix->transform(&fc);
01008     bb.lo = fc;             
01009     bb.hi = fc;
01010 
01011     
01012     WORD Count = (WORD)NumCoords;
01013     ExportFile->write(&Count, sizeof(Count));
01014 
01015     
01016     INT32 l;
01017 TRACEUSER( "Ben", _T("\nPath\n"));
01018     for(l = 0; l < NumCoords; l++)
01019     {
01020         DocCoord Coord = Coords[l];
01021         pMatrix->transform(&Coord);
01022 
01023         
01024         if(ThirtyTwoBit)
01025         {
01026             cmxPoint32 p = {Coord.x, Coord.y};
01027             ExportFile->write(&p, sizeof(p));
01028         }
01029         else
01030         {
01031 TRACEUSER( "Ben", _T("Coord %d %d\n"), Coord.x, Coord.y);
01032             cmxPoint16 p = {(SWORD)Coord.x, (SWORD)Coord.y};
01033             ExportFile->write(&p, sizeof(p));
01034         }
01035 
01036         
01037         if(Coord.x < bb.lo.x) bb.lo.x = Coord.x;
01038         if(Coord.y < bb.lo.y) bb.lo.y = Coord.y;
01039         if(Coord.x > bb.hi.x) bb.hi.x = Coord.x;
01040         if(Coord.y > bb.hi.y) bb.hi.y = Coord.y;
01041     }
01042 
01043     
01044     INT32 BezCount = 0;     
01045     for(l = 0; l < NumCoords; l++)
01046     {
01047         BYTE Type;
01048 
01049         switch(Verbs[l] & (PT_LINETO | PT_MOVETO | PT_BEZIERTO))
01050         {
01051         case PT_MOVETO:
01052             {
01053                 Type = CMXNODETYPE_TYPE_MOVE | CMXNODETYPE_USER;
01054             
01055                 
01056                 for(INT32 lp = l + 1; lp < NumCoords; lp++)
01057                 {
01058                     
01059                     if((Verbs[lp] & (PT_LINETO | PT_MOVETO | PT_BEZIERTO)) == PT_MOVETO)
01060                         break;
01061 
01062                     
01063                     if((Verbs[lp] & PT_CLOSEFIGURE) != 0)
01064                     {
01065                         Type |= CMXNODETYPE_CLOSED;
01066                         break;
01067                     }
01068                 }
01069             }
01070             BezCount = 0;
01071             break;
01072 
01073         case PT_LINETO:
01074             Type = CMXNODETYPE_TYPE_LINE | CMXNODETYPE_USER;
01075             BezCount = 0;
01076             break;
01077 
01078         case PT_BEZIERTO:
01079             
01080             
01081             if(BezCount == 2)
01082             {
01083                 Type = CMXNODETYPE_TYPE_CURVE | CMXNODETYPE_USER;
01084             }
01085             else
01086             {
01087                 Type = CMXNODETYPE_TYPE_ARC;
01088             }
01089             BezCount++;
01090             if(BezCount > 2)
01091                 BezCount = 0;       
01092             break;
01093 
01094         default:
01095             ERROR3("Unknown node type");
01096             break;
01097         }
01098 
01099         if((Verbs[l] & PT_CLOSEFIGURE) != 0)
01100         {
01101             Type |= CMXNODETYPE_CLOSED;
01102         }
01103 
01104         ExportFile->write(&Type, sizeof(Type));
01105     }
01106 
01107     
01108     if(!EndTag())
01109         return FALSE;
01110 
01111     
01112     if(!StartTag(cmxTAG_PolyCurve_BoundingBox)
01113         || !WriteBBox(&bb, FALSE)
01114         || !EndTag())
01115         return FALSE;
01116 
01117     
01118     if(!WriteMinEndTag()
01119         || !EndCommand())
01120         return FALSE;
01121 
01122     
01123 
01124     return TRUE;
01125 }
01126 
01127 
01128 
01129 
01130 
01131 
01132 
01133 
01134 
01135 
01136 
01137 
01138 
01139 
01140 WORD CMXExportDC::GetColourReference(DocColour *pTheLovelyColour)
01141 {
01142     
01143     
01144     
01145     
01146 
01147     
01148     INT32 Ref = 0;
01149 
01150     
01151     CMXReferListItem *pEn = (CMXReferListItem *)ReferList.GetHead();
01152     while(pEn != 0)
01153     {
01154         ERROR3IF(!pEn->IsKindOf(CC_RUNTIME_CLASS(CMXReferListItem)), "unexpected type of entry in refer list");
01155 
01156         if(pEn->IsInWhichDesc() == cmxDESC_COLOUR)
01157         {
01158             Ref++;
01159 
01160             CMXReferColour *pLC = (CMXReferColour *)pEn;
01161             ERROR3IF(!pLC->IsKindOf(CC_RUNTIME_CLASS(CMXReferColour)), "not a refer colour, when it said it was");
01162             
01163             
01164             if(pLC->AreYouThisColour(pTheLovelyColour))
01165             {
01166                 
01167                 return Ref;
01168             }
01169         }
01170 
01171         pEn = (CMXReferListItem *)ReferList.GetNext(pEn);
01172     }
01173 
01174     
01175     CMXReferColour *pNewRefCol = new CMXReferColour(this);
01176     if(pNewRefCol == 0)
01177         return 0;
01178 
01179     pNewRefCol->SetColour(pTheLovelyColour);
01180 
01181     ReferList.AddTail(pNewRefCol);
01182 
01183     
01184     return (WORD)Ref + 1;
01185 }
01186 
01187 
01188 
01189 
01190 
01191 
01192 
01193 
01194 
01195 
01196 
01197 
01198 
01199 
01200 
01201 WORD CMXExportDC::GetArrowReference(ArrowRec *pArrow)
01202 {
01203     
01204     if(pArrow->IsNullArrow())
01205         return 0;       
01206 
01207     
01208     INT32 Ref = 0;
01209 
01210     
01211     CMXReferListItem *pEn = (CMXReferListItem *)ReferList.GetHead();
01212     while(pEn != 0)
01213     {
01214         ERROR3IF(!pEn->IsKindOf(CC_RUNTIME_CLASS(CMXReferListItem)), "unexpected type of entry in refer list");
01215 
01216         if(pEn->IsInWhichDesc() == cmxDESC_ARROW)
01217         {
01218             Ref++;
01219 
01220             CMXReferArrow *pAr = (CMXReferArrow *)pEn;
01221             ERROR3IF(!pAr->IsKindOf(CC_RUNTIME_CLASS(CMXReferArrow)), "not an arrow, when it said it was");
01222             
01223             
01224             if(pAr->AreYouThisArrow(pArrow))
01225             {
01226                 
01227                 return Ref;
01228             }
01229         }
01230 
01231         pEn = (CMXReferListItem *)ReferList.GetNext(pEn);
01232     }
01233 
01234     
01235     CMXReferArrow *pNewArrow = new CMXReferArrow(this);
01236     if(pNewArrow == 0)
01237         return 0;
01238 
01239     pNewArrow->Set(pArrow);
01240 
01241     ReferList.AddTail(pNewArrow);
01242 
01243     
01244     return (WORD)Ref + 1;
01245 }
01246 
01247 
01248 
01249 
01250 
01251 
01252 
01253 
01254 
01255 
01256 
01257 
01258 
01259 
01260 
01261 WORD CMXExportDC::GetBitmapReference(KernelBitmap *pTheLovelyBitmap, DocColour *pStartCol,
01262     DocColour *pEndCol, EFFECTTYPE Effect, CMXReferBitmap **ppRB)
01263 {
01264     
01265     INT32 Ref = 0;
01266 
01267     
01268     CMXReferListItem *pEn = (CMXReferListItem *)ReferList.GetHead();
01269     while(pEn != 0)
01270     {
01271         ERROR3IF(!pEn->IsKindOf(CC_RUNTIME_CLASS(CMXReferListItem)), "unexpected type of entry in refer list");
01272 
01273         if(pEn->IsInWhichIndex() == cmxINDEX_EMBEDFILE && IS_A(pEn, CMXReferBitmap))
01274         {
01275             Ref++;
01276 
01277             CMXReferBitmap *pBitty = (CMXReferBitmap *)pEn;
01278             
01279             
01280             if(pBitty->AreYouThisBitmap(pTheLovelyBitmap, pStartCol, pEndCol, Effect))
01281             {
01282                 
01283                 if(ppRB != 0)
01284                     (*ppRB) = pBitty;
01285 
01286                 return Ref;
01287             }
01288         }
01289 
01290         pEn = (CMXReferListItem *)ReferList.GetNext(pEn);
01291     }
01292 
01293     
01294     CMXReferBitmap *pNewRefBit = new CMXReferBitmap(this);
01295     if(pNewRefBit == 0)
01296         return 0;
01297 
01298     pNewRefBit->Set(pTheLovelyBitmap, pStartCol, pEndCol, Effect);
01299 
01300     ReferList.AddTail(pNewRefBit);
01301 
01302     
01303     if(ppRB != 0)
01304         (*ppRB) = pNewRefBit;
01305 
01306     
01307     return (WORD)Ref + 1;
01308 }
01309 
01310 
01311 
01312 
01313 
01314 
01315 
01316 
01317 
01318 
01319 
01320 
01321 
01322 
01323 BOOL CMXReferPen::WriteInDesc(CMXExportDC *pDC)
01324 {
01325     if(pDC->IsThirtyTwoBit())
01326     {
01327         
01328         if(!pDC->StartTag(cmxTAG_DescrSection_Pen))
01329             return FALSE;
01330 
01331         cmxPen32 pen;
01332 
01333         double scaledwidth = ((double)Width) * CAMCOORD_SCALEFACTOR32;
01334         pen.Width = (DWORD)scaledwidth;
01335         pen.Aspect = 100;       
01336         pen.Angle = 0;
01337         pDC->WriteData(&pen, sizeof(pen));
01338 
01339         
01340         if(!pDC->WriteMatrix())
01341             return FALSE;
01342 
01343         
01344         if(!pDC->EndTag()
01345             || !pDC->WriteMinEndTag())
01346             return FALSE;
01347     }
01348     else
01349     {
01350         cmxPen16 pen;
01351 
01352         double scaledwidth = ((double)Width) * pDC->GetScaleFactor();
01353         pen.Width = (WORD)scaledwidth;
01354         pen.Aspect = 100;       
01355         pen.Angle = 0;
01356         pDC->WriteData(&pen, sizeof(pen));
01357 
01358         
01359         if(!pDC->WriteMatrix())
01360             return FALSE;
01361     }
01362 
01363     return TRUE;
01364 }
01365 
01366 
01367 
01368 
01369 
01370 
01371 
01372 
01373 
01374 
01375 
01376 
01377 
01378 
01379 BOOL CMXReferArrowheads::WriteInDesc(CMXExportDC *pDC)
01380 {
01381     struct {
01382         WORD Start,End;
01383     } en = {Start, End};
01384 
01385     return pDC->WriteData(&en, sizeof(en));
01386 }
01387 
01388 
01389 
01390 
01391 
01392 
01393 
01394 
01395 
01396 
01397 
01398 
01399 
01400 
01401 BOOL CMXReferLineStyle::WriteInDesc(CMXExportDC *pDC)
01402 {
01403     if(!pDC->WriteTag(cmxTAG_DescrSection_LineStyle, &LineStyle, sizeof(LineStyle))
01404         || !pDC->WriteMinEndTag())
01405         return FALSE;
01406 
01407     return TRUE;
01408 }
01409 
01410 
01411 
01412 
01413 
01414 
01415 
01416 
01417 
01418 
01419 
01420 
01421 
01422 
01423 BOOL CMXReferLineStyle::AreYouThisStyle(cmxLineStyle *pLineStyle)
01424 {
01425     
01426     
01427     if(memcmp(&LineStyle, pLineStyle, sizeof(cmxLineStyle)) == 0)
01428     {
01429         
01430         return TRUE;
01431     }
01432     
01433     
01434     return FALSE;
01435 }
01436 
01437 
01438 
01439 
01440 
01441 
01442 
01443 
01444 
01445 
01446 
01447 
01448 
01449 
01450 BOOL CMXReferOutline::WriteInDesc(CMXExportDC *pDC)
01451 {
01452     if(!pDC->WriteTag(cmxTAG_DescrSection_Outline, &Outline, sizeof(Outline))
01453         || !pDC->WriteMinEndTag())
01454         return FALSE;
01455 
01456     return TRUE;
01457 }
01458 
01459 
01460 
01461 
01462 
01463 
01464 
01465 
01466 
01467 
01468 
01469 
01470 
01471 
01472 BOOL CMXReferOutline::AreYouThisOutline(cmxOutline *pOutline)
01473 {
01474     
01475     
01476     if(memcmp(&Outline, pOutline, sizeof(cmxOutline)) == 0)
01477     {
01478         
01479         return TRUE;
01480     }
01481     
01482     
01483     return FALSE;
01484 }
01485 
01486 
01487 
01488 
01489 
01490 
01491 
01492 
01493 
01494 
01495 
01496 
01497 
01498 
01499 BOOL CMXExportDC::WriteOutlineSpec(CMXRenderRegion *pReg)
01500 {
01501     
01502     
01503     
01504     
01505     
01506     
01507     
01508     
01509     
01510 
01511     
01512     MILLIPOINT Width;
01513     
01514     LineWidthAttribute *pLineWidthA
01515             = (LineWidthAttribute *)pReg->GetCurrentAttribute(ATTR_LINEWIDTH);
01516 
01517     
01518     ERROR2IF(pLineWidthA == 0, FALSE, "No line width attribute");
01519     ERROR3IF(!pLineWidthA->IsKindOf(CC_RUNTIME_CLASS(LineWidthAttribute)), "not a line width attribute");
01520 
01521     Width = pLineWidthA->LineWidth;
01522 
01523     
01524     DocColour *pColour;
01525     
01526     StrokeColourAttribute *pColA
01527             = (StrokeColourAttribute *)pReg->GetCurrentAttribute(ATTR_STROKECOLOUR);
01528     
01529     ERROR2IF(pColA == 0, FALSE, "No stroke colour attribute");
01530     ERROR3IF(!pColA->IsKindOf(CC_RUNTIME_CLASS(StrokeColourAttribute)), "not a stroke colour attribute");
01531 
01532     pColour = pColA->GetStartColour();
01533 
01534     
01535     BOOL TransparentLine = FALSE;
01536     WORD ColRef;
01537     if(pColour->IsTransparent())
01538     {
01539         TransparentLine = TRUE;
01540         Width = 0;                  
01541     }
01542     else
01543         ColRef = GetColourReference(pColour);
01544 
01545     
01546     cmxLineStyle LineStyle;
01547     LineStyle.Spec = TransparentLine?cmxLINESPEC_NONE:0;
01548     LineStyle.CapAndJoin = 0;
01549 
01550     
01551     
01552     JoinTypeAttribute *pJTA
01553             = (JoinTypeAttribute *)pReg->GetCurrentAttribute(ATTR_JOINTYPE);
01554     
01555     ERROR2IF(pJTA == 0, FALSE, "No join type attribute");
01556     ERROR3IF(!pJTA->IsKindOf(CC_RUNTIME_CLASS(JoinTypeAttribute)), "not a join type attribute");
01557     
01558     switch(pJTA->JoinType)
01559     {
01560         case RoundJoin: LineStyle.CapAndJoin |= cmxCAPJOIN_ROUNDJOIN; break;
01561         case BevelledJoin: LineStyle.CapAndJoin |= cmxCAPJOIN_BEVELJOIN; break;
01562         default: break;
01563     }
01564 
01565     
01566     
01567     StartCapAttribute *pSCA
01568             = (StartCapAttribute *)pReg->GetCurrentAttribute(ATTR_STARTCAP);
01569     
01570     ERROR2IF(pSCA == 0, FALSE, "No start cap attribute");
01571     ERROR3IF(!pSCA->IsKindOf(CC_RUNTIME_CLASS(StartCapAttribute)), "not a start cap attribute");
01572     
01573     switch(pSCA->StartCap)
01574     {
01575         case LineCapRound: LineStyle.CapAndJoin |= cmxCAPJOIN_ROUNDCAP; break;
01576         case LineCapSquare: LineStyle.CapAndJoin |= cmxCAPJOIN_SQUARECAP; break;
01577         default: break;
01578     }
01579 
01580     
01581     DashRec *pDash;
01582     DashPatternAttribute *pDas
01583             = (DashPatternAttribute *)pReg->GetCurrentAttribute(ATTR_DASHPATTERN);
01584     
01585     ERROR2IF(pDas == 0, FALSE, "No dash pattern attribute");
01586     ERROR3IF(!pDas->IsKindOf(CC_RUNTIME_CLASS(DashPatternAttribute)), "not a dash pattern attribute");
01587     
01588     pDash = &pDas->DashPattern;
01589 
01590     if(pDash->Elements != 0)
01591         LineStyle.Spec |= cmxLINESPEC_DOTDASH;
01592     else
01593         LineStyle.Spec |= cmxLINESPEC_SOLIDOUTLINE;
01594     
01595     
01596     EndArrowAttribute *pEa
01597             = (EndArrowAttribute *)pReg->GetCurrentAttribute(ATTR_ENDARROW);
01598     
01599     ERROR2IF(pEa == 0, FALSE, "No arrow attribute");
01600     ERROR3IF(!pEa->IsKindOf(CC_RUNTIME_CLASS(EndArrowAttribute)), "not a arrow attribute");
01601     StartArrowAttribute *pSa
01602             = (StartArrowAttribute *)pReg->GetCurrentAttribute(ATTR_STARTARROW);
01603     
01604     ERROR2IF(pSa == 0, FALSE, "No arrow attribute");
01605     ERROR3IF(!pSa->IsKindOf(CC_RUNTIME_CLASS(StartArrowAttribute)), "not a arrow attribute");
01606 
01607     
01608     WORD StartArrow = GetArrowReference(&pSa->StartArrow);
01609     WORD EndArrow = GetArrowReference(&pEa->EndArrow);
01610 
01611     
01612     BOOL FoundPen = FALSE;          
01613     WORD PenRef = 0;                
01614     BOOL FoundLineStyle = FALSE;
01615     WORD LineStyleRef = 0;
01616     BOOL FoundArrowheads = FALSE;
01617     WORD ArrowheadsRef = 0;
01618     BOOL FoundDotDash = FALSE;
01619     WORD DotDashRef = 0;
01620 
01621     WORD LastOutlineRef = 0;        
01622 
01623     CMXReferListItem *pEn = (CMXReferListItem *)ReferList.GetHead();
01624     while(pEn != 0)
01625     {
01626         ERROR3IF(!pEn->IsKindOf(CC_RUNTIME_CLASS(CMXReferListItem)), "unexpected type of entry in refer list");
01627 
01628         switch(pEn->IsInWhichDesc())
01629         {
01630 
01631         case cmxDESC_PEN:
01632             if(!FoundPen)
01633             {
01634                 PenRef++;
01635 
01636                 CMXReferPen *pPen = (CMXReferPen *)pEn;
01637                 ERROR3IF(!pPen->IsKindOf(CC_RUNTIME_CLASS(CMXReferPen)), "not a refer pen, when it said it was");
01638                 
01639                 
01640                 if(pPen->AreYouThisWidth(Width))
01641                 {
01642                     
01643                     FoundPen = TRUE;
01644                 }
01645             }
01646             break;
01647 
01648         case cmxDESC_LINESTYLE:
01649             if(!FoundLineStyle)
01650             {
01651                 LineStyleRef++;
01652 
01653                 CMXReferLineStyle *pSt = (CMXReferLineStyle *)pEn;
01654                 ERROR3IF(!pSt->IsKindOf(CC_RUNTIME_CLASS(CMXReferLineStyle)), "not a refer LineStyle, when it said it was");
01655                 
01656                 
01657                 if(pSt->AreYouThisStyle(&LineStyle))
01658                 {
01659                     
01660                     FoundLineStyle = TRUE;
01661                 }
01662             }
01663             break;
01664 
01665         case cmxDESC_ARROWHEADS:
01666             if(!FoundArrowheads)
01667             {
01668                 ArrowheadsRef++;
01669 
01670                 CMXReferArrowheads *pAh = (CMXReferArrowheads *)pEn;
01671                 ERROR3IF(!pAh->IsKindOf(CC_RUNTIME_CLASS(CMXReferArrowheads)), "not a arrowheads, when it said it was");
01672                 
01673                 
01674                 if(pAh->AreYouThisArrowheads(StartArrow, EndArrow))
01675                 {
01676                     
01677                     FoundArrowheads = TRUE;
01678                 }
01679             }
01680             break;
01681 
01682         case cmxDESC_DOTDASH:
01683             if(!FoundDotDash)
01684             {
01685                 DotDashRef++;
01686 
01687                 CMXReferDotDash *pDd = (CMXReferDotDash *)pEn;
01688                 ERROR3IF(!pDd->IsKindOf(CC_RUNTIME_CLASS(CMXReferDotDash)), "not a refer dot dash, when it said it was");
01689                 
01690                 
01691                 if(pDd->AreYouThisDotDash(pDash))
01692                 {
01693                     
01694                     FoundDotDash = TRUE;
01695                 }
01696             }
01697             break;
01698 
01699         case cmxDESC_OUTLINE:
01700             LastOutlineRef++;       
01701             break;
01702 
01703         default:
01704             
01705             break;
01706         }
01707 
01708         pEn = (CMXReferListItem *)ReferList.GetNext(pEn);
01709     }
01710 
01711     
01712     BOOL NewReferObjectCreated = FALSE;     
01713 
01714     if(!FoundPen)
01715     {
01716         NewReferObjectCreated = TRUE;
01717         
01718         CMXReferPen *pPen = new CMXReferPen(this);
01719         if(pPen == NULL)
01720             return FALSE;
01721 
01722         pPen->SetWidth(Width);
01723         PenRef++;               
01724 
01725         ReferList.AddTail(pPen);
01726     }
01727 
01728     if(!FoundLineStyle)
01729     {
01730         NewReferObjectCreated = TRUE;
01731         
01732         CMXReferLineStyle *pLs = new CMXReferLineStyle(this);
01733         if(pLs == NULL)
01734             return FALSE;
01735 
01736         pLs->SetLineStyle(&LineStyle);
01737         LineStyleRef++;             
01738 
01739         ReferList.AddTail(pLs);
01740     }
01741 
01742     if(!FoundArrowheads)
01743     {
01744         NewReferObjectCreated = TRUE;
01745         
01746         CMXReferArrowheads *pAh = new CMXReferArrowheads(this);
01747         if(pAh == NULL)
01748             return FALSE;
01749 
01750         pAh->SetArrowheads(StartArrow, EndArrow);
01751         ArrowheadsRef++;                
01752 
01753         ReferList.AddTail(pAh);
01754     }
01755 
01756     if(!FoundDotDash)
01757     {
01758         NewReferObjectCreated = TRUE;
01759         
01760         CMXReferDotDash *pDd = new CMXReferDotDash(this);
01761         if(pDd == NULL)
01762             return FALSE;
01763 
01764         pDd->Set(pDash);
01765         DotDashRef++;               
01766 
01767         ReferList.AddTail(pDd);
01768     }
01769 
01770     
01771     cmxOutline Outline;
01772     memset(&Outline, 0, sizeof(Outline));
01773 
01774     Outline.LineStyle = LineStyleRef;
01775     Outline.Screen = cmxSCREENREFERENCE;
01776     if(TransparentLine)
01777         Outline.Colour = 1;     
01778     else
01779         Outline.Colour = ColRef;
01780     Outline.Arrowheads = ArrowheadsRef;
01781     Outline.Pen = PenRef;
01782     Outline.DotDash = DotDashRef;
01783 
01784     
01785     BOOL FoundOutline = FALSE;
01786     WORD OutlineRef = 0;
01787     if(NewReferObjectCreated == FALSE) 
01788     {
01789         CMXReferListItem *pEn = (CMXReferListItem *)ReferList.GetHead();
01790         while(pEn != 0)
01791         {
01792             ERROR3IF(!pEn->IsKindOf(CC_RUNTIME_CLASS(CMXReferListItem)), "unexpected type of entry in refer list");
01793 
01794             if(pEn->IsInWhichDesc() == cmxDESC_OUTLINE)
01795             {
01796                 OutlineRef++;
01797 
01798                 CMXReferOutline *pLC = (CMXReferOutline *)pEn;
01799                 ERROR3IF(!pLC->IsKindOf(CC_RUNTIME_CLASS(CMXReferOutline)), "not a refer outline, when it said it was");
01800                 
01801                 
01802                 if(pLC->AreYouThisOutline(&Outline))
01803                 {
01804                     FoundOutline = TRUE;
01805                     break;
01806                 }
01807             }
01808 
01809             pEn = (CMXReferListItem *)ReferList.GetNext(pEn);
01810         }
01811     }
01812 
01813     
01814     if(FoundOutline == FALSE)
01815     {
01816         OutlineRef = LastOutlineRef + 1;
01817 
01818         
01819         CMXReferOutline *pOlt = new CMXReferOutline(this);
01820         if(pOlt == NULL)
01821             return FALSE;
01822 
01823         
01824         pOlt->SetOutline(&Outline);
01825 
01826         
01827         ReferList.AddTail(pOlt);
01828     }
01829 
01830     
01831     if(!WriteNestedTag(cmxTAG_RenderAttr_OutlineSpec, &OutlineRef, sizeof(OutlineRef)))
01832         return FALSE;
01833 
01834     
01835     if(!WriteMinEndTag())
01836         return FALSE;
01837 
01838     return TRUE;
01839 }
01840 
01841 
01842 
01843 
01844 
01845 
01846 
01847 
01848 
01849 
01850 
01851 
01852 
01853 
01854 
01855 void CMXExportDC::CalcCorelBBox(DocCoord *Coords, INT32 NumCoords, DocRect *Result)
01856 {
01857     ERROR3IF(Coords == NULL || NumCoords < 1, "dodgy coords");
01858 
01859     
01860     Result->lo = Coords[0];
01861     Result->hi = Coords[0];
01862 
01863     
01864     for(INT32 l = 1; l < NumCoords; l++)
01865     {
01866         if(Result->lo.x > Coords[l].x) Result->lo.x = Coords[l].x;
01867         if(Result->lo.y > Coords[l].y) Result->lo.y = Coords[l].y;
01868         if(Result->hi.x < Coords[l].x) Result->hi.x = Coords[l].x;
01869         if(Result->hi.y < Coords[l].y) Result->hi.y = Coords[l].y;
01870     }
01871 
01872     
01873 }
01874 
01875 
01876 
01877 
01878 
01879 
01880 
01881 
01882 
01883 
01884 
01885 
01886 
01887 
01888 
01889 
01890 WORD CMXExportDC::GetProcedureReference(CMXReferListItem *pProc)
01891 {
01892     ERROR3IF(!pProc->IsAProcedure(), "item is not a procedure");
01893 
01894     
01895     WORD Ref = 0;
01896     CMXReferListItem *pEn = (CMXReferListItem *)ReferList.GetHead();
01897     while(pEn != 0)
01898     {
01899         ERROR3IF(!pEn->IsKindOf(CC_RUNTIME_CLASS(CMXReferListItem)), "unexpected type of entry in refer list");
01900 
01901         if(pEn->IsAProcedure())
01902         {
01903             
01904             Ref++;
01905 
01906             
01907             if(pEn == pProc)
01908                 return Ref;
01909         }
01910 
01911         pEn = (CMXReferListItem *)ReferList.GetNext(pEn);
01912     }
01913 
01914     return 1;       
01915 }
01916 
01917 
01918 
01919 
01920 
01921 
01922 
01923 
01924 
01925 
01926 
01927 
01928 
01929 
01930 
01931 
01932 BOOL CMXExportDC::WriteAttrCheckLens(CMXRenderRegion *pReg, INT32 Tag, DocCoord *Coords, INT32 NumCoords, BOOL *WasLens)
01933 {
01934     
01935     *WasLens = FALSE;
01936 
01937     
01938     TranspFillAttribute *pTra =
01939         (TranspFillAttribute *)pReg->GetCurrentAttribute(ATTR_TRANSPFILLGEOMETRY);
01940     
01941     if(pTra == NULL)
01942     {
01943         TRACEUSER( "Ben", _T("No transparent fill attribute -- assuming it's not transparent\n"));
01944         return TRUE;
01945     }
01946     ERROR3IF(!pTra->IsKindOf(CC_RUNTIME_CLASS(TranspFillAttribute)), "not a transparent fill attribute");
01947 
01948     
01949     UINT32 TransparencyValue = 0;
01950     if(pTra->IsAFlatFill())
01951     {
01952         TransparencyValue = *pTra->GetStartTransp();
01953     }
01954     else
01955     {
01956         
01957         TransparencyValue = (*pTra->GetStartTransp() + *pTra->GetEndTransp()) / 2;
01958     }
01959 
01960     
01961     if (TransparencyValue == 0)
01962         return TRUE;            
01963 
01964     TRACEUSER( "Ben", _T("transparent, has value %d\n"), TransparencyValue);
01965 
01966     
01967     if(WriteAttrCheckIgnoreLens(pReg, Coords, NumCoords))
01968     {
01969         
01970         return TRUE;
01971     }
01972 
01973     
01974     WORD UniformRate = 1000 - ((TransparencyValue * 1000) / 255);   
01975 
01976     
01977     WORD ColourReference = 1;       
01978 
01979     
01980     FillGeometryAttribute *pFillGeometry
01981             = (FillGeometryAttribute *)pReg->GetCurrentAttribute(ATTR_FILLGEOMETRY);
01982 
01983     
01984     ERROR2IF(pFillGeometry == 0, FALSE, "No fill geometry");
01985     ERROR3IF(!pFillGeometry->IsKindOf(CC_RUNTIME_CLASS(FillGeometryAttribute)), "not one of them there fill geometries");
01986 
01987     
01988     DocColour *pColour = pFillGeometry->GetStartColour();
01989 
01990     if(pColour != 0 && !pColour->IsTransparent())
01991     {
01992         
01993         ColourReference = GetColourReference(pColour);
01994     }
01995 
01996     
01997     CMXReferLens *pLens = new CMXReferLens(this);
01998     if(pLens == NULL)
01999         return FALSE;
02000 
02001     
02002     DocRect bb;
02003     CalcCorelBBox(Coords, NumCoords, &bb);
02004 
02005     
02006     if(!pLens->Set(this, &bb))
02007         return FALSE;
02008 
02009     
02010     ReferList.AddTail(pLens);
02011 
02012     
02013     
02014     if(Tag != -1)
02015         if(!StartTag(Tag))
02016             return FALSE;
02017 
02018     
02019     WriteByte(cmxRENDATTRMASK_FILL | cmxRENDATTRMASK_OUTLINE | cmxRENDATTRMASK_LENS);
02020 
02021     
02022     if(!StartNestedTag(cmxTAG_RenderAttr_FillSpec)
02023         ||!WriteFillType(cmxFILLID_UNIFORM))
02024         return FALSE;
02025     struct {
02026         WORD FillReference;
02027         WORD ScreenReference;
02028     } filldef = {ColourReference, cmxSCREENREFERENCE};
02029     if(!WriteNestedTag(cmxTAG_RenderAttr_FillSpec_Uniform, &filldef, sizeof(filldef))
02030         || !WriteMinEndTag()
02031         || !EndNestedTag()
02032         || !WriteMinEndTag())
02033         return FALSE;
02034 
02035     
02036     if(!WriteOutlineSpec(pReg))
02037         return FALSE;
02038 
02039     
02040     cmxGlassLensDefn lendef;
02041     lendef.LensType = cmxLENSTYPE_GLASS;
02042 
02043     switch(pTra->GetTranspType())
02044     {
02045         default:            lendef.TintMethod = cmxLENSTINTMETH_AVERAGE;    break;
02046         case TT_StainGlass: lendef.TintMethod = cmxLENSTINTMETH_SUBTRACT;   break;
02047         case TT_Bleach:     lendef.TintMethod = cmxLENSTINTMETH_ADD;        break;
02048     }
02049     lendef.UniformRate = UniformRate;
02050     lendef.ColourReference = ColourReference;
02051     lendef.RangeProcReference = GetProcedureReference(pLens);
02052 
02053     if(!WriteNestedTag(cmxTAG_RenderAttr_LensSpec_Base, &lendef, sizeof(lendef)))
02054         return FALSE;
02055 
02056     if(ThirtyTwoBit)
02057     {
02058         cmxLensFrozView fv;         
02059         fv.FlagFrozen = 0;
02060         fv.FlagActive = 0;
02061         fv.ViewPointX = 0;
02062         fv.ViewPointY = 0;
02063 
02064         if(!WriteNestedTag(cmxTAG_RenderAttr_LensSpec_FrozViewp, &fv, sizeof(fv))
02065             || !WriteMinEndTag())
02066             return FALSE;
02067     }
02068 
02069     
02070     if(Tag != -1)
02071         if(!EndTag())
02072             return FALSE;
02073 
02074     
02075     *WasLens = TRUE;
02076 
02077     
02078     SetCMXFlag(cmxSTRUCTFLAGS_HASLENS);
02079 
02080     return TRUE;
02081 }
02082 
02083 
02084 
02085 
02086 
02087 
02088 
02089 
02090 
02091 
02092 
02093 
02094 
02095 
02096 
02097 
02098 
02099 BOOL CMXExportDC::WriteAttrCheckIgnoreLens(CMXRenderRegion *pReg, DocCoord *Coords, INT32 NumCoords)
02100 {
02101     
02102     DocRect BBox;
02103     CalcCorelBBox(Coords, NumCoords, &BBox);
02104 
02105     
02106     INT32 LensesBehindThisOne = 0;
02107     CMXLensBBox *pEn = (CMXLensBBox *)LensBBoxes.GetHead();
02108     while(pEn != 0)
02109     {
02110         
02111         if(pEn->DoesIntersect(&BBox))
02112             LensesBehindThisOne++;
02113 
02114         
02115         pEn = (CMXLensBBox *)LensBBoxes.GetNext(pEn);
02116     }
02117 
02118     
02119     CMXLensBBox *pNewLensBBox = new CMXLensBBox(&BBox);
02120     if(pNewLensBBox != NULL)
02121         LensBBoxes.AddTail(pNewLensBBox);
02122 
02123     
02124     if(LensesBehindThisOne > CMX_MAX_OVERLAP_LENSES)
02125     {
02126         TRACEUSER( "Ben", _T("found transparency to ignore, %d lenses behind\n"), LensesBehindThisOne);
02127         
02128         if(!AreIgnoreingOverlappedLenses && !HaveAskedUserAboutLenses)
02129         {
02130             HaveAskedUserAboutLenses = TRUE;
02131 
02132             INT32 Result = InformWarning(_R(IDW_CMXOVERLAPPEDLENS), _R(IDB_CMXDOLENSES), _R(IDB_CMXIGNORELENSES), 0, 0, 2, 1);
02133 
02134             switch(Result)
02135             {
02136             case 1: 
02137                 AreIgnoreingOverlappedLenses = FALSE;
02138                 break;
02139 
02140             case 2: 
02141             default:
02142                 AreIgnoreingOverlappedLenses = TRUE;
02143                 break;
02144             }
02145         }
02146 
02147         
02148         if(AreIgnoreingOverlappedLenses)
02149         {
02150             
02151             OverlappedLensesHaveBeenIgnored = TRUE;
02152 
02153             return TRUE;        
02154         }
02155     }
02156 
02157     return FALSE;       
02158 }
02159 
02160 
02161 
02162 
02163 
02164 
02165 
02166 
02167 
02168 
02169 
02170 
02171 
02172 
02173 BOOL CMXReferLens::Set(CMXExportDC *pDC, DocRect *tBBox)
02174 {
02175     
02176     BBox = *tBBox;
02177 
02178     
02179     CommandFilePosition = pDC->GetCurrentInstrFilePosition();
02180 
02181     
02182     LayerNumber = pDC->GetLayerNumber();
02183     
02184     return TRUE;
02185 }
02186 
02187 
02188 
02189 
02190 
02191 
02192 
02193 
02194 
02195 
02196 
02197 
02198 
02199 
02200 BOOL CMXReferLens::WriteSection(CMXExportDC *pDC)
02201 {
02202     
02203     LensDescFilePosition = pDC->GetFilePosition();
02204 
02205     
02206     if(!pDC->StartSection(CMXExportDC::CMXSECTION_LENS))
02207         return FALSE;
02208 
02209     
02210     cmxLensDescriptionSection len;
02211     len.ParentType = cmxREFLISTEN_TYPE_LAYER;
02212     len.Page = 1;
02213     len.ParentReference = LayerNumber;
02214     len.StartAddress = pDC->GetFirstInstrFilePosition();
02215     len.EndAddress = CommandFilePosition;
02216     pDC->WriteData(&len, sizeof(len));
02217 
02218     
02219     Matrix *pMat = pDC->GetTransMatrix();
02220     DocRect b = BBox;
02221     pMat->TransformBounds(&b);
02222     if(!pDC->WriteBBox(&b))
02223         return FALSE;
02224 
02225     
02226     if(!pDC->EndSection())
02227         return FALSE;
02228 
02229     return TRUE;
02230 }
02231 
02232 
02233 
02234 
02235 
02236 
02237 
02238 
02239 
02240 
02241 
02242 
02243 
02244 
02245 
02246 
02247 BOOL CMXReferLens::WriteInReferenceList(CMXExportDC *pDC)
02248 {
02249     ERROR2IF(pDC == 0, FALSE, "no DC");
02250 
02251     
02252     cmxRefListEntryRefOffset en;
02253     memset(&en, '\0', sizeof(en));
02254 
02255     en.Association = cmxREFLISTEN_DESC_LENS;
02256     en.Type = cmxREFLISTEN_TYPE_INSTRUCTION;
02257     en.Offset = CommandFilePosition;
02258 
02259     pDC->WriteData(&en, sizeof(en));
02260 
02261     return TRUE;
02262 }
02263 
02264 
02265 
02266 
02267 
02268 
02269 
02270 
02271 
02272 
02273 
02274 
02275 
02276 
02277 
02278 BOOL CMXReferLens::WriteInIndex(CMXExportDC *pDC)
02279 {
02280     
02281     cmxProcIndexEntry en;
02282     pDC->WriteSizeInFile(sizeof(en));
02283     en.RefList = -1;
02284     en.Procedure = LensDescFilePosition;
02285 
02286     return pDC->WriteData(&en, sizeof(en));
02287 }
02288 
02289 
02290 
02291 
02292 
02293 
02294 
02295 
02296 
02297 
02298 
02299 
02300 
02301 
02302 
02303 BOOL CMXReferBitmapFill::WriteInIndex(CMXExportDC *pDC)
02304 {
02305     
02306     cmxProcIndexEntry en;
02307     pDC->WriteSizeInFile(sizeof(en));
02308     en.RefList = -1;
02309     en.Procedure = ProcedureFilePosition;
02310 
02311     return pDC->WriteData(&en, sizeof(en));
02312 }
02313 
02314 
02315 
02316 
02317 
02318 
02319 
02320 
02321 
02322 
02323 
02324 
02325 
02326 
02327 
02328 BOOL CMXReferBitmap::WriteInIndex(CMXExportDC *pDC)
02329 {
02330     cmxEmbedFileIndexEntry en;
02331     pDC->WriteSizeInFile(sizeof(en));
02332     en.Offset = BitmapFileOffset;
02333     en.Type = cmxEMBEDFILETYPE_RIMAGE;
02334 
02335     return pDC->WriteData(&en, sizeof(en));
02336 }
02337 
02338 
02339 
02340 
02341 
02342 
02343 
02344 
02345 
02346 
02347 
02348 
02349 
02350 
02351 
02352 BOOL CMXReferBitmap::WriteSection(CMXExportDC *pDC)
02353 {
02354     
02355     
02356     KernelBitmap *pBitmap = Ref.GetBitmap();
02357     ERROR2IF(pBitmap == NULL, FALSE, "no bitmap in ref");
02358     OILBitmap *bit = pBitmap->ActualBitmap;
02359     ERROR2IF(bit == NULL, FALSE, "kernel bitmap didn't have a oil bitmap");
02360 
02361     
02362     BitmapFileOffset = pDC->GetFilePosition();
02363 
02364     
02365     if(Contone)
02366     {
02367         
02368         View *pView = NULL;
02369         if (pDC->GetRenderRegion()!=NULL)
02370             pView=pDC->GetRenderRegion()->GetRenderView();
02371 
02372         
02373         if (!bit->BuildContonePalette(StartColour, EndColour, Effect, pView))
02374             return FALSE;
02375 
02376         
02377         pDC->GetRenderRegion()->SetAreExportingContoneBitmap(TRUE);
02378     }
02379     else
02380     {
02381         
02382         pDC->GetRenderRegion()->SetAreExportingContoneBitmap(FALSE);
02383     }
02384 
02385     
02386     if(!bit->ExportBitmap(pDC->GetRenderRegion()))
02387         return FALSE;
02388 
02389     if(Contone)
02390     {
02391         
02392         bit->DestroyContonePalette();
02393     }
02394 
02395     return TRUE;
02396 }
02397 
02398 
02399 
02400 
02401 
02402 
02403 
02404 
02405 
02406 
02407 
02408 
02409 
02410 
02411 
02412 BOOL CMXReferBitmapFill::WriteSection(CMXExportDC *pDC)
02413 {
02414     
02415     ProcedureFilePosition = pDC->GetFilePosition();
02416 
02417     
02418     if(!pDC->StartSection(CMXExportDC::CMXSECTION_PROCBITFILL))
02419         return FALSE;
02420 
02421     
02422     DocRect bbox = DocRect(0, 0, cmxBITMAPFILLTILESIZE_X, cmxBITMAPFILLTILESIZE_Y);
02423 
02424     
02425     if(!pDC->StartPage(&bbox, TRUE))
02426         return FALSE;
02427 
02428     
02429     DocCoord Paral[4] =             
02430         {   DocCoord(0, cmxBITMAPFILLTILESIZE_Y),
02431             DocCoord(cmxBITMAPFILLTILESIZE_X, cmxBITMAPFILLTILESIZE_Y),
02432             DocCoord(cmxBITMAPFILLTILESIZE_X, 0),
02433             DocCoord(0, 0)
02434         };
02435 
02436     if ( !pDC->WriteBitmap ( 0, Paral, CMXExportDC::CMXBITMAPCOLOURSOURCE_NONE,
02437                              FALSE, BitmapReference ) )
02438         return FALSE;
02439 
02440     
02441     if(!pDC->EndPage())
02442         return FALSE;
02443 
02444     
02445     if(!pDC->EndSection())
02446         return FALSE;
02447 
02448     return TRUE;
02449 }
02450 
02451 
02452 
02453 
02454 
02455 
02456 
02457 
02458 
02459 
02460 
02461 
02462 
02463 
02464 
02465 
02466 
02467 
02468 
02469 BOOL CMXExportDC::WriteBitmap ( KernelBitmap            *pBitmap,
02470                                 DocCoord                *pParallelogram,
02471                                 CMXBitmapColourSource   ColSource,
02472                                 BOOL                    TransformParallelogram,
02473                                 WORD                    BitmapReference )
02474 {
02475     
02476     DocColour *pStartColour = 0;
02477     DocColour *pEndColour = 0;
02478     EFFECTTYPE Effect = EFFECT_RGB;
02479 
02480     
02481     switch(ColSource)
02482     {
02483     case CMXBITMAPCOLOURSOURCE_FILLGEOMETRY:
02484         ERROR2(FALSE, "fill geometry bitmap colour source not implemented");
02485         break;
02486 
02487     case CMXBITMAPCOLOURSOURCE_LINEANDFILL:
02488         {
02489         
02490         
02491         StrokeColourAttribute *pColA
02492                 = (StrokeColourAttribute *)pRenderRegion->GetCurrentAttribute(ATTR_STROKECOLOUR);
02493         
02494         ERROR2IF(pColA == 0, FALSE, "No stroke colour attribute");
02495         ERROR3IF(!pColA->IsKindOf(CC_RUNTIME_CLASS(StrokeColourAttribute)), "not a stroke colour attribute");
02496         pStartColour = pColA->GetStartColour();
02497         
02498         if(pStartColour != 0 && pStartColour->IsTransparent())
02499             pStartColour = 0;
02500 
02501         
02502         if(pStartColour != 0)
02503         {
02504             
02505             FillGeometryAttribute *pFillGeometry
02506                     = (FillGeometryAttribute *)pRenderRegion->GetCurrentAttribute(ATTR_FILLGEOMETRY);
02507             
02508             ERROR2IF(pFillGeometry == 0, FALSE, "No fill geometry");
02509             ERROR3IF(!pFillGeometry->IsKindOf(CC_RUNTIME_CLASS(FillGeometryAttribute)), "not one of them there fill geometries");
02510 
02511             
02512             pEndColour = pFillGeometry->GetStartColour();
02513 
02514             if(pEndColour == NULL || pEndColour->IsTransparent())
02515             {
02516                 
02517                 pStartColour = 0;
02518                 pEndColour = 0;
02519             }
02520             else
02521             {
02522                 
02523                 Effect = pRenderRegion->GetFillEffect();
02524             }
02525         }
02526         }
02527         break;
02528 
02529     default:
02530     case CMXBITMAPCOLOURSOURCE_NONE:
02531         break;      
02532     }
02533 
02534     
02535     WORD BitmapRef = 0;
02536     if(pBitmap == 0)
02537     {
02538         BitmapRef = BitmapReference;
02539     }
02540     else
02541     {
02542         BitmapRef = GetBitmapReference(pBitmap, pStartColour, pEndColour, Effect);
02543     }
02544     if(BitmapRef == 0)
02545         return TRUE;            
02546 
02547     
02548     DocCoord Para[4];
02549     ERROR2IF(pMatrix == NULL, FALSE, "no matrix");
02550     for(INT32 z = 0; z < (sizeof(Para) / sizeof(DocCoord)); z++)
02551     {
02552         Para[z] = pParallelogram[z];
02553         if(TransformParallelogram)
02554             pMatrix->transform(&(Para[z]));
02555     }
02556 
02557     
02558     if(!StartCommand(cmxINSTR_DrawImage))
02559         return FALSE;
02560 
02561     
02562     if(!WriteBlankAttributes(cmxTAG_DrawImage_RenderingAttr))
02563         return FALSE;
02564 
02565     
02566     if(!StartTag(cmxTAG_DrawImage_DrawImageSpecification))
02567         return FALSE;
02568 
02569     
02570     DocRect ImEx;
02571     if(ThirtyTwoBit)
02572     {
02573         ImEx.lo.x = ImEx.lo.y = 0;
02574         ImEx.hi.x = 2048;
02575         ImEx.hi.y = 2048;
02576     }
02577     else
02578     {
02579         ImEx.lo.x = 0;
02580         ImEx.lo.y = -2048;
02581         ImEx.hi.x = 2048;
02582         ImEx.hi.y = 0;
02583     }
02584     if(!WriteBBox(&ImEx, FALSE) ||
02585         !WriteBBox(&ImEx, FALSE))
02586         return FALSE;
02587 
02588     
02589     double magX = 2048.0;
02590     double magY = 2048.0;
02591     cmxMatrix Matrix = {cmxMATRIXTYPE_GENERAL,
02592         (double)(Para[2].x - Para[3].x) / magX,
02593         (double)(Para[2].y - Para[3].y) / magY,
02594         (double)(Para[0].x - Para[3].x) / magX,
02595         (double)(Para[0].y - Para[3].y) / magY,
02596         Para[3].x,
02597         Para[3].y};
02598 
02599     if(!ThirtyTwoBit)
02600     {
02601         
02602         Matrix.f += Matrix.d * 2048;
02603     }
02604 
02605     
02606     ExportFile->write(&Matrix, sizeof(Matrix));
02607 
02608     
02609     cmxDrawImageEndBits eb;
02610     eb.ImageType = cmxDRAWIMAGE_IMAGETYPE_COLOUR;
02611     eb.FileRef1 = BitmapRef;
02612     eb.FileRef2 = 0;            
02613     if(!WriteData(&eb, sizeof(eb)))
02614         return FALSE;
02615 
02616     
02617     if(!EndTag())
02618         return FALSE;
02619 
02620     
02621     if(!WriteMinEndTag()
02622         || !EndCommand())
02623         return FALSE;
02624 
02625     return TRUE;
02626 }