cdrfill.cpp

Go to the documentation of this file.
00001 // $Id: cdrfill.cpp 751 2006-03-31 15:43:49Z alex $
00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
00003 ================================XARAHEADERSTART===========================
00004  
00005                Xara LX, a vector drawing and manipulation program.
00006                     Copyright (C) 1993-2006 Xara Group Ltd.
00007        Copyright on certain contributions may be held in joint with their
00008               respective authors. See AUTHORS file for details.
00009 
00010 LICENSE TO USE AND MODIFY SOFTWARE
00011 ----------------------------------
00012 
00013 This file is part of Xara LX.
00014 
00015 Xara LX is free software; you can redistribute it and/or modify it
00016 under the terms of the GNU General Public License version 2 as published
00017 by the Free Software Foundation.
00018 
00019 Xara LX and its component source files are distributed in the hope
00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the
00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00022 See the GNU General Public License for more details.
00023 
00024 You should have received a copy of the GNU General Public License along
00025 with Xara LX (see the file GPL in the root directory of the
00026 distribution); if not, write to the Free Software Foundation, Inc., 51
00027 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
00028 
00029 
00030 ADDITIONAL RIGHTS
00031 -----------------
00032 
00033 Conditional upon your continuing compliance with the GNU General Public
00034 License described above, Xara Group Ltd grants to you certain additional
00035 rights. 
00036 
00037 The additional rights are to use, modify, and distribute the software
00038 together with the wxWidgets library, the wxXtra library, and the "CDraw"
00039 library and any other such library that any version of Xara LX relased
00040 by Xara Group Ltd requires in order to compile and execute, including
00041 the static linking of that library to XaraLX. In the case of the
00042 "CDraw" library, you may satisfy obligation under the GNU General Public
00043 License to provide source code by providing a binary copy of the library
00044 concerned and a copy of the license accompanying it.
00045 
00046 Nothing in this section restricts any of the rights you have under
00047 the GNU General Public License.
00048 
00049 
00050 SCOPE OF LICENSE
00051 ----------------
00052 
00053 This license applies to this program (XaraLX) and its constituent source
00054 files only, and does not necessarily apply to other Xara products which may
00055 in part share the same code base, and are subject to their own licensing
00056 terms.
00057 
00058 This license does not apply to files in the wxXtra directory, which
00059 are built into a separate library, and are subject to the wxWindows
00060 license contained within that directory in the file "WXXTRA-LICENSE".
00061 
00062 This license does not apply to the binary libraries (if any) within
00063 the "libs" directory, which are subject to a separate license contained
00064 within that directory in the file "LIBS-LICENSE".
00065 
00066 
00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
00068 ----------------------------------------------
00069 
00070 Subject to the terms of the GNU Public License (see above), you are
00071 free to do whatever you like with your modifications. However, you may
00072 (at your option) wish contribute them to Xara's source tree. You can
00073 find details of how to do this at:
00074   http://www.xaraxtreme.org/developers/
00075 
00076 Prior to contributing your modifications, you will need to complete our
00077 contributor agreement. This can be found at:
00078   http://www.xaraxtreme.org/developers/contribute/
00079 
00080 Please note that Xara will not accept modifications which modify any of
00081 the text between the start and end of this header (marked
00082 XARAHEADERSTART and XARAHEADEREND).
00083 
00084 
00085 MARKS
00086 -----
00087 
00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
00089 designs are registered or unregistered trademarks, design-marks, and/or
00090 service marks of Xara Group Ltd. All rights in these marks are reserved.
00091 
00092 
00093       Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
00094                         http://www.xara.com/
00095 
00096 =================================XARAHEADEREND============================
00097  */
00098 // *********Fills for the CDR file filter
00099 
00100 /*
00101 */
00102 
00103 #include "camtypes.h"
00104 #include "cdrfiltr.h"
00105 #include "nodepath.h"
00106 #include "cdrbitm.h"
00107 //#include "ben.h"
00108 #include "nodebmp.h"
00109 #include "nodetxts.h"
00110 
00111 DECLARE_SOURCE("$Revision: 751 $");
00112 
00113 #define new CAM_DEBUG_NEW
00114 
00115 /********************************************************************************************
00116 
00117 >   BOOL CDRFilter::SetFillAttr(cdrfOffsetHeader *Object)
00118 
00119     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00120     Created:    27 03 95
00121     Inputs:     address of the object
00122     Returns:    error flag
00123     Purpose:    sets the fill attributes
00124     SeeAlso:    Filter
00125 
00126 ********************************************************************************************/
00127 
00128 BOOL CDRFilter::SetFillAttr(cdrfOffsetHeader *Object)
00129 {
00130     if(Version == CDRVERSION_3)
00131     {
00132         return SetFillAttr3(Object);
00133     }
00134 
00135     // find the reference...
00136     DWORD *pReference = (DWORD *)FindDataInObject(Object, cdrfOBJOFFSETTYPE_FILL);
00137 
00138     // if the pointer to the reference is zero, then the reference is probably
00139     // within some random style definition
00140     if(pReference == 0)
00141     {
00142         // OK, try and find a style number within the style reference
00143         WORD *pStyleReference = (WORD *)FindDataInObject(Object, cdrfOBJOFFSETTYPE_STYLE);
00144 
00145         if(pStyleReference != 0)
00146         {
00147             // OK, see if we can find a the style...
00148             cdrfStyle *pStyle;
00149             INT32 StyleSize;
00150 
00151             if((pStyle = (cdrfStyle *)Styles.Find(*pStyleReference, &StyleSize)) != 0)
00152             {
00153                 // OK, got a style... now find a fill reference within it
00154                 pReference = (DWORD *)FindDataInObject(&pStyle->Header, cdrfSTYLEOFFSETTYPE_FILL);
00155             }
00156         }
00157     }
00158     
00159     // should this be filled?
00160     if(pReference == 0 || ObjFilled == FALSE)
00161     {
00162         // set not filled attribute
00163         return NoFill();
00164     }
00165 
00166     cdrfFillHeader *Fill;
00167     INT32 FillSize;
00168     
00169     // set is filled attribute
00170     if(!SetPathFilled(TRUE))
00171         return FALSE;
00172 
00173     // try and find the data for a version 4 or 5 fill
00174     if((Fill = (cdrfFillHeader *)Fills.Find(*pReference, &FillSize)) == 0)
00175         return SetUKFill();
00176 
00177     // check the fill's size
00178     if(FillSize < sizeof(cdrfFillHeader))
00179     {
00180         // if no fill defn or it's just a tad to small, set the unknown fill colour
00181         return SetUKFill();
00182     }
00183 
00184     // OK, what's this fill then?
00185     switch(CDRDATA_WORD(Fill->FillType))
00186     {
00187         case cdrfFILLTYPE_NONE:
00188             // no fill - set things up to be hoopy about that.
00189             return NoFill();
00190             break;
00191 
00192         case cdrfFILLTYPE_FLAT:
00193             return SetFillAttrFlat(Fill, FillSize);
00194             break;
00195 
00196         case cdrfFILLTYPE_GRADUATED:
00197             return SetFillAttrGrad(Fill, FillSize);
00198             break;
00199 
00200         case cdrfFILLTYPE_PATTERN:
00201             {
00202                 CDRTiledFillInfo i;
00203                 cdrfFillPattern *PFill = (cdrfFillPattern *)Fill;
00204 
00205                 // check the size and set an unknown fill if it's too small
00206                 if(FillSize < sizeof(cdrfFillPattern))
00207                     return SetUKFill();
00208     
00209                 // set the info structure
00210                 i.SizeX = CDRDATA_SWORD(PFill->SizeX);
00211                 i.SizeY = CDRDATA_SWORD(PFill->SizeY);
00212                 i.OffsetX = CDRDATA_SWORD(PFill->OffsetX);
00213                 i.OffsetY = CDRDATA_SWORD(PFill->OffsetY);
00214                 i.Reference = CDRDATA_DWORD(PFill->Reference);
00215 
00216                 // convert the colours
00217                 DocColour Colour1;
00218                 DocColour Colour2;
00219                 ConvertColour(&PFill->Colour1, &Colour1);
00220                 ConvertColour(&PFill->Colour2, &Colour2);
00221 
00222                 return SetFillAttrPattern(&i, &Colour1, &Colour2);
00223             }
00224             break;
00225         
00226         case cdrfFILLTYPE_VECTOR:
00227             {
00228                 CDRTiledFillInfo i;
00229                 cdrfFillVector *VFill = (cdrfFillVector *)Fill;
00230 
00231                 // check the size and set an unknown fill if it's too small
00232                 if(FillSize < sizeof(cdrfFillVector))
00233                     return SetUKFill();
00234     
00235                 // set the info structure
00236                 i.SizeX = CDRDATA_SWORD(VFill->SizeX);
00237                 i.SizeY = CDRDATA_SWORD(VFill->SizeY);
00238                 i.OffsetX = CDRDATA_SWORD(VFill->OffsetX);
00239                 i.OffsetY = CDRDATA_SWORD(VFill->OffsetY);
00240                 i.Reference = CDRDATA_DWORD(VFill->VectorReference);
00241 
00242                 return SetFillAttrVector(&i);
00243             }
00244             break;
00245         
00246         case cdrfFILLTYPE_TEXTURE:
00247             return SetFillAttrTexture(Fill, FillSize);
00248             break;
00249 
00250         default:
00251             return SetUKFill();
00252             break;
00253     }
00254 
00255     return TRUE;
00256 }
00257 
00258 
00259 /********************************************************************************************
00260 
00261 >   BOOL CDRFilter::SetFillAttr(cdrfOffsetHeader *Object)
00262 
00263     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00264     Created:    24/04/95
00265     Inputs:     -
00266     Returns:    error flag
00267     Purpose:    makes an object not filled
00268     SeeAlso:    Filter
00269 
00270 ********************************************************************************************/
00271 
00272 BOOL CDRFilter::NoFill(void)
00273 {
00274     if(pMadeNode->IsKindOf(CC_RUNTIME_CLASS(NodePath)))
00275     {
00276         NodePath *pPath = (NodePath *)pMadeNode;
00277 
00278         pPath->InkPath.IsFilled = FALSE;
00279     }
00280 
00281     ObjFilled = FALSE;
00282     SetFillColour(DocColour(COLOUR_TRANS));
00283     return SetPathFilled(FALSE);
00284 }
00285 
00286 /********************************************************************************************
00287 
00288 >   BOOL CDRFilter::SetFillAttr3(cdrfOffsetHeader *Object)
00289 
00290     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00291     Created:    05/04/95
00292     Inputs:     address of object
00293     Returns:    error flag
00294     Purpose:    sets the fill attributes for version 3
00295     SeeAlso:    Filter
00296 
00297 ********************************************************************************************/
00298 
00299 BOOL CDRFilter::SetFillAttr3(cdrfOffsetHeader *Object)
00300 {
00301     cdrfFillV3 *Fill = (cdrfFillV3 *)FindDataInObject(Object, cdrfOBJOFFSETTYPE_FILL);
00302     
00303     if(Fill == 0)
00304     {
00305         // set not filled attribute
00306         return NoFill();
00307     }
00308 
00309     // info about the fill
00310     CDRFillInfo fi;
00311 
00312     // find the bounding box of this lovely node
00313     DocRect BBox;
00314     if(!GetObjCorelBBox((NodeRenderableBounded *)pMadeNode, &BBox))
00315         return FALSE;
00316 
00317     // convert colours and things as necessary
00318     DocColour Col1;
00319     DocColour Col2;
00320 
00321     if(Fill->Type == cdrfFILLTYPEV3_FLAT)
00322     {
00323         if(!ConvertColour((cdrfColour *)&Fill->Data.Flat.Colour, &Col1))
00324             return FALSE;
00325     }
00326     else if(Fill->Type == cdrfFILLTYPEV3_LINEAR || Fill->Type == cdrfFILLTYPEV3_RADIAL)
00327     {
00328         fi.Angle = CDRDATA_SWORD(Fill->Data.Grad.Angle);
00329         fi.Pad = CDRDATA_SWORD(Fill->Data.Grad.Pad);
00330         fi.HorizontalCentreOffset = CDRDATA_SWORD(Fill->Data.Grad.HorizontalCentreOffset);
00331         fi.VerticalCentreOffset = CDRDATA_SWORD(Fill->Data.Grad.VerticalCentreOffset);
00332     
00333         if(!ConvertColour((cdrfColour *)&Fill->Data.Grad.Colour1, &Col1))
00334             return FALSE;
00335         if(!ConvertColour((cdrfColour *)&Fill->Data.Grad.Colour2, &Col2))
00336             return FALSE;
00337     }
00338 
00339     // make the path filled
00340     if(!SetPathFilled(TRUE))
00341         return FALSE;
00342     
00343     // set the fill
00344     switch(Fill->Type)
00345     {
00346         case cdrfFILLTYPEV3_NONE:
00347             return NoFill();
00348             break;
00349 
00350         case cdrfFILLTYPEV3_FLAT:
00351             if(!SetFillColour(Col1))
00352                 return FALSE;
00353             break;
00354 
00355         case cdrfFILLTYPEV3_LINEAR:
00356             if(!SetLinearGrad(&fi, BBox, &Col1, &Col2))
00357                 return SetUKFill();
00358             break;
00359 
00360         case cdrfFILLTYPEV3_RADIAL:
00361             if(!SetRadialGrad(&fi, BBox, &Col1, &Col2))
00362                 return SetUKFill();
00363             break;
00364 
00365 
00366         case cdrfFILLTYPEV3_PATTERN:
00367             {
00368                 CDRTiledFillInfo i;
00369 
00370                 // set the info structure
00371                 i.SizeX = CDRDATA_SWORD(Fill->Data.Pattern.SizeX);
00372                 i.SizeY = CDRDATA_SWORD(Fill->Data.Pattern.SizeY);
00373                 i.OffsetX = CDRDATA_SWORD(Fill->Data.Pattern.OffsetX);
00374                 i.OffsetY = CDRDATA_SWORD(Fill->Data.Pattern.OffsetY);
00375                 i.Reference = CDRDATA_DWORD(Fill->Data.Pattern.Reference);
00376 
00377                 // convert the colours
00378                 ConvertColour((cdrfColour *)&Fill->Data.Pattern.Colour1, &Col1);
00379                 ConvertColour((cdrfColour *)&Fill->Data.Pattern.Colour2, &Col2);
00380 
00381                 return SetFillAttrPattern(&i, &Col1, &Col2);
00382             }
00383             break;
00384     
00385         case cdrfFILLTYPEV3_VECTOR:
00386             {
00387                 CDRTiledFillInfo i;
00388 
00389                 // set the info structure
00390                 i.SizeX = CDRDATA_SWORD(Fill->Data.Vector.SizeX);
00391                 i.SizeY = CDRDATA_SWORD(Fill->Data.Vector.SizeY);
00392                 i.OffsetX = CDRDATA_SWORD(Fill->Data.Vector.OffsetX);
00393                 i.OffsetY = CDRDATA_SWORD(Fill->Data.Vector.OffsetY);
00394                 i.Reference = CDRDATA_DWORD(Fill->Data.Vector.Reference);
00395 
00396                 return SetFillAttrVector(&i);
00397             }
00398             break;
00399     
00400         default:
00401             return SetUKFill();
00402             break;
00403     }   
00404 
00405     return TRUE;
00406 }
00407 
00408 
00409 /********************************************************************************************
00410 
00411 >   BOOL CDRFilter::SetFillAttrFlat(cdrfFillHeader *Fill, INT32 Size)
00412 
00413     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00414     Created:    28 03 95
00415     Inputs:     pointer to fill header
00416     Returns:    error flag
00417     Purpose:    sets flat fill attributes
00418     SeeAlso:    Filter
00419 
00420 ********************************************************************************************/
00421 
00422 BOOL CDRFilter::SetFillAttrFlat(cdrfFillHeader *Fill, INT32 Size)
00423 {
00424     cdrfFillFlat *FFill = (cdrfFillFlat *)Fill;
00425 
00426     // check the size and set an unknown fill if it's too small
00427     if(Size < sizeof(cdrfFillFlat))
00428         return SetUKFill();
00429     
00430     // convert and set the line colour
00431     DocColour Col;
00432     ConvertColour(&FFill->Colour, &Col);
00433 
00434     if(!SetFillColour(Col))
00435         return FALSE;
00436 
00437     return TRUE;
00438 }
00439 
00440 
00441 /********************************************************************************************
00442 
00443 >   BOOL CDRFilter::SetFillAttrGrad(cdrfFillHeader *Fill, INT32 Size)
00444 
00445     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00446     Created:    28 03 95
00447     Inputs:     pointer to fill header
00448     Returns:    error flag
00449     Purpose:    sets graduated fill attributes
00450     SeeAlso:    Filter
00451 
00452 ********************************************************************************************/
00453 
00454 BOOL CDRFilter::SetFillAttrGrad(cdrfFillHeader *Fill, INT32 Size)
00455 {
00456     // check that it's big enought to be a realistic grad fill
00457     if(Size < (sizeof(cdrfFillGraduated) + sizeof(cdrfFillGradColour)))
00458     {
00459 TRACEUSER( "Ben", _T("fill too small, size = %d\n"), Size);
00460         return SetUKFill();
00461     }
00462 
00463     // make a new pointer
00464     cdrfFillGraduated *GFill = (cdrfFillGraduated *)Fill;
00465 
00466     // has it got enough colours in it?
00467     if(CDRDATA_WORD(GFill->NColours) < 1)
00468         return SetUKFill();
00469 
00470     // find the bounding box of this lovely node
00471     DocRect BBox;
00472     if(!GetObjCorelBBox((NodeRenderableBounded *)pMadeNode, &BBox))
00473         return FALSE;
00474 
00475     // sort out the colours on this fill - ATM we can only go from one colour to
00476     // another, so we just need to find the last and first ones and use those.
00477     cdrfFillGradColour *Cols = (cdrfFillGradColour *)(GFill + 1);
00478 
00479     UINT32 min = CDRDATA_WORD(Cols[0].Percentage);
00480     UINT32 max = min;
00481     UINT32 minO = 0;
00482     UINT32 maxO = 0;
00483     UINT32 l;
00484 
00485     for(l = 1; l < CDRDATA_WORD(GFill->NColours); l++)
00486     {
00487         UINT32 p = CDRDATA_WORD(Cols[l].Percentage);
00488 
00489         if(p < min)
00490         {
00491             min = p;
00492             minO = l;
00493         }
00494         if(p > max)
00495         {
00496             max = p;
00497             maxO = l;
00498         }
00499     }
00500 
00501     // OK, found the minimum and maximim percentages along the grad fill line.
00502     // get and convert the colours
00503     DocColour StartColour;
00504     DocColour EndColour;
00505 
00506     ConvertColour(&Cols[minO].Colour, &StartColour);
00507     ConvertColour(&Cols[maxO].Colour, &EndColour);
00508 
00509     // now work out what kind of fade we need here
00510     UINT32 FadeType = CDRDATA_WORD(GFill->ColourType);
00511 
00512     // if it's a rainbow effect, work out whether an anti-clockwise thingy will be a
00513     // a normal or alt rainbow fill
00514     BOOL NormalRainbow = TRUE;
00515     if(FadeType == cdrfGRADFILLCOLOURTYPE_RAINBOW_CLOCKWISE ||
00516              FadeType == cdrfGRADFILLCOLOURTYPE_RAINBOW_ANTICLOCKWISE)
00517     {
00518         // convert both colours to HSV to find their hue
00519         ColourContext *Conv = ColourContext::GetGlobalDefault(COLOURMODEL_HSVT);
00520 
00521         ColourHSVT StartC;
00522         ColourHSVT EndC;
00523 
00524         Conv->ConvertColour(&StartColour, (ColourGeneric *)&StartC);
00525         Conv->ConvertColour(&EndColour, (ColourGeneric *)&EndC);
00526 
00527         // compare the hues and work out a difference
00528         ColourValue Difference;
00529 
00530         if(EndC.Hue > StartC.Hue)
00531         {
00532             Difference = EndC.Hue - StartC.Hue;
00533         } else {
00534             Difference = 1.0 - (StartC.Hue - EndC.Hue);
00535         }
00536 
00537         // if the difference is more than 0.5 then it's a alt rainbow thingy
00538         if(Difference > fixed24(0.5))
00539             NormalRainbow = FALSE;
00540     }
00541 
00542     // set the fade effect
00543     switch(FadeType)
00544     {
00545         case cdrfGRADFILLCOLOURTYPE_DIRECT:
00546         case cdrfGRADFILLCOLOURTYPE_CUSTOM:
00547         default:
00548             SetFadeFillEffect();
00549             break;
00550 
00551         case cdrfGRADFILLCOLOURTYPE_RAINBOW_ANTICLOCKWISE:
00552             if(NormalRainbow)
00553                 SetRainbowFillEffect();
00554             else
00555                 SetAltRainbowFillEffect();
00556             break;
00557 
00558         case cdrfGRADFILLCOLOURTYPE_RAINBOW_CLOCKWISE:
00559             if(NormalRainbow)
00560                 SetAltRainbowFillEffect();
00561             else
00562                 SetRainbowFillEffect();
00563             break;
00564     }
00565 
00566     // get the info about the fill
00567     CDRFillInfo fi;
00568 
00569     fi.Angle = CDRDATA_SWORD(GFill->Angle);
00570     fi.Pad = CDRDATA_SWORD(GFill->Pad);
00571     fi.HorizontalCentreOffset = CDRDATA_SWORD(GFill->HorizontalCentreOffset);
00572     fi.VerticalCentreOffset = CDRDATA_SWORD(GFill->VerticalCentreOffset);
00573     
00574     // and finally, sort out the start and end points of the thingy
00575     DocCoord StartPoint;
00576     DocCoord EndPoint;
00577     switch(CDRDATA_WORD(GFill->GradFillType))
00578     {
00579         case cdrfGRADFILLTYPE_LINEAR:
00580             if(!SetLinearGrad(&fi, BBox, &StartColour, &EndColour))
00581                 return SetUKFill();
00582             break;
00583 
00584         case cdrfGRADFILLTYPE_RADIAL:
00585         case cdrfGRADFILLTYPE_SQUARE:       // radial is the nearest Camelot fill to a square fill
00586             if(!SetRadialGrad(&fi, BBox, &StartColour, &EndColour))
00587                 return SetUKFill();
00588             break;
00589 
00590         case cdrfGRADFILLTYPE_CONICAL:
00591             if(!SetConicalGrad(&fi, BBox, &StartColour, &EndColour))
00592                 return SetUKFill();
00593             break;
00594 
00595         default:            
00596             return SetUKFill();
00597             break;
00598     }
00599 
00600     return TRUE;
00601 }
00602 
00603 
00604 /********************************************************************************************
00605 
00606 >   BOOL CDRFilter::SetUKFill(void)
00607 
00608     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00609     Created:    28 03 95
00610     Inputs:     pointer to fill header
00611     Returns:    error flag
00612     Purpose:    sets a fill attribute for unknown fills
00613     SeeAlso:    Filter
00614 
00615 ********************************************************************************************/
00616 
00617 BOOL CDRFilter::SetUKFill(void)
00618 {
00619     PColourCMYK cmyk;
00620     cmyk.Cyan = cmyk.Magenta = cmyk.Yellow = 0;
00621     cmyk.Key = 255;
00622 
00623     DocColour Col;
00624     Col.SetCMYKValue(&cmyk);
00625 
00626     return SetFillColour(Col);
00627 }
00628 
00629 
00630 /********************************************************************************************
00631 
00632 >   BOOL CDRFilter::GetObjCorelBBox(NodeRenderable *pNode, DocRect *BBox)
00633 
00634     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00635     Created:    28 03 95
00636     Inputs:     converted node (after transformation) and a pointer to bbox to fill in
00637     Returns:    error flag
00638     Purpose:    gets the corel bbox of a converted object, looking up the bbox of text objects
00639     SeeAlso:    Filter
00640 
00641 ********************************************************************************************/
00642 
00643 BOOL CDRFilter::GetObjCorelBBox(NodeRenderableBounded *pNode, DocRect *BBox)
00644 {
00645     if(IS_A(pNode, TextStory) && TextBBoxes.Find(pNode, BBox) == TRUE)
00646         return TRUE;
00647 
00648     return GetCorelBBox(pNode, BBox);
00649 }
00650 
00651 /********************************************************************************************
00652 
00653 >   BOOL CDRFilter::GetCorelBBox(NodeRenderable *pNode, DocRect *BBox)
00654 
00655     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00656     Created:    28 03 95
00657     Inputs:     converted node (after transformation) and a pointer to bbox to fill in
00658     Returns:    error flag
00659     Purpose:    gets the Corel simple union bbox of an object
00660     SeeAlso:    Filter
00661 
00662 ********************************************************************************************/
00663 
00664 BOOL CDRFilter::GetCorelBBox(NodeRenderableBounded *pNode, DocRect *BBox)
00665 {
00666     if(pNode->IsKindOf(CC_RUNTIME_CLASS(NodePath)))
00667     {
00668         // ok, so it's a path. That means we can run through it to find out the simple
00669         // union of all points. That's cool. Nice of corel not to do proper bboxes, isn't
00670         // it?
00671 
00672         NodePath *pNodePath = (NodePath *)pNode;
00673 
00674         // get a pointer to the array of coords in the nice path
00675         INT32 NCoords = pNodePath->InkPath.GetNumCoords();
00676         DocCoord *Coords = pNodePath->InkPath.GetCoordArray();
00677 
00678         ERROR3IF(NCoords < 1, "Awooga! Trying to find a corel bbox of a path with less than one coord.");
00679 
00680         INT32 c;
00681 
00682         INT32 x0, y0, x1, y1;
00683 
00684         // initialise my bbox variables
00685         x0 = x1 = Coords[0].x;
00686         y0 = y1 = Coords[0].y;
00687         
00688         for(c = 1; c < NCoords; c++)
00689         {
00690             // update my bbox
00691             if(Coords[c].x < x0) x0 = Coords[c].x;
00692             if(Coords[c].y < y0) y0 = Coords[c].y;
00693             if(Coords[c].x > x1) x1 = Coords[c].x;
00694             if(Coords[c].y > y1) y1 = Coords[c].y;
00695         }
00696 
00697         // fill in *BBox
00698         BBox->lo.x = x0;
00699         BBox->lo.y = y0;
00700         BBox->hi.x = x1;
00701         BBox->hi.y = y1;
00702     } else {
00703         // if it's not a path object, ask the node what it's bounding box is - we'll just
00704         // have to make do with a *correct* bounding box instead of simply corel union.
00705         *BBox = pNode->GetBoundingRect();
00706     }
00707 
00708     return TRUE;
00709 }
00710 
00711 
00712 /********************************************************************************************
00713 
00714 >   BOOL CDRFilter::SetLinearGrad(CDRFillInfo *GFill, DocRect &BBox, DocColour *StartColour, DocColour *EndColour)
00715 
00716     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00717     Created:    28 03 95
00718     Inputs:     grad fill defn and converted colours for the fill
00719     Returns:    error flag
00720     Purpose:    sets a linear graduated fill from fill definition in the file
00721                 Copied from coreleps.cpp and modified
00722     SeeAlso:    Filter
00723 
00724 ********************************************************************************************/
00725 
00726 BOOL CDRFilter::SetLinearGrad(CDRFillInfo *GFill, DocRect &BBox, DocColour *StartColour, DocColour *EndColour)
00727 {
00728     // NB. this function is (hopefully!) over-complex and will be simplified.
00729     // However, it's like this atm so I can get my head around the weird maths Corel 
00730     // forces us to use.
00731 
00732     // The desired start and end points of the grad fill 'arrow'.
00733     DocCoord Start, End;
00734 
00735     // Calculate width and height
00736     MILLIPOINT Width = BBox.Width();
00737     MILLIPOINT Height = BBox.Height();
00738 
00739     // bodge just in case of zero height or widths
00740     if(Width < 16)
00741         Width = 16;
00742 
00743     if(Height < 16)
00744         Height = 16;
00745 
00746     // Find centre of box
00747     DocCoord Centre;
00748     Centre.x = BBox.lo.x + (Width / 2);
00749     Centre.y = BBox.lo.y + (Height / 2);
00750 
00751     // Find total area of BBox
00752     double TotalArea = (double) Width * (double) Height;
00753 
00754     // Cope with angles > 180
00755     BOOL Mirror = FALSE;
00756     INT32 Angle = GFill->Angle;     // note angle is * 10
00757     
00758     if (Angle >= 1800)
00759     {
00760         Angle -= 1800;
00761         Mirror = TRUE;
00762     }
00763     else if (Angle < 00)
00764     {
00765         Angle += 1800;
00766         Mirror = TRUE;
00767     }
00768 
00769     Angle += 900;
00770 
00771     if (Angle >= 1800)
00772     {
00773         Angle -= 1800;
00774     }
00775 
00776     // get edge pad value
00777     INT32 EdgePad = GFill->Pad;
00778     
00779     // Calculate tan of the angle - convert angle to radians first.
00780     double Radians = (((double) Angle) / 1800.0) * PI;
00781     double TanTheta;
00782     if (Angle == 900)
00783     {
00784         // Special case for horizontal grad fill arrow.
00785 
00786         // Make 0% padding first
00787         Start.x = BBox.lo.x;
00788         Start.y = Centre.y;
00789         End.x = BBox.hi.x;
00790         End.y = Centre.y;
00791 
00792         // Find out width of padding
00793         INT32 Padding = (Width * EdgePad) / 100;
00794         Start.x += Padding;
00795         End.x -= Padding;
00796     }
00797     else if (Angle == 0)
00798     {
00799         // Special case for vertical grad fill arrow.
00800 
00801         // Make 0% padding first
00802         Start.x = Centre.x;
00803         Start.y = BBox.lo.y;
00804         End.x = Centre.x;
00805         End.y = BBox.hi.y;
00806 
00807         // Find out width of padding
00808         INT32 Padding = (Height * EdgePad) / 100;
00809         Start.y += Padding;
00810         End.y -= Padding;
00811     }
00812     else
00813     {
00814         TanTheta = tan(Radians);
00815 
00816         // Find out what the maximum padding is that we can achieve using just triangles:
00817 
00818         // Find the maximum triangle width
00819         MILLIPOINT TriWidth = (MILLIPOINT) ((double) Height / TanTheta);
00820 
00821         // Limit it to sensible value
00822         if (TriWidth < 0)
00823             TriWidth = -TriWidth;
00824         if (TriWidth > Width)
00825             TriWidth = Width;
00826 
00827         // Find the maximum triangle width
00828         MILLIPOINT TriHeight = (MILLIPOINT) ((double) Width * TanTheta);
00829 
00830         // Limit it to sensible value
00831         if (TriHeight < 0)
00832             TriHeight = -TriHeight;
00833         if (TriHeight > Height)
00834             TriHeight = Height;
00835 
00836         // The 'c' values of the y = mx+c equation.
00837         MILLIPOINT StartC, EndC;
00838 
00839         // Work out the maximum percentage/edge padding this gives us
00840         // (50 because it's 100 / 2 because we want area of triangle, not rectangle).
00841         double Percentage = (50.0 * (double) TriWidth * (double) TriHeight) / TotalArea;
00842 
00843         INT32 Diff = 0;
00844 
00845         // Is this enough?
00846         if (((INT32) Percentage) >= EdgePad)
00847         {
00848             // Yes - calculate exactly how big the triangle needs to be.
00849             TriHeight = (MILLIPOINT) sqrt(ABS(((double) EdgePad * TotalArea * TanTheta) / 100.0));
00850 
00851             TriWidth = (MILLIPOINT) ((double) TriHeight / TanTheta);
00852             if (TriWidth < 0)
00853                 TriWidth = -TriWidth;
00854 
00855             ENSURE(TriWidth < Width, "Error in Corel Grad fill decoding logic");
00856         }
00857         else
00858         {
00859             // How much percentage do we need to add with each rectangle?
00860             Percentage = (EdgePad - Percentage) / 2;
00861 
00862             // Handle the rectangle stuff.
00863             if (TriWidth == Width)
00864             {
00865                 // Need to add rectangles to the top and bottom.
00866                 Diff = (MILLIPOINT) ((Percentage * Height) / 100.0);
00867             }
00868             else
00869             {
00870                 // Need to add rectangles to left and right
00871                 Diff = (MILLIPOINT) ((Percentage * Width) / 100.0);
00872                 Diff = (MILLIPOINT) (Diff / tan(PI - Radians));
00873                 Diff = ABS(Diff);
00874             }
00875         }
00876 
00877         // Work out the C value for the start line (c = y - mx)
00878         // (m = tan(angle) )
00879         if (Angle == 900)
00880         {
00881             //ENSURE(FALSE, "90 degree angle found!");
00882         }
00883         else if (Angle < 900)
00884         {
00885             StartC = (MILLIPOINT) (BBox.lo.y - ((BBox.hi.x - TriWidth) * TanTheta));
00886             EndC = (MILLIPOINT) (BBox.hi.y - ((BBox.lo.x + TriWidth) * TanTheta));
00887         }
00888         else
00889         {
00890             StartC = (MILLIPOINT) (BBox.lo.y - ((BBox.lo.x + TriWidth) * TanTheta));
00891             EndC = (MILLIPOINT) (BBox.hi.y - ((BBox.hi.x - TriWidth) * TanTheta));
00892         }
00893 
00894         // Add on difference for rectangles, if any.
00895         StartC += Diff;
00896         EndC -= Diff;
00897 
00898 
00899         // Work out m and c for the grad fill line.
00900         // We know m is -1/m of the triangle's hypotenuse.
00901         // c = roy - (rox/m)
00902         double FillM = -1.00 / TanTheta;
00903         MILLIPOINT FillC = (MILLIPOINT) (Centre.y - (Centre.x * FillM));
00904 
00905         // Work out intersections:  x = (c2 - c1) / (2m)
00906 
00907         Start.x = (MILLIPOINT) ( (FillC - StartC) / (TanTheta + (1.00 / TanTheta)) );
00908         Start.y = (MILLIPOINT) ((FillM * Start.x) + FillC);
00909 
00910         End.x = (MILLIPOINT) ( (FillC - EndC) / (TanTheta + (1.00 / TanTheta)) );
00911         End.y = (MILLIPOINT) ((FillM * End.x) + FillC);
00912     }
00913 
00914     if (Mirror)
00915     {
00916         // Swap the grid fill end-points over.
00917         DocCoord Tmp = Start;
00918         Start = End;
00919         End = Tmp;
00920     }
00921 
00922     // Set the fill type according to these calculations.
00923     return SetLinearFill(*StartColour, *EndColour, Start, End); 
00924 }
00925 
00926 
00927 /********************************************************************************************
00928 
00929 >   BOOL CDRFilter::SetConicalGrad(CDRFillInfo *GFill, DocRect &BBox, DocColour *StartColour, DocColour *EndColour)
00930 
00931     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00932     Created:    28 03 95
00933     Inputs:     grad fill defn and converted colours for the fill
00934     Returns:    error flag
00935     Purpose:    sets a conical graduated fill from fill definition in the file
00936                 Copied from coreleps.cpp and modified
00937     SeeAlso:    Filter
00938 
00939 ********************************************************************************************/
00940 
00941 BOOL CDRFilter::SetConicalGrad(CDRFillInfo *GFill, DocRect &BBox, DocColour *StartColour, DocColour *EndColour)
00942 {
00943     // The desired start and end points of the grad fill 'arrow'.
00944     DocCoord Start, End;
00945 
00946     // Calculate width and height
00947     MILLIPOINT Width = BBox.Width();
00948     MILLIPOINT Height = BBox.Height();
00949 
00950     // Start point is the centre given by Corel.
00951     // This centre is percentage offsets from the centre of the object, i.e. (0,0) is
00952     // the centre of the bounding box.
00953     Start.x = BBox.lo.x + (Width  / 2);
00954     Start.y = BBox.lo.y + (Height / 2);
00955     Start.x += ((GFill->HorizontalCentreOffset * Width) / 100);
00956     Start.y += ((GFill->VerticalCentreOffset * Height) / 100);
00957 
00958     // End point is start point + radius but takes into account the angle
00959     double Radius = Width / 2;
00960     // angle is * 10, and needs to be in radians
00961     double Theta = ((((double)(GFill->Angle)) / 10.0) / 360.0) * (2 * PI);
00962 
00963     // make the angle go anti-clockwise
00964     Theta = 0 - Theta;
00965 
00966     // rotate by PI / 2
00967     Theta -= PI / 2;
00968     
00969     // angle can be negative, ensure it's positive
00970     while(Theta < 0)
00971         Theta += (2 * PI);
00972 
00973     // calculate the triangle
00974     double dx, dy;
00975 
00976     dx = Radius * sin(Theta);
00977     dy = Radius * cos(Theta);
00978 
00979     End.x = Start.x + (INT32)dx;
00980     End.y = Start.y + (INT32)dy;
00981 
00982     // Seems that we need to swap start and end colours...
00983 
00984     // Set the fill type according to these calculations.
00985     return SetConicalFill(*EndColour, *StartColour, Start, End);    
00986 }
00987 
00988 
00989 /********************************************************************************************
00990 
00991 >   BOOL CDRFilter::SetRadialGrad(CDRFillInfo *GFill, DocRect &BBox, DocColour *StartColour, DocColour *EndColour)
00992 
00993     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00994     Created:    21/04/95
00995     Inputs:     grad fill defn and converted colours for the fill
00996     Returns:    error flag
00997     Purpose:    sets a radial graduated fill from fill definition in the file
00998     SeeAlso:    Filter
00999 
01000 ********************************************************************************************/
01001 
01002 BOOL CDRFilter::SetRadialGrad(CDRFillInfo *GFill, DocRect &BBox, DocColour *StartColour, DocColour *EndColour)
01003 {
01004     // The desired start and end points of the grad fill 'arrow'.
01005     DocCoord Start, End;
01006 
01007     // Calculate width and height
01008     MILLIPOINT Width = BBox.Width();
01009     MILLIPOINT Height = BBox.Height();
01010 
01011     // caluculate the source area
01012     // first, what's the diagonal length
01013     double dWidth = Width;
01014     double dHeight = Height;
01015     INT32 Diagonal = (INT32)sqrt(dWidth*dWidth + dHeight*dHeight);
01016 
01017     // and from that calculate area of the box containing the bit of the
01018     // bit of the circle in the bbox
01019     INT32 Edge = (Diagonal * (100 - (GFill->Pad * 2))) / 100;
01020 
01021     // Start point is the centre given by Corel.
01022     // This centre is percentage offsets from the centre of the object, i.e. (0,0) is
01023     // the centre of the bounding box.
01024     DocCoord Centre = DocCoord(BBox.lo.x + (Width / 2), BBox.lo.y + (Height / 2));
01025     INT32 OffX = (GFill->HorizontalCentreOffset * Width) / 100;
01026     INT32 OffY = (GFill->VerticalCentreOffset * Height) / 100;
01027     Start.x = Centre.x + OffX;
01028     Start.y = Centre.y + OffY;
01029 
01030     // Find required radius of circle.
01031     double Radius = Edge / 2;
01032 
01033     // how far away is the centre of the fill from the centre of the bbox?
01034     double dOffX = OffX;
01035     double dOffY = OffY;
01036     double Dist = (INT32)sqrt(dOffX*dOffX + dOffY*dOffY);
01037 
01038     // and increase the radius by a bodge factor
01039     double BodgeFactor = 1 + (Dist / (double)(Diagonal / 2));
01040     Radius *= BodgeFactor;
01041     
01042     // End point is start point + radius
01043     End.x = Start.x + ((MILLIPOINT) Radius);
01044     End.y = Start.y;
01045 
01046     // Seems that we need to swap start and end colours...
01047 
01048     // Set the fill type according to these calculations.
01049     return SetRadialFill(*EndColour, *StartColour, Start, End); 
01050 }
01051 
01052 
01053 /********************************************************************************************
01054 
01055 >   BOOL CDRBitmapStore::AddChunkToStore(RIFFFile *RIFF, BOOL Pattern, CDRFilter *C)
01056 
01057     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01058     Created:    10/04/95
01059     Inputs:     RIFF file to get the chunk from, and wether it's pattern or not (Pattern are
01060                 1bpp and have a different format)
01061     Returns:    error flag
01062     Purpose:    Adds a bitmap to the store, converting it now rather than storing it up
01063                 for later
01064     SeeAlso:    CDRFilter
01065 
01066 ********************************************************************************************/
01067 
01068 
01069 BOOL CDRBitmapStore::AddChunkToStore(RIFFFile *RIFF, BOOL Pattern, CDRFilter *C)
01070 {
01071     CDRBitmapStoredItem *Item = new CDRBitmapStoredItem;
01072 
01073     if(Item == 0)
01074         return FALSE;
01075     
01076     // convert the bitmap
01077     FOURCC Reference = 0;       // the reference number of this thingy
01078 
01079     // convert depending on the type of thing
01080     if(Pattern)
01081     {
01082         Item->pBitmap = CDRBitmap::ConvertPattern(RIFF, &Reference, C);
01083     }
01084     else
01085     {
01086         switch(C->Version)
01087         {
01088             case CDRVERSION_5:
01089                 Item->pBitmap = CDRBitmap::ConvertBitmap5(RIFF, &Reference, C);
01090                 break;
01091 
01092             default:
01093                 Item->pBitmap = CDRBitmap::ConvertBitmap4(RIFF, &Reference, C);
01094                 break;
01095         }
01096     }
01097 
01098     // check that we got one
01099     if(Item->pBitmap == 0)
01100         return FALSE;
01101     
01102     // make a nice name for it
01103     String_256 Name;
01104     if(Pattern)
01105         Name.MakeMsg(_R(IDT_CDRPATTERNNAME), CDRFilter::PatternNumber++);
01106     else
01107         Name.MakeMsg(_R(IDT_CDRBITMAPNAME), CDRFilter::BitmapNumber++);
01108 
01109     // and set the name
01110     Item->pBitmap->ActualBitmap->SetName(Name);
01111 
01112     // store the reference
01113     Item->Reference = Reference;
01114     
01115     // add the item to this list
01116     AddTail(Item);
01117     
01118     return TRUE;
01119 }
01120 
01121 
01122 /********************************************************************************************
01123 
01124 >   KernelBitmap *CDRBitmapStore::FindBitmap(DWORD Reference)
01125 
01126     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01127     Created:    10/04/95
01128     Inputs:     reference of the bitmap to find (a CDRDATA_ should already have been done
01129                 on it)
01130     Returns:    a pointer to a KernelBitmap or 0 for not found
01131     Purpose:    Finds a bitmap within the store. Finding a bitmap sets it's used flag to
01132                 TRUE to avoid it being deleted.
01133     SeeAlso:    CDRFilter
01134 
01135 ********************************************************************************************/
01136 
01137 KernelBitmap *CDRBitmapStore::FindBitmap(DWORD Reference)
01138 {
01139     CDRBitmapStoredItem *Item = (CDRBitmapStoredItem *)GetHead();
01140     
01141     // go through the list of items searching for the reference number given
01142     while(Item != 0)
01143     {
01144         if(Item->Reference == Reference)
01145         {
01146             // set the used flag
01147             Item->Used = TRUE;
01148 
01149             return Item->pBitmap;
01150         }
01151 
01152         Item = (CDRBitmapStoredItem *)GetNext(Item);
01153     }
01154 
01155     return 0;
01156 }
01157 
01158 
01159 /********************************************************************************************
01160 
01161 >   CDRBitmapStoredItem::CDRBitmapStoredItem()
01162 
01163     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01164     Created:    10/04/95
01165     Inputs:     -
01166     Returns:    -
01167     Purpose:    Constructor for a bitmap store entry
01168     SeeAlso:    CDRBitmapStore
01169 
01170 ********************************************************************************************/
01171 
01172 CDRBitmapStoredItem::CDRBitmapStoredItem()
01173 {
01174     pBitmap = 0;
01175     Used = FALSE;
01176 }
01177 
01178 
01179 /********************************************************************************************
01180 
01181 >   CDRBitmapStoredItem::~CDRBitmapStoredItem()
01182 
01183     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01184     Created:    10/04/95
01185     Inputs:     -
01186     Returns:    -
01187     Purpose:    Destructor for a bitmap store entry
01188     SeeAlso:    CDRBitmapStore
01189 
01190 ********************************************************************************************/
01191 
01192 CDRBitmapStoredItem::~CDRBitmapStoredItem()
01193 {
01194     if(pBitmap != 0 && Used == FALSE)
01195         delete pBitmap;
01196 }
01197 
01198 
01199 /********************************************************************************************
01200 
01201 >   BOOL CDRFilter::SetFillAttrPattern(CDRTiledFillInfo *Info, DocColour *Colour1, DocColour *Colour2)
01202 
01203     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01204     Created:    10/04/95
01205     Inputs:     pointer to fill header
01206     Returns:    error flag
01207     Purpose:    set pattern fill attributes
01208     SeeAlso:    Filter
01209 
01210 ********************************************************************************************/
01211 
01212 BOOL CDRFilter::SetFillAttrPattern(CDRTiledFillInfo *Info, DocColour *Colour1, DocColour *Colour2)
01213 {
01214     // find the bitmap we're going to use
01215     KernelBitmap *pBitmap = Patterns.FindBitmap(Info->Reference);
01216 
01217     if(pBitmap == 0)
01218         return SetUKFill();
01219 
01220     // work out where it's going to go.
01221 
01222     // find the size of the tile
01223     INT32 SizeX = Info->SizeX * CDRCOORDS_TO_MILLIPOINTS;
01224     INT32 SizeY = Info->SizeY * CDRCOORDS_TO_MILLIPOINTS;
01225 
01226     // find the bounding box of this lovely node
01227     DocRect BBox;
01228     if(!GetObjCorelBBox((NodeRenderableBounded *)pMadeNode, &BBox))
01229         return FALSE;
01230 
01231     // set to the top left + the first tile offset
01232     INT32 XPos = BBox.lo.x + ((SizeX * Info->OffsetX) / 100);
01233     INT32 YPos = BBox.hi.y - SizeY - ((SizeY * Info->OffsetY) / 100);
01234 
01235     // can't do anything with the row/column staggering thingy
01236 
01237     // set the bitmap fill
01238     DocCoord Start  = DocCoord(XPos,            YPos);
01239     DocCoord End1   = DocCoord(XPos + SizeX,    YPos);
01240     DocCoord End2   = DocCoord(XPos,            YPos + SizeY);
01241     if(!SetBitmapFill(pBitmap, Start, End1, End2, Colour1, Colour2))
01242         return FALSE;
01243 
01244     return TRUE;
01245 }
01246 
01247 
01248 /********************************************************************************************
01249 
01250 >   BOOL CDRFilter::SetFillAttrVector(CDRTiledFillInfo *Info)
01251 
01252     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01253     Created:    20/04/95
01254     Inputs:     pointer to fill header
01255     Returns:    error flag
01256     Purpose:    set vector fill attributes
01257     SeeAlso:    Filter
01258 
01259 ********************************************************************************************/
01260 
01261 BOOL CDRFilter::SetFillAttrVector(CDRTiledFillInfo *Info)
01262 {
01263     // find the bitmap we're going to use - at the moment, we can't only do a vector fill
01264     // if it actually referes to a bitmap
01265 
01266     // first things first - find the entry in the vectors list
01267     CDRVectorStoredItem *Item = Vectors.Find(Info->Reference);
01268 
01269     if(Item->Objects == 0)
01270         return SetUKFill();
01271 
01272     // now, does this just refer to a bitmap?
01273     KernelBitmap *pBitmap = BitmapFromNodeList(Item->Objects);
01274 
01275     if(pBitmap == 0)
01276         return SetUKFill();     // no bitmap generation possible
01277 
01278     // work out where it's going to go.
01279 
01280     // find the size of the tile
01281     INT32 SizeX = Info->SizeX * CDRCOORDS_TO_MILLIPOINTS;
01282     INT32 SizeY = Info->SizeY * CDRCOORDS_TO_MILLIPOINTS;
01283 
01284     // find the bounding box of this lovely node
01285     DocRect BBox;
01286     if(!GetObjCorelBBox((NodeRenderableBounded *)pMadeNode, &BBox))
01287         return FALSE;
01288 
01289     // set to the top left + the first tile offset
01290     INT32 XPos = BBox.lo.x + ((SizeX * Info->OffsetX) / 100);
01291     INT32 YPos = BBox.hi.y - SizeY - ((SizeY * Info->OffsetY) / 100);
01292 
01293     // can't do anything with the row/column staggering thingy
01294 
01295     // set the bitmap fill
01296     DocCoord Start  = DocCoord(XPos,            YPos);
01297     DocCoord End1   = DocCoord(XPos + SizeX,    YPos);
01298     DocCoord End2   = DocCoord(XPos,            YPos + SizeY);
01299     if(!SetBitmapFill(pBitmap, Start, End1, End2))
01300         return FALSE;
01301 
01302     return TRUE;
01303 }
01304 
01305 
01306 /********************************************************************************************
01307 
01308 >   BOOL CDRFilter::SetFillAttrTexture(cdrfFillHeader *Fill, INT32 Size)
01309 
01310     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01311     Created:    20/04/95
01312     Inputs:     pointer to fill header
01313     Returns:    error flag
01314     Purpose:    sets texture fill attributes
01315     SeeAlso:    Filter
01316 
01317 ********************************************************************************************/
01318 
01319 BOOL CDRFilter::SetFillAttrTexture(cdrfFillHeader *Fill, INT32 Size)
01320 {
01321     cdrfFillTexture *TFill = (cdrfFillTexture *)Fill;
01322 
01323     // check the size and set an unknown fill if it's too small
01324     if(Size < sizeof(cdrfFillTexture))
01325         return SetUKFill();
01326 
01327     // OK, let's try and find the vector thing it represents
01328     DocRect fBBox;
01329     Node *FillNodes;
01330     
01331     FillNodes = Vectors.Find(CDRDATA_WORD(TFill->VectorReference), &fBBox);
01332 
01333     // did we get any?
01334     if(FillNodes == 0)
01335         return SetUKFill();
01336 
01337     // find the associated bitmap
01338     KernelBitmap *pBitmap;
01339 
01340     pBitmap = BitmapFromNodeList(FillNodes);
01341 
01342     // got one?
01343     if(pBitmap == 0)
01344         return SetUKFill();
01345 
01346     // right then, set the fill to cover the object
01347     // what's it's bounding box?
01348     DocRect BBox;
01349     if(!GetObjCorelBBox((NodeRenderableBounded *)pMadeNode, &BBox))
01350         return FALSE;
01351 
01352     // set the bitmap fill
01353     DocCoord Start  = DocCoord(BBox.lo.x,   BBox.lo.y);
01354     DocCoord End1   = DocCoord(BBox.hi.x,   BBox.lo.y);
01355     DocCoord End2   = DocCoord(BBox.lo.x,   BBox.hi.y);
01356     if(!SetBitmapFill(pBitmap, Start, End1, End2))
01357         return FALSE;
01358 
01359     return TRUE;
01360 }
01361 
01362 
01363 /********************************************************************************************
01364 
01365 >   CDRVectorStoredItem::CDRVectorStoredItem(void)
01366 
01367     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01368     Created:    19/04/95
01369     Inputs:     -
01370     Returns:    -
01371     Purpose:    constructor
01372     SeeAlso:    CDRFilter
01373 
01374 ********************************************************************************************/
01375 
01376 CDRVectorStoredItem::CDRVectorStoredItem(void)
01377     : BBox(0, 0, 0, 0)
01378 {
01379     Objects = 0;
01380     Reference = 0;
01381     pBitmap = 0;
01382 }
01383 
01384 
01385 /********************************************************************************************
01386 
01387 >   BOOL CDRVectorStoredItem::GenerateBitmap(Document *pDocument)
01388 
01389     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01390     Created:    17/05/95
01391     Inputs:     a document to use the default attributes from
01392     Returns:    pointer to a bitmap or zero for an error
01393     Purpose:    generates a bitmap representatation of the vectors stored in this entry
01394     SeeAlso:    CDRFilter
01395 
01396 ********************************************************************************************/
01397 
01398 KernelBitmap *CDRVectorStoredItem::GetBitmap(Document *pDocument)
01399 {
01400     ERROR2IF(Objects == 0, FALSE, "not objects in VectorStoredItem!");
01401 
01402     // has a bitmap already been made?
01403     if(pBitmap != 0)
01404         return pBitmap;
01405 
01406     // generate one...
01407 
01408     return 0;           // nothing could be generated
01409 }
01410 
01411 
01412 /********************************************************************************************
01413 
01414 >   CDRVectorStoredItem::~CDRVectorStoredItem(void)
01415 
01416     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01417     Created:    19/04/95
01418     Inputs:     -
01419     Returns:    -
01420     Purpose:    destructor
01421     SeeAlso:    CDRFilter
01422 
01423 ********************************************************************************************/
01424 
01425 CDRVectorStoredItem::~CDRVectorStoredItem(void)
01426 {
01427     // the objects should always be deleted as copies are made when necessary
01428     if(Objects != 0)
01429         CDRFilter::DeleteNodeList(Objects);
01430 }
01431 
01432 
01433 
01434 /********************************************************************************************
01435 
01436 >   BOOL CDRFilter::ProcessVectorList(ADDR Block, INT32 Size)
01437 
01438     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01439     Created:    19/04/95
01440     Inputs:     vect list contents and size
01441     Returns:    error flag
01442     Purpose:    processes the vector list at the beginning of CDR files. This contains
01443                 a list of objects which are used for things such as full colour fills,
01444                 texture fills, mould shapes, that sort of thing.
01445                 
01446                 They are referenced by the objects serial number.
01447                 
01448                 This function takes a block containing the vect list contents and it's
01449                 size as Corel store all these vectors *before* the fill and outline
01450                 definitions. Are these people really crazy?  
01451     SeeAlso:    Filter
01452 
01453 ********************************************************************************************/
01454 
01455 BOOL CDRFilter::ProcessVectorList(ADDR Block, INT32 Size)
01456 {
01457     ERROR3IF(pLevelNodeList != 0, "ProcessVectorList called when LevelNodeList was in use");
01458 
01459     // first of all, make a CCMemFile out of the block so we can do RIFF stuff on it
01460     CCMemFile MFile;
01461 
01462     MFile.open(Block, Size);
01463 
01464     // make a RIFF file out of it - but we don't have a header
01465     RIFFFile RFile;
01466 
01467     RFile.Init(&MFile, TRUE);
01468 
01469     // OK, change a few variables over...
01470     INT32 oTranslateByX = TranslateByX;
01471     INT32 oTranslateByY = TranslateByY;
01472     RIFFFile *oRIFF = RIFF;
01473 
01474     TranslateByX = 0;
01475     TranslateByY = 0;
01476     RIFF = &RFile;
01477 
01478     // get on and process the block
01479     // what we've got it a load of 'grp' lists containing the objects we're interested in
01480     // they contain a serial number which is used to identify the vector and a bbox,
01481     // which we need to find and store in the list
01482     do
01483     {
01484         // is it a group list?
01485         if(RIFF->GetObjType() == RIFFOBJECTTYPE_LISTSTART && RIFF->GetObjChunkType() == cdrT_grp)
01486         {
01487             if(!ProcessVectorListEntry())
01488                 return FALSE;
01489         }
01490 
01491         if(!RIFF->NextObject())
01492             goto Failure;
01493 
01494     } while(RIFF->GetObjType() != RIFFOBJECTTYPE_FILEEND);
01495 
01496     // close everything down and put the variables back
01497     MFile.close();
01498 
01499     TranslateByX = oTranslateByX;
01500     TranslateByY = oTranslateByY;
01501     RIFF = oRIFF;
01502 
01503     return TRUE;
01504 
01505 Failure:
01506     // clear everything up...
01507     MFile.close();
01508 
01509     TranslateByX = oTranslateByX;
01510     TranslateByY = oTranslateByY;
01511     RIFF = oRIFF;
01512 
01513     return FALSE;
01514 }
01515 
01516 
01517 /********************************************************************************************
01518 
01519 >   BOOL CDRFilter::ProcessVectorListEntry()
01520 
01521     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01522     Created:    19/04/95
01523     Inputs:     -
01524     Returns:    error flag
01525     Purpose:    processes an entry in the vector list
01526     SeeAlso:    Filter
01527 
01528 ********************************************************************************************/
01529 
01530 BOOL CDRFilter::ProcessVectorListEntry()
01531 {
01532     UINT32 StartLevel = RIFF->GetObjLevel();
01533 
01534     ERROR3IF(RIFF->GetObjType() != RIFFOBJECTTYPE_LISTSTART && RIFF->GetObjChunkType() != cdrT_grp,
01535         "ProcessVectorListEntry called without RIFF set up correctly");
01536 
01537     // OK, wander though to find the serial number and the bbox
01538     WORD Reference;     // the serial number
01539     DocRect BBox;
01540     BOOL GotReference = FALSE;
01541     BOOL GotBBox = FALSE;
01542 
01543     do
01544     {
01545         if(RIFF->GetObjType() == RIFFOBJECTTYPE_CHUNK)
01546         {
01547             switch(RIFF->GetObjChunkType())
01548             {
01549                 case cdrT_spnd:
01550                     {
01551                         // got the serial number block - get it...
01552                         if(!RIFF->AquireChunkData())
01553                             return FALSE;
01554                     
01555                         WORD *Data = (WORD *)RIFF->GetAquiredData();
01556                     
01557                         if(Data == 0)
01558                             return FALSE;
01559 
01560                         // store it...
01561                         Reference = CDRDATA_WORD(*Data);
01562 
01563                         GotReference = TRUE;
01564                     }
01565                     break;
01566 
01567                 case cdrT_bbox:
01568                     {
01569                         // is it large enought?
01570                         if(RIFF->GetObjSize() < sizeof(cdrfBBox))
01571                         {
01572                             // no - ignore this entry
01573                             RIFF->SkipToListEnd(StartLevel);
01574                             return TRUE;
01575                         }
01576 
01577                         // found the bbox... get the data
01578                         if(!RIFF->AquireChunkData())
01579                             return FALSE;
01580                     
01581                         cdrfBBox *Data = (cdrfBBox *)RIFF->GetAquiredData();
01582                     
01583                         if(Data == 0)
01584                             return FALSE;
01585 
01586                         // get the bounding box
01587                         BBox.lo.x = CDRDATA_SWORD(Data->x0) * CDRCOORDS_TO_MILLIPOINTS;
01588                         BBox.lo.y = CDRDATA_SWORD(Data->y0) * CDRCOORDS_TO_MILLIPOINTS;
01589                         BBox.hi.x = CDRDATA_SWORD(Data->x1) * CDRCOORDS_TO_MILLIPOINTS;
01590                         BBox.hi.y = CDRDATA_SWORD(Data->y1) * CDRCOORDS_TO_MILLIPOINTS;
01591                     
01592                         GotBBox = TRUE;
01593                     }
01594                     break;
01595                 
01596                 default:
01597                     break;
01598             }
01599         }
01600     
01601         if(!RIFF->NextObject())
01602             return FALSE;
01603 
01604     } while((GotReference == FALSE || GotBBox == FALSE) &&
01605         (RIFF->GetObjType() != RIFFOBJECTTYPE_LISTEND || RIFF->GetObjLevel() > StartLevel));
01606 
01607     // OK, now get the object tree
01608     if(!ProcessObjectTree(StartLevel))
01609         return FALSE;
01610 
01611     // right then, the converted nodes are in pLevelNodeList
01612     // create a nice list entry
01613 
01614     CDRVectorStoredItem *Item = new CDRVectorStoredItem;
01615 
01616     if(Item == 0)
01617         return FALSE;
01618 
01619     // set the object data
01620     Item->Objects = pLevelNodeList;
01621     Item->Reference = Reference;
01622     Item->BBox = BBox;
01623 
01624     // make the node list unused
01625     pLevelNodeList = 0;
01626     
01627     // add the list entry
01628     Vectors.AddTail(Item);
01629 
01630     return TRUE;
01631 }
01632 
01633 /********************************************************************************************
01634 
01635 >   Node *CDRVectorStore::Find(DWORD Reference, DocRect *BBox)
01636 
01637     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01638     Created:    19/04/95
01639     Inputs:     reference to find, bounding box of found stuff
01640     Returns:    pointer to a node list, or zero for not found
01641     Purpose:    find a vector from the vectors list
01642     SeeAlso:    Filter
01643 
01644 ********************************************************************************************/
01645 
01646 Node *CDRVectorStore::Find(DWORD Reference, DocRect *BBox)
01647 {
01648     CDRVectorStoredItem *Item = (CDRVectorStoredItem *)GetHead();
01649     
01650     // go through the list of items searching for the reference number given
01651     while(Item != 0)
01652     {
01653         if(Item->Reference == Reference)
01654         {
01655             // OK, we found it...
01656             if(BBox != 0)
01657                 *BBox = Item->BBox;
01658             
01659             return Item->Objects;
01660         }
01661 
01662         Item = (CDRVectorStoredItem *)GetNext(Item);
01663     }
01664 
01665     return 0;
01666 }
01667 
01668 
01669 /********************************************************************************************
01670 
01671 >   KernelBitmap *CDRVectorStore::FindAsBitmap(DWORD Reference, DocRect *BBox)
01672 
01673     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01674     Created:    19/04/95
01675     Inputs:     reference to find, bounding box of found stuff
01676     Returns:    pointer to a node list, or zero for not found
01677     Purpose:    find a vector from the vectors list
01678     SeeAlso:    Filter
01679 
01680 ********************************************************************************************/
01681 
01682 CDRVectorStoredItem *CDRVectorStore::Find(DWORD Reference)
01683 {
01684     CDRVectorStoredItem *Item = (CDRVectorStoredItem *)GetHead();
01685     
01686     // go through the list of items searching for the reference number given
01687     while(Item != 0)
01688     {
01689         if(Item->Reference == Reference)
01690         {
01691             // OK, we found it...
01692             return Item;
01693         }
01694 
01695         Item = (CDRVectorStoredItem *)GetNext(Item);
01696     }
01697 
01698     return 0;
01699 }
01700 
01701 
01702 /********************************************************************************************
01703 
01704 >   KernelBitmap *CDRFilter::BitmapFromNodeList(Node *List)
01705 
01706     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01707     Created:    20/04/95
01708     Inputs:     pointer to first node in a list
01709     Returns:    a pointer to the relevant bitmap, or zero if one couldn't be found
01710     Purpose:    given a list of nodes, if it only contains one bitmap then return a pointer
01711                 to that bitmap
01712     SeeAlso:    Filter
01713 
01714 ********************************************************************************************/
01715 
01716 KernelBitmap *CDRFilter::BitmapFromNodeList(Node *List)
01717 {
01718     // make sure we've got something
01719     if(List == 0)
01720         return 0;
01721 
01722     // is there's more than one item?
01723     if(List->FindNext() != 0)
01724         return 0;
01725 
01726     // is it a bitmap?
01727     if(IS_A(List, NodeBitmap))
01728     {
01729         // right then, woz it's bitmap den?
01730         NodeBitmap *NB = (NodeBitmap *)List;
01731 
01732         // return the bitmap...
01733         return NB->GetBitmap();
01734     }
01735 
01736     return 0;
01737 }
01738 
01739 

Generated on Sat Nov 10 03:44:40 2007 for Camelot by  doxygen 1.4.4