cdroutl.cpp

Go to the documentation of this file.
00001 // $Id: cdroutl.cpp 1282 2006-06-09 09:46: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 // *********Outlines for the CDR file filter
00099 
00100 /*
00101 */
00102 
00103 #include "camtypes.h"
00104 #include "cdrfiltr.h"
00105 #include "nodepath.h"
00106 //#include "trans2d.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00107 //#include "group.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00108 #include "impcol.h"
00109 
00110 DECLARE_SOURCE("$Revision: 1282 $");
00111 
00112 #define new CAM_DEBUG_NEW
00113 
00114 /********************************************************************************************
00115 
00116 >   BOOL CDRFilter::SetLineAttr(cdrfOffsetHeader *Object)
00117 
00118     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00119     Created:    27 03 95
00120     Inputs:     address of line data *within* the main object data (loda chunk). Can be zero
00121     Returns:    error flag
00122     Purpose:    sets the line attributes
00123     SeeAlso:    Filter
00124 
00125 ********************************************************************************************/
00126 
00127 #define MAX_LINE_WIDTH  (4*72000)
00128 
00129 BOOL CDRFilter::SetLineAttr(cdrfOffsetHeader *Object)
00130 {
00131     if(Version == CDRVERSION_3)
00132     {
00133         return SetLineAttr3(Object);
00134     }
00135         
00136     // find the reference...
00137     DWORD *pReference = (DWORD *)FindDataInObject(Object, cdrfOBJOFFSETTYPE_LINE);
00138 
00139     // if the pointer to the reference is zero, then the reference is probably
00140     // within some random style definition
00141     if(pReference == 0)
00142     {
00143         // OK, try and find a style number within the style reference
00144         WORD *pStyleReference = (WORD *)FindDataInObject(Object, cdrfOBJOFFSETTYPE_STYLE);
00145 
00146         if(pStyleReference != 0)
00147         {
00148             // OK, see if we can find a the style...
00149             cdrfStyle *pStyle;
00150             INT32 StyleSize;
00151 
00152             if((pStyle = (cdrfStyle *)Styles.Find(*pStyleReference, &StyleSize)) != 0)
00153             {
00154                 // OK, got a style... now find a fill reference within it
00155                 pReference = (DWORD *)FindDataInObject(&pStyle->Header, cdrfSTYLEOFFSETTYPE_OUTLINE);
00156             }
00157         }
00158     }
00159     
00160     cdrfOutline *Out;
00161     INT32 OutSize;
00162     
00163     if(pReference == 0 || (Out = (cdrfOutline *)Outlines.Find(*pReference, &OutSize)) == 0
00164             || OutSize < sizeof(cdrfOutline))
00165     {
00166         // if no outline data, or outline definitions couldn't be found, or outline
00167         // definition is too small, set up the default line attributes
00168         if(!SetLineWidth(cdrfOUTLINE_DEFAULT_WIDTH))
00169             return FALSE;
00170 
00171     PColourCMYK cmyk;
00172     cmyk.Cyan = cmyk.Magenta = cmyk.Yellow = 0;
00173     cmyk.Key = 255;
00174 
00175     DocColour Col;
00176     Col.SetCMYKValue(&cmyk);
00177     
00178         if(!SetLineColour(Col))
00179             return FALSE;
00180 
00181         return TRUE;
00182     }
00183 
00184     // check that this thingy should have an outline
00185     if((CDRDATA_WORD(Out->Flags) & cdrfOUTLINEFLAGS_NOOUTLINE) != 0)
00186     {
00187         if (!SetLineColour(DocColour(COLOUR_TRANS)))
00188             return FALSE;
00189 
00190         return TRUE;
00191     }
00192 
00193     // convert the line colour
00194     DocColour Col;
00195     ConvertColour(&Out->Colour, &Col);
00196 
00197     // find the line width
00198     INT32 LineWidth = CDRDATA_WORD(Out->LineThickness) * CDRCOORDS_TO_MILLIPOINTS;
00199 
00200     if(LineWidth > MAX_LINE_WIDTH)
00201         LineWidth = MAX_LINE_WIDTH;
00202     
00203     // find the join type
00204     JointType JType;
00205     switch(CDRDATA_WORD(Out->JoinStyle))
00206     {
00207         case cdrfJOINSTYLE_SQUARE:  JType = MitreJoin;      break;
00208         case cdrfJOINSTYLE_ROUNDED: JType = RoundJoin;      break;
00209         default:
00210         case cdrfJOINSTYLE_BEVEL:   JType = BevelledJoin;   break;
00211     }
00212     
00213     // set the cap style
00214     LineCapType CType;
00215     switch(CDRDATA_WORD(Out->EndStyle))
00216     {
00217         case cdrfENDSTYLE_BUTT:     CType = LineCapButt;    break;
00218         case cdrfENDSTYLE_ROUNDED:  CType = LineCapRound;   break;
00219         default:
00220         case cdrfENDSTYLE_SQUARE:   CType = LineCapSquare;  break;
00221 
00222     }
00223 
00224     // set the dash pattern
00225     DashRec Dash;
00226     DashElement DashArray[cdrfMAX_DASH_ELEMENTS];
00227     if(CDRDATA_WORD(Out->NDashSegments) > 0 && (CDRDATA_WORD(Out->Flags) & cdrfOUTLINEFLAGS_NODASH) == 0)
00228     {
00229         // set a dash pattern
00230         INT32 NSeg = CDRDATA_WORD(Out->NDashSegments);
00231         if(NSeg > cdrfMAX_DASH_ELEMENTS)
00232             NSeg = cdrfMAX_DASH_ELEMENTS;
00233 
00234         INT32 l;
00235         for(l = 0; l < NSeg; l++)
00236         {
00237             DashArray[l] = CDRDATA_WORD(Out->DashSegments[l]) * LineWidth;
00238         }
00239 
00240         Dash.Elements = NSeg;
00241         Dash.DashStart = 0;
00242         Dash.ElementData = DashArray;
00243 
00244         Dash.LineWidth = LineWidth;
00245         Dash.ScaleWithLineWidth = TRUE;
00246         Dash.DashID = -1;
00247     }
00248     else
00249     {
00250         // no dash pattern
00251         Dash = SD_SOLID;
00252     }
00253 
00254     // set the attributes
00255     if(!SetLineWidth(LineWidth) || !SetLineColour(Col) || !SetJoinType(JType)
00256             || !SetLineCap(CType) || !SetDashPattern(Dash))
00257         return FALSE;
00258 
00259     // check for arrowheads
00260     if(CDRDATA_DWORD(Out->StartArrowReference) != 0 || CDRDATA_DWORD(Out->EndArrowReference) != 0)
00261     {
00262         // apply the attributes to the object
00263         // If not filled, then set the ignore bit on the fill attribute.
00264         if (ObjFilled == FALSE)
00265             CurrentAttrs[ATTR_FILLGEOMETRY].Ignore = TRUE;
00266 
00267         // Add attributes to the path, if they are different from the default...
00268         AttributeManager::ApplyBasedOnDefaults(pMadeNode, CurrentAttrs);
00269 
00270     //  DeleteCurrentAttrs();
00271     //  SetUpCurrentAttrs();
00272 
00273         // Enable the fill attribute again
00274         CurrentAttrs[ATTR_FILLGEOMETRY].Ignore = FALSE;
00275 
00276         // ensure that the attributes won't be applied again
00277         AttrsAlreadyApplied = TRUE;
00278 
00279         // apply arrow heads to the path
00280         AddArrowheadsToPath(CDRDATA_DWORD(Out->StartArrowReference), CDRDATA_DWORD(Out->EndArrowReference),
00281                 &Col, LineWidth, CType, JType);
00282     }
00283 
00284     return TRUE;
00285 }
00286 
00287 
00288 /********************************************************************************************
00289 
00290 >   BOOL CDRFilter::SetLineAttr3(cdrfOffsetHeader *Object)
00291 
00292     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00293     Created:    05/04/95
00294     Inputs:     address of line data *within* the main object data (loda chunk). Can be zero
00295     Returns:    error flag
00296     Purpose:    sets the line attributes for version 3 attributes
00297     SeeAlso:    Filter
00298 
00299 ********************************************************************************************/
00300 
00301 #define MAX_LINE_WIDTH  (4*72000)
00302 
00303 BOOL CDRFilter::SetLineAttr3(cdrfOffsetHeader *Object)
00304 {
00305     cdrfOutlineV3 *Out = (cdrfOutlineV3 *)FindDataInObject(Object, cdrfOBJOFFSETTYPE_LINE);
00306     
00307     if(Out == 0)
00308     {
00309         // if no outline data, or outline definitions couldn't be found, or outline
00310         // definition is too small, set up the default line attributes
00311         if(!SetLineWidth(cdrfOUTLINE_DEFAULT_WIDTH))
00312             return FALSE;
00313 
00314         PColourCMYK cmyk;
00315         cmyk.Cyan = cmyk.Magenta = cmyk.Yellow = 0;
00316         cmyk.Key = 255;
00317 
00318         DocColour Col;
00319         Col.SetCMYKValue(&cmyk);
00320     
00321         if(!SetLineColour(Col))
00322             return FALSE;
00323 
00324         return TRUE;
00325     }
00326 
00327     // check that this thingy should have an outline
00328     if((Out->Flags & cdrfOUTLINEFLAGSV3_STROKED) == 0)
00329     {
00330         if (!SetLineColour(DocColour(COLOUR_TRANS)))
00331             return FALSE;
00332 
00333         return TRUE;
00334     }
00335 
00336     // convert the line colour
00337     DocColour Col;
00338     ConvertColour((cdrfColour *)&Out->Colour, &Col);
00339 
00340     // find the line width
00341     INT32 LineWidth = CDRDATA_WORD(Out->LineThickness) * CDRCOORDS_TO_MILLIPOINTS;
00342 
00343     if(LineWidth > MAX_LINE_WIDTH)
00344         LineWidth = MAX_LINE_WIDTH;
00345     
00346     // find the join type
00347     JointType JType;
00348     switch(CDRDATA_WORD(Out->JoinStyle))
00349     {
00350         case cdrfJOINSTYLE_SQUARE:  JType = MitreJoin;      break;
00351         case cdrfJOINSTYLE_ROUNDED: JType = RoundJoin;      break;
00352         default:
00353         case cdrfJOINSTYLE_BEVEL:   JType = BevelledJoin;   break;
00354     }
00355     
00356     // set the cap style
00357     LineCapType CType;
00358     switch(Out->EndStyle)  // byte
00359     {
00360         case cdrfENDSTYLE_BUTT:     CType = LineCapButt;    break;
00361         case cdrfENDSTYLE_ROUNDED:  CType = LineCapRound;   break;
00362         default:
00363         case cdrfENDSTYLE_SQUARE:   CType = LineCapSquare;  break;
00364 
00365     }
00366 
00367     // set the dash pattern
00368 /*  DashRec Dash;
00369     DashElement DashArray[cdrfMAX_DASH_ELEMENTS];
00370     if((ObjectFlagsV3 & cdrfOBJFLAGSV3_NODASH) == 0 && Out->NDashSegments > 0)      // byte
00371     {
00372         // set a dash pattern
00373         INT32 NSeg = CDRDATA_WORD(Out->NDashSegments);
00374         if(NSeg > cdrfMAX_DASH_ELEMENTS)
00375             NSeg = cdrfMAX_DASH_ELEMENTS;
00376 
00377         INT32 l;
00378         for(l = 0; l < NSeg; l++)
00379         {
00380             DashArray[l] = Out->DashSegments[l] * LineWidth;  // byte
00381         }
00382 
00383         Dash.Elements = NSeg;
00384         Dash.DashStart = 0;
00385         Dash.ElementData = DashArray;
00386 
00387         Dash.LineWidth = LineWidth;
00388         Dash.ScaleWithLineWidth = TRUE;
00389         Dash.DashID = -1;
00390     }
00391     else
00392     {
00393         // no dash pattern
00394         Dash = SD_SOLID;
00395     }
00396 */
00397     // set the attributes
00398     if(!SetLineWidth(LineWidth) || !SetLineColour(Col) || !SetJoinType(JType)
00399             || !SetLineCap(CType)/* || !SetDashPattern(Dash)*/)
00400         return FALSE;
00401 
00402     // check for arrowheads
00403     if(CDRDATA_DWORD(Out->StartArrowReference) != 0 || CDRDATA_DWORD(Out->EndArrowReference) != 0)
00404     {
00405         // apply the attributes to the object
00406         // If not filled, then set the ignore bit on the fill attribute.
00407         if (ObjFilled == FALSE)
00408             CurrentAttrs[ATTR_FILLGEOMETRY].Ignore = TRUE;
00409 
00410         // Add attributes to the path, if they are different from the default...
00411         AttributeManager::ApplyBasedOnDefaults(pMadeNode, CurrentAttrs);
00412 
00413         // Enable the fill attribute again
00414         CurrentAttrs[ATTR_FILLGEOMETRY].Ignore = FALSE;
00415 
00416         // ensure that the attributes won't be applied again
00417         AttrsAlreadyApplied = TRUE;
00418 
00419         // apply arrow heads to the path
00420         AddArrowheadsToPath(CDRDATA_DWORD(Out->StartArrowReference), CDRDATA_DWORD(Out->EndArrowReference),
00421                 &Col, LineWidth, CType, JType);
00422     }
00423 
00424     return TRUE;
00425 }
00426 
00427 
00428 /********************************************************************************************
00429 
00430 >   BOOL CDRFilter::AddAttributesToArrowheadNode(NodeRenderableBounded *N, DocColour *Col, INT32 LineWidth,
00431         LineCapType Cap, JointType Join);
00432 
00433     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00434     Created:    29 03 95
00435     Inputs:     node, colour and line width
00436     Returns:    error flag
00437     Purpose:    apply attributes to a arrow head node
00438     SeeAlso:    Filter
00439 
00440 ********************************************************************************************/
00441 
00442 BOOL CDRFilter::AddAttributesToArrowheadNode(NodeRenderableBounded *N, DocColour *Col, INT32 LineWidth,
00443         LineCapType Cap, JointType Join)
00444 {
00445     if(IS_A(N, NodeGroup))
00446     {
00447         // go through all the members of the group setting their attributes
00448         Node *pNode;
00449 
00450         pNode = N->FindFirstChild();
00451 
00452         while(pNode != 0)
00453         {
00454             if(IS_A(pNode, NodePath))
00455                 AddAttributesToArrowheadPath((NodePath *)pNode, Col, LineWidth, Cap, Join);
00456             
00457             pNode = pNode->FindNext();
00458         }
00459     } else if(IS_A(N, NodePath))
00460     {
00461         // simply apply the attributes to this path
00462         AddAttributesToArrowheadPath((NodePath *)N, Col, LineWidth, Cap, Join);
00463     } else {
00464         ERROR3("Something unexpected passed to AddAttributesToArrowheadNode");
00465     }
00466 
00467     return TRUE;
00468 }
00469 
00470 
00471 /********************************************************************************************
00472 
00473 >   BOOL CDRFilter::AddAttributesToArrowheadPath(NodePath *P, DocColour *Col, INT32 LineWidth,
00474         LineCapType Cap, JointType Join);
00475 
00476     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00477     Created:    29 03 95
00478     Inputs:     node, colour and line width
00479     Returns:    error flag
00480     Purpose:    apply attributes to a arrow head path
00481     SeeAlso:    Filter
00482 
00483 ********************************************************************************************/
00484 
00485 BOOL CDRFilter::AddAttributesToArrowheadPath(NodePath *P, DocColour *Col, INT32 LineWidth,
00486         LineCapType Cap, JointType Join)
00487 {
00488     if(P->InkPath.IsFilled)
00489     {
00490         // it's a filled path, so it need to be filled with the colour and have no line
00491         // colour
00492         SetPathFilled(TRUE);
00493         if(!SetLineColour(DocColour(COLOUR_TRANS)) || !SetFillColour(*Col))
00494             return FALSE;
00495     } else {
00496         // it's not a filled colour, so don't fill it and stroke it with the line width and colour
00497         if(!SetLineColour(*Col) || !SetLineWidth(LineWidth) || !SetLineCap(Cap) || !SetJoinType(Join))
00498             return FALSE;
00499     }
00500 
00501     // apply the attributes to the object
00502     // If not filled, then set the ignore bit on the fill attribute.
00503 //  if (P->InkPath.IsFilled == FALSE)
00504 //      CurrentAttrs[ATTR_FILLGEOMETRY].Ignore = TRUE;
00505 //  else
00506         CurrentAttrs[ATTR_FILLGEOMETRY].Ignore = FALSE;
00507 
00508     // Add attributes to the path, if they are different from the default...
00509     BOOL Result = AttributeManager::ApplyBasedOnDefaults(P, CurrentAttrs);
00510 
00511     //  DeleteCurrentAttrs();
00512     //  SetUpCurrentAttrs();
00513 
00514     // Enable the fill attribute again
00515     CurrentAttrs[ATTR_FILLGEOMETRY].Ignore = FALSE;
00516 
00517     return Result;
00518 }
00519         
00520 /********************************************************************************************
00521 
00522 >   BOOL CDRFilter::DoesPathNeedArrowheads(NodePath *P)
00523 
00524     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00525     Created:    29 03 95
00526     Inputs:     NodePath to search
00527     Returns:    whether the path need some arrowheads
00528     Purpose:    To find out whether a path need attributes
00529     SeeAlso:    Filter
00530 
00531 ********************************************************************************************/
00532         
00533 BOOL CDRFilter::DoesPathNeedArrowheads(NodePath *P)
00534 {
00535     // if the number of end points is greater than 0, then it needs some arrowheads
00536     if(P->InkPath.GetNumEndPoints() > 0)
00537         return TRUE;
00538 
00539     return FALSE;
00540 }
00541 
00542 
00543 /********************************************************************************************
00544 
00545 >   BOOL CDRFilter::TransformArrowhead(NodePath *N, DocCoord *Point, DocCoord *Other,
00546         BOOL Start, INT32 LineWidth, INT32 Distance)
00547 
00548     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00549     Created:    29 03 95
00550     Inputs:     The path to transform, the This coordsinate (the coordinate to apply it to) and the 
00551                 previous coordinate (the one before or after it), whether it's a start one or not
00552                 and the line width and the distance to shift it from the arrow definition. 
00553     Returns:    error flag
00554     Purpose:    transform an arrowhead path to be the correct size and orientation
00555     SeeAlso:    Filter
00556 
00557 ********************************************************************************************/
00558         
00559 BOOL CDRFilter::TransformArrowhead(NodeRenderableBounded *N, DocCoord *Point, DocCoord *Other, BOOL Start,
00560          INT32 LineWidth, INT32 Distance)
00561 {
00562     // first of all, work out how much we need to scale this thingy by
00563     double Scale = (double)LineWidth / (double)cdrfARROWHEAD_LINEWIDTH;
00564 
00565     // work out the adj and opp side of the triangle we're going to rotate around
00566     double Adj = (double)Point->x - (double)Other->x;
00567     double Opp = (double)Point->y - (double)Other->y;
00568     
00569     // work out the hyp of the triangle
00570     double Hyp = sqrt((Adj * Adj) + (Opp * Opp));
00571 
00572     // how far we need to move the arrowhead by
00573     double Move = Scale * (double)Distance;
00574 
00575     // calculate a matrix
00576     double a, b, c, d, e, f;
00577     if(Hyp == 0)
00578     {
00579         // default thing which shouldn't do too much hard - avoid div by zero
00580         a = Scale;
00581         b = 0;
00582         c = 0;
00583         d = Scale;
00584         e = Point->x + Move;
00585         f = Point->y;
00586     } else {
00587         double cosTheta = (Adj / Hyp);
00588         double sinTheta = (Opp / Hyp);
00589 
00590         a = Scale * cosTheta;
00591         b = Scale * sinTheta;
00592         c = 0 - (Scale * sinTheta);
00593         d = Scale * cosTheta;
00594         e = Point->x + (Move * cosTheta);
00595         f = Point->y + (Move * sinTheta);
00596     }
00597 
00598     // knock up a matrix
00599     Matrix M = Matrix(a, b, c, d, (INT32)e, (INT32)f);
00600 
00601     // need to flip it over?
00602     if(Start)
00603     {
00604         Matrix F = Matrix(1, 0, 0, -1, 0, 0);
00605 
00606         M = F * M;
00607     }
00608 
00609     // transform the node
00610     Trans2DMatrix Trans(M);
00611 
00612     N->Transform(Trans);
00613 
00614     return TRUE;
00615 }
00616 
00617 
00618 /********************************************************************************************
00619 
00620 >   BOOL CDRFilter::AddArrowheadsToPath(DWORD StartArrow, DWORD EndArrow, DocColour *Col, INT32 LineWidth,
00621             LineCapType Cap, JointType Join)
00622 
00623     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00624     Created:    29 03 95
00625     Inputs:     
00626     Returns:    error flag
00627     Purpose:    adds arrowheads to a path. Changes pMadeNode from a path to a group
00628     SeeAlso:    Filter
00629 
00630 ********************************************************************************************/
00631         
00632 BOOL CDRFilter::AddArrowheadsToPath(DWORD StartArrow, DWORD EndArrow, DocColour *Col, INT32 LineWidth,
00633             LineCapType Cap, JointType Join)
00634 {
00635     if(!IS_A(pMadeNode, NodePath))
00636         return TRUE;            // don't apply arrowheads to non path things
00637 
00638     NodePath *pPath = (NodePath *)pMadeNode;
00639 
00640     // check that the path actaully needs some arrow heads
00641     if(!DoesPathNeedArrowheads(pPath) || (StartArrow == 0 && EndArrow == 0))
00642         return TRUE;
00643     
00644     // get pointers to nodes of the arrow heads to copy
00645     NodeRenderableBounded *StartA = 0;
00646     NodeRenderableBounded *EndA = 0;
00647     INT32 StartDistance;
00648     INT32 EndDistance;
00649     if(StartArrow != 0)
00650     {
00651         BOOL NotPresent;
00652         StartA = Arrowheads.GetConvertedNode(StartArrow, &StartDistance, &NotPresent);
00653 
00654         if(StartA == 0 && NotPresent == FALSE)
00655             return FALSE;   // error occurred
00656     }
00657     if(EndArrow != 0)
00658     {
00659         BOOL NotPresent;
00660         EndA = Arrowheads.GetConvertedNode(EndArrow, &EndDistance, &NotPresent);
00661 
00662         if(EndA == 0 && NotPresent == FALSE)
00663             return FALSE;   // error occurred
00664     }
00665 
00666     // check that enough arrowheads were found to do something with
00667     if(StartA == 0 && EndA == 0)
00668         return TRUE;
00669 
00670     // get rid of any dash patterns
00671     DashRec NoDash;
00672     NoDash = SD_SOLID;
00673     SetDashPattern(NoDash);
00674 
00675     // get some info about the path
00676     DocCoord *Coords = pPath->InkPath.GetCoordArray();
00677     PathVerb *Verbs = pPath->InkPath.GetVerbArray();
00678     INT32 NCoords = pPath->InkPath.GetNumCoords();
00679     INT32 SubPathStart = -1;        // the number of the coord the sub path starts on
00680     INT32 SubPathEnd = -1;          // the number of the coord the sub path ends on
00681 
00682     // set up a pointers for the nodes we're about to create - it points to the made
00683     // at first, but shuffles on as nodes are copied. You see, we have to copy nodes which
00684     // are attached to something
00685     NodeRenderableBounded *ThisNode = pPath;
00686 
00687     // work out the trim distances
00688     double StartTrimDistance;
00689     double EndTrimDistance;
00690     if(StartA != 0)
00691         StartTrimDistance = ((double)LineWidth / (double)cdrfARROWHEAD_LINEWIDTH) * (double)StartDistance;
00692     if(EndA != 0)
00693         EndTrimDistance = ((double)LineWidth / (double)cdrfARROWHEAD_LINEWIDTH) * (double)EndDistance;
00694 
00695     // run through all the coords
00696     INT32 c;
00697     for(c = 0; c < NCoords; c++)
00698     {
00699         UINT32 Verb = Verbs[c] & ~PT_CLOSEFIGURE;
00700         BOOL CloseHere = ((Verbs[c] & PT_CLOSEFIGURE) != 0)?TRUE:FALSE;
00701         
00702         // if the verb is a close figure, this sub path is close, so we can't add arrowheads
00703         // to it. Invalidate the path start to avoid getting any arrowheads
00704         if(CloseHere)
00705             SubPathStart = -1;
00706         
00707         // if we get a new moveto and the sub path start is valid then we have a applying arrowheads
00708         // situation
00709         if((Verb == PT_MOVETO || ((c == (NCoords - 1)) && !CloseHere)) && c != 0)
00710         {
00711             // set the sub path end
00712             if(Verb == PT_MOVETO)
00713             {
00714                 // if it's a moveto, then the sub path end was at the previous coord
00715                 SubPathEnd = c - 1;
00716             } else {
00717                 // if it wasn't, then it's this one (end of path)
00718                 SubPathEnd = c;
00719             }
00720         }
00721 
00722         // have we got a valid start path marker?
00723 
00724         if(SubPathStart != -1 && SubPathEnd != -1)
00725         {
00726             // OK, now we need to trim the sub path
00727             if(StartA != 0)
00728             {
00729                 // trim the start of the path if the next element is a line
00730                 if((Verbs[SubPathStart + 1] & ~PT_CLOSEFIGURE) == PT_LINETO)
00731                 {
00732                     double dx, dy;
00733                     dx = Coords[SubPathStart + 1].x - Coords[SubPathStart].x;
00734                     dy = Coords[SubPathStart + 1].y - Coords[SubPathStart].y;
00735                     double len = sqrt((dx * dx) + (dy * dy));
00736                     // if the resulting path line leaves enough room, trim it
00737                     if((len - StartTrimDistance) >= 32.0)
00738                     {
00739                         double factor = StartTrimDistance / len;
00740                         dx *= factor;
00741                         Coords[SubPathStart].x += (INT32)dx;
00742                         dy *= factor;
00743                         Coords[SubPathStart].y += (INT32)dy;
00744                     }
00745                 }
00746                 
00747                 // now pop an arrowhead on the resulting point
00748 
00749                 // first, make a copy of our node
00750                 if(!StartA->CopyNode(ThisNode, NEXT))
00751                     return FALSE;   // error!
00752 
00753                 ThisNode = (NodeRenderableBounded *)ThisNode->FindNext();
00754                 ERROR3IF(ThisNode == 0, "CopyNode returned a zero path but didn't complain");
00755                 ERROR3IF(ThisNode->IsKindOf(CC_RUNTIME_CLASS(NodeRenderableBounded)) == FALSE, "copied thing isn't a renderable bounded node");
00756 
00757                 // transform it
00758                 if(!TransformArrowhead(ThisNode, &Coords[SubPathStart], &Coords[SubPathStart + 1],
00759                         TRUE, LineWidth, StartDistance))
00760                     return FALSE;
00761 
00762                 // and apply attributes to it
00763                 if(!AddAttributesToArrowheadNode(ThisNode, Col, LineWidth, Cap, Join))
00764                     return FALSE;       
00765             }
00766 
00767             // and the same for the end path
00768             if(EndA != 0)
00769             {
00770                 if((Verbs[SubPathEnd] & ~PT_CLOSEFIGURE) == PT_LINETO)
00771                 {
00772                     double dx, dy;
00773                     dx = Coords[SubPathEnd].x - Coords[SubPathEnd - 1].x;
00774                     dy = Coords[SubPathEnd].y - Coords[SubPathEnd - 1].y;
00775                     double len = sqrt((dx * dx) + (dy * dy));
00776                     // if the resulting path line leaves enough room, trim it
00777                     if((len - EndTrimDistance) >= 32.0)
00778                     {
00779                         double factor = EndTrimDistance / len;
00780                         dx *= factor;
00781                         Coords[SubPathEnd].x += (INT32)dx;
00782                         dy *= factor;
00783                         Coords[SubPathEnd].y += (INT32)dy;
00784                     }
00785                 }
00786                 
00787                 // now pop an arrowhead on the resulting point
00788 
00789                 // first, make a copy of our node
00790                 if(!EndA->CopyNode(ThisNode, NEXT))
00791                     return FALSE;   // error!
00792 
00793                 ThisNode = (NodeRenderableBounded *)ThisNode->FindNext();
00794                 ERROR3IF(ThisNode == 0, "CopyNode returned a zero path but didn't complain");
00795                 ERROR3IF(ThisNode->IsKindOf(CC_RUNTIME_CLASS(NodeRenderableBounded)) == FALSE, "copied thing isn't a renderable bounded node");
00796 
00797                 // transform it
00798                 if(!TransformArrowhead(ThisNode, &Coords[SubPathEnd], &Coords[SubPathEnd - 1],
00799                         FALSE, LineWidth, EndDistance))
00800                     return FALSE;
00801 
00802                 // and apply attributes to it
00803                 if(!AddAttributesToArrowheadNode(ThisNode, Col, LineWidth, Cap, Join))
00804                     return FALSE;               
00805             }
00806         
00807         }
00808             
00809         // set the new sub path start marker and invalidate the end point marker
00810         if(Verb == PT_MOVETO)
00811         {
00812             SubPathStart = c;
00813             SubPathEnd = -1;
00814         }
00815     }
00816 
00817 
00818     // ensure that the bounding rectangle is updated
00819     pPath->InvalidateBoundingRect();
00820 
00821     // get a new group node
00822     NodeGroup *pGroup = new NodeGroup;
00823     if(pGroup == 0)
00824         return FALSE;
00825     
00826     // attach everything to it
00827     pMadeNode->InsertChainSimple(pGroup, FIRSTCHILD);
00828 
00829     // and make the made node the group
00830     pMadeNode = pGroup;
00831     
00832     return TRUE;
00833 }
00834 
00835 
00836 /********************************************************************************************
00837 
00838 >   BOOL CDRArrowheadStore::AddChunkToStore(RIFFFile *RIFF)
00839 
00840     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00841     Created:    22 03 95
00842     Inputs:     A RIFFFile object
00843     Returns:    error flag
00844     Purpose:    Stores arrowhead chunks for the CDRFilter class
00845     SeeAlso:    CDRFilter, CDRAttributeStore
00846 
00847 ********************************************************************************************/
00848 
00849 BOOL CDRArrowheadStore::AddChunkToStore(RIFFFile *RIFF)
00850 {
00851     if(RIFF->GetObjType() != RIFFOBJECTTYPE_CHUNK)
00852     {
00853         ERROR2(FALSE, "CDRAttributeStore::AddChunkToStore called without a chunk in the RIFFFile");
00854     }
00855 
00856     // get a new item obect
00857     CDRArrowheadStoredItem *Item = new CDRArrowheadStoredItem;
00858 
00859     if(Item == 0)
00860         return FALSE;
00861 
00862     // get the data of the RIFF chunk
00863     if(!Item->Aquire(RIFF))
00864     {
00865         delete Item;
00866         return FALSE;
00867     }
00868 
00869     Item->Size = RIFF->GetObjSize();
00870 
00871     // and add the new item to the list
00872     AddTail(Item);
00873 
00874     return TRUE;
00875 }
00876 
00877 
00878 /********************************************************************************************
00879 
00880 >   NodeRenderableBounded *CDRArrowheadStore::GetConvertedNode(DWORD Reference, INT32 *Distance, BOOL *NotPresent)
00881 
00882     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
00883     Created:    29 03 95
00884     Inputs:     a DWORD reference
00885     Returns:    node pointer or 0 for an error
00886     Purpose:    gets a converted node for the arrow head which should be copied and
00887                 transformed. Converted nodes are cached. If *NotPresent is TRUE when 0 is
00888                 returned then the arrowhead couldn't be found rather than an error occuring
00889     SeeAlso:    CDRFilter, CDRAttributeStore
00890 
00891 ********************************************************************************************/
00892 
00893 #define GCN_LASTSUB_NONE    0
00894 #define GCN_LASTSUB_CLOSED  1
00895 #define GCN_LASTSUB_OPEN    2
00896 
00897 NodeRenderableBounded *CDRArrowheadStore::GetConvertedNode(DWORD Reference, INT32 *Distance, BOOL *NotPresent)
00898 {
00899     // set up the not present thingy
00900     *NotPresent = FALSE;
00901     
00902     // find the correct chunk
00903     CDRArrowheadStoredItem *Item;
00904     INT32 Size;
00905 
00906     if(IsEmpty())
00907         return 0;       // no items in the list
00908     
00909     Item = (CDRArrowheadStoredItem *)GetHead();
00910 
00911     // scan though the list looking for the reference
00912     while(Item != 0)
00913     {
00914         if(CDRDATA_DWORD(*((DWORD *)(Item->Block))) == Reference)
00915         {
00916             Size = Item->Size;
00917             break;
00918         }
00919 
00920         Item = (CDRArrowheadStoredItem *)GetNext(Item);
00921     }
00922     
00923     // did we find a chunk?
00924     if(Item == 0)
00925     {
00926         *NotPresent = TRUE;
00927         return 0;
00928     }
00929 
00930     // locate the coordinates
00931     cdrfArrowhead *Arrow = (cdrfArrowhead *)Item->Block;
00932     cdrfCoord *Coords = (cdrfCoord *)(Item->Block + CDRDATA_WORD(Arrow->CoordsOffset) + cdrfARROWHEAD_COORDOFF_CORRECT);
00933 
00934     // store the distance from the definitons
00935     *Distance = CDRDATA_SWORD(Arrow->Distance);
00936 
00937     // check to see if a cached pointer is available
00938     if(Item->pNode != 0)
00939         return Item->pNode;
00940 
00941     // OK, convert that arrowhead
00942 
00943     // this is not particularly pleasant. We need to scan though the coords creating a path,
00944     // each sub path must be a seperate path unless the next subpath has the same closedness
00945     // as the previous one, in which case it's a sub path.
00946     // this is because closed sub paths have different attributes to open ones. It's a nasty
00947     // system, and rather overcomplicated, but never mind.
00948 
00949     INT32 ThisType = GCN_LASTSUB_NONE;      // the type of this subpath
00950     INT32 LastType = GCN_LASTSUB_NONE;      // the type of the last subpath
00951     
00952     NodePath *FirstPath = 0;                // the first path in my set of paths
00953     NodePath *LastPath = 0;                 // the last path in my set of paths
00954     NodePath *ThisPath = 0;                 // the path I'm currently working on
00955 
00956     // check that the first node type is a move to avoid stuffing up my next bit
00957     if((Arrow->NodeTypes[0] & cdrfPATHCOORDTYPE_MASK) != cdrfPATHCOORDTYPE_MOVE)
00958     {
00959         // for now, if the first element isn't a move, pretend that it doesn't exist
00960         *NotPresent = TRUE;
00961         return 0;
00962     }
00963 
00964     INT32 CoordType;
00965 
00966     INT32 l;
00967     
00968     UINT32 Control1 = 0;        // number of first control point
00969     UINT32 Control2 = 0;        // of second
00970     DocCoord co, cn1, cn2;  // coordinates
00971     PathFlags Flags;
00972 
00973     INT32 NNodes = CDRDATA_WORD(Arrow->NNodes);
00974     BOOL NeedMoveTo = TRUE;
00975 
00976     // convert all the coordinates
00977     for(l = 0; l < NNodes; l++)
00978     {
00979         CoordType = Arrow->NodeTypes[l] & cdrfPATHCOORDTYPE_MASK;
00980 
00981         if(CoordType == cdrfPATHCOORDTYPE_MOVE || l == 0)
00982         {
00983             // start a new path!
00984             LastType = ThisType;
00985 
00986             // first of all, what type of path is this?
00987             if((Arrow->NodeTypes[l] & cdrfPATHCOORDATTR_CLOSE) != 0)
00988                 ThisType = GCN_LASTSUB_CLOSED;
00989             else
00990                 ThisType = GCN_LASTSUB_OPEN;
00991 
00992             // OK, do we need to start a new path?
00993             if(ThisType != LastType)
00994             {
00995                 // yep, attach the last one we did
00996                 if(ThisPath != 0)
00997                 {
00998                     // check that the path is OK
00999                     if(!ThisPath->InkPath.EnsureValid())
01000                     {
01001                         // no, it's completely knackered
01002                         delete ThisPath;
01003                         ThisPath = 0;
01004                     } else {    
01005                         // finish off the path
01006                         ThisPath->InvalidateBoundingRect();             
01007 
01008                         if(FirstPath == 0)
01009                             FirstPath = ThisPath;
01010 
01011                         if(LastPath != 0)
01012                             ThisPath->AttachNode(LastPath, NEXT);
01013 
01014                         LastPath = ThisPath;
01015 
01016                         ThisPath = 0;
01017                     }
01018                 }
01019 
01020                 // get a new path
01021                 ThisPath = new NodePath;
01022 
01023                 if(ThisPath == 0)
01024                     return 0;           // no path created. A bit of a pity
01025 
01026                 // set it up ready for conversion
01027                 if(!ThisPath->SetUpPath())
01028                     return 0;
01029         
01030                 ThisPath->InkPath.FindStartOfPath();
01031 
01032                 // set whether it's filled or not
01033                 if(ThisType == GCN_LASTSUB_CLOSED)
01034                 {
01035                     ThisPath->InkPath.IsFilled = TRUE;
01036                     ThisPath->InkPath.IsStroked = FALSE;
01037                 } else {
01038                     ThisPath->InkPath.IsFilled = FALSE;
01039                     ThisPath->InkPath.IsStroked = TRUE;
01040                 }
01041                 
01042             }
01043 
01044         }
01045 
01046         co.x = CDRDATA_SWORD(Coords[l].X);
01047         co.y = CDRDATA_SWORD(Coords[l].Y);
01048 
01049         // ensure we get all the move tos we need.
01050         if(NeedMoveTo && CoordType != cdrfPATHCOORDTYPE_MOVE)
01051         {
01052             if(!ThisPath->InkPath.InsertMoveTo(co))
01053                 return 0;
01054         }
01055 
01056         NeedMoveTo = FALSE;
01057 
01058         // convert the coordinates
01059         switch(CoordType)
01060         {
01061             case cdrfPATHCOORDTYPE_MOVE:
01062                 // add a move to this path
01063                 if(!ThisPath->InkPath.InsertMoveTo(co))
01064                     return 0;
01065                 break;
01066             
01067             case cdrfPATHCOORDTYPE_LINETO:
01068                 // add a line to this coord to the path
01069                 if(!ThisPath->InkPath.InsertLineTo(co))
01070                     return 0;
01071                 break;
01072             
01073             case cdrfPATHCOORDTYPE_CURVE:
01074                 // check we have some control points for this curve
01075                 // a control point cannot be the first coord, so it's OK to check against 0
01076                 if(Control1 == 0 || Control2 == 0)
01077                 {
01078 TRACEUSER( "Ben", _T("No control points for curve element\n"));
01079                     return 0;
01080                 }
01081 
01082                 // convert the control points
01083                 cn1.x = CDRDATA_SWORD(Coords[Control1].X);
01084                 cn1.y = CDRDATA_SWORD(Coords[Control1].Y);
01085                 cn2.x = CDRDATA_SWORD(Coords[Control2].X);
01086                 cn2.y = CDRDATA_SWORD(Coords[Control2].Y);
01087                 
01088                 // create the curve
01089                 Flags.IsSelected = FALSE;
01090                 Flags.IsSmooth = Flags.IsRotate = ((Arrow->NodeTypes[l] & cdrfPATHCOORDATTR_SMOOTH) != 0)?TRUE:FALSE;
01091                 Flags.IsEndPoint;
01092                 
01093                 // insert it into the path
01094                 if(!ThisPath->InkPath.InsertCurveTo(cn1, cn2, co, &Flags))
01095                     return 0;
01096                 break;
01097 
01098             case cdrfPATHCOORDTYPE_CONTROL:
01099                 // shuffle the control points we've already got and add the new one
01100                 Control1 = Control2;
01101                 Control2 = l;
01102                 break;
01103             
01104             default:
01105                 break;
01106         }
01107         
01108         // is this a close subpath situtation?
01109         if((Arrow->NodeTypes[l] & cdrfPATHCOORDATTR_CLOSE) != 0)
01110         {
01111             // close the sub path
01112             if(CoordType != cdrfPATHCOORDTYPE_MOVE)
01113             {
01114                 if(!ThisPath->InkPath.CloseSubPath())
01115                     return 0;
01116 
01117                 // check the next coord type
01118                 NeedMoveTo = TRUE;
01119             }
01120         }
01121     }
01122 
01123     // finish off the last path
01124     ThisPath->InvalidateBoundingRect();             
01125 
01126     // finish off this path we're doing
01127     if(ThisPath != 0)
01128     {
01129         if(FirstPath == 0)
01130             FirstPath = ThisPath;
01131 
01132         if(LastPath != 0)
01133             ThisPath->AttachNode(LastPath, NEXT);
01134 
01135         LastPath = ThisPath;
01136 
01137         ThisPath = 0;
01138     }
01139 
01140     // make up a nice group if there's more than one path
01141     NodeRenderableBounded *ToInsert = 0;
01142     if(FirstPath == LastPath)
01143     {
01144         ToInsert = FirstPath;
01145     } else {
01146         ToInsert = new NodeGroup;
01147 
01148         if(ToInsert == 0)
01149             return 0;
01150 
01151         FirstPath->InsertChainSimple(ToInsert, FIRSTCHILD);
01152     }
01153 
01154     Item->pNode = ToInsert;
01155 
01156     return ToInsert;
01157 }
01158 
01159 /********************************************************************************************
01160 
01161 >   CDRArrowheadStoredItem::CDRArrowheadStoredItem(void)
01162 
01163     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01164     Created:    29 03 95
01165     Inputs:     
01166     Returns:    
01167     Purpose:    Constructor
01168     SeeAlso:    CDRAttributeStore, CDRAttributeStoredItem
01169 
01170 ********************************************************************************************/
01171 
01172 CDRArrowheadStoredItem::CDRArrowheadStoredItem(void)
01173 {
01174     pNode = 0;
01175 }
01176 
01177 
01178 /********************************************************************************************
01179 
01180 >   CDRArrowheadStoredItem::~CDRArrowheadStoredItem(void)
01181 
01182     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01183     Created:    29 03 95
01184     Inputs:     
01185     Returns:    
01186     Purpose:    Destructor
01187     SeeAlso:    CDRAttributeStore, CDRAttributeStoredItem
01188 
01189 ********************************************************************************************/
01190 
01191 CDRArrowheadStoredItem::~CDRArrowheadStoredItem(void)
01192 {
01193     if(pNode != 0)
01194         pNode->CascadeDelete();
01195 
01196     delete pNode;
01197 }
01198 
01199 
01200 /*******************************************************************************************/
01201 
01202 typedef struct {
01203     BYTE C, M, Y, K;
01204     TCHAR *Name;
01205 } StandardCDRColour;
01206 
01207 static StandardCDRColour StandardCDRColours[] = {
01208     {0, 0,  0,  100,    "Black"},
01209     {0, 0,  0,  90, "90% Black"},
01210     {0, 0,  0,  80, "80% Black"},
01211     {0, 0,  0,  70, "70% Black"},
01212     {0, 0,  0,  60, "60% Black"},
01213     {0, 0,  0,  50, "50% Black"},
01214     {0, 0,  0,  40, "40% Black"},
01215     {0, 0,  0,  30, "30% Black"},
01216     {0, 0,  0,  20, "20% Black"},
01217     {0, 0,  0,  10, "10% Black"},
01218     {0, 0,  0,  0,  "White"},
01219     {100,   100,    0,  0,  "Blue"},
01220     {100,   0,  0,  0,  "Cyan"},
01221     {100,   0,  100,    0,  "Green"},
01222     {0, 0,  100,    0,  "Yellow"},
01223     {0, 100,    100,    0,  "Red"},
01224     {0, 100,    0,  0,  "Magenta"},
01225     {20,    80, 0,  20, "Purple"},
01226     {0, 60, 100,    0,  "Orange"},
01227     {0, 40, 20, 0,  "Pink"},
01228     {0, 20, 20, 60, "Dark Brown"},
01229     {20,    20, 0,  0,  "Powder Blue"},
01230     {40,    40, 0,  0,  "Pastel Blue"},
01231     {60,    40, 0,  0,  "Baby Blue"},
01232     {60,    60, 0,  0,  "Electric Blue"},
01233     {40,    40, 0,  20, "Twilight Blue"},
01234     {60,    40, 0,  40, "Navy Blue"},
01235     {40,    40, 0,  60, "Deep Navy Blue"},
01236     {40,    20, 0,  40, "Desert Blue"},
01237     {100,   20, 0,  0,  "Sky Blue"},
01238     {40,    0,  0,  0,  "Ice Blue"},
01239     {20,    0,  0,  20, "Light BlueGreen"},
01240     {20,    0,  0,  40, "Ocean Green"},
01241     {20,    0,  0,  60, "Moss Green"},
01242     {20,    0,  0,  80, "Dark Green"},
01243     {40,    0,  20, 60, "Forest Green"},
01244     {60,    0,  40, 40, "Grass Green"},
01245     {40,    0,  20, 40, "Kentucky Green"},
01246     {60,    0,  40, 20, "Light Green"},
01247     {60,    0,  60, 20, "Spring Green"},
01248     {60,    0,  20, 0,  "Turquoise"},
01249     {60,    0,  20, 20, "Sea Green"},
01250     {20,    0,  20, 20, "Faded Green"},
01251     {20,    0,  20, 0,  "Ghost Green"},
01252     {40,    0,  40, 0,  "Mint Green"},
01253     {20,    0,  20, 40, "Army Green"},
01254     {20,    0,  40, 40, "Avocado Green"},
01255     {20,    0,  60, 20, "Martian Green"},
01256     {20,    0,  40, 20, "Dull Green"},
01257     {40,    0,  100,    0,  "Chartreuse"},
01258     {20,    0,  60, 0,  "Moon Green"},
01259     {0, 0,  20, 80, "Murky Green"},
01260     {0, 0,  20, 60, "Olive Drab"},
01261     {0, 0,  20, 40, "Khaki"},
01262     {0, 0,  40, 40, "Olive"},
01263     {0, 0,  60, 20, "Banana Yellow"},
01264     {0, 0,  60, 0,  "Light Yellow"},
01265     {0, 0,  40, 0,  "Chalk"},
01266     {0, 0,  20, 0,  "Pale Yellow"},
01267     {0, 20, 40, 40, "Brown"},
01268     {0, 40, 60, 20, "Red Brown"},
01269     {0, 20, 60, 20, "Gold"},
01270     {0, 60, 80, 0,  "Autumn Orange"},
01271     {0, 40, 80, 0,  "Light Orange"},
01272     {0, 40, 60, 0,  "Peach"},
01273     {0, 20, 100,    0,  "Deep Yellow"},
01274     {0, 20, 40, 0,  "Sand"},
01275     {0, 20, 40, 60, "Walnut"},
01276     {0, 60, 60, 40, "Ruby Red"},
01277     {0, 60, 80, 20, "Brick Red"},
01278     {0, 60, 60, 0,  "Tropical Pink"},
01279     {0, 40, 40, 0,  "Soft Pink"},
01280     {0, 20, 20, 0,  "Faded Pink"},
01281     {0, 40, 20, 40, "Crimson"},
01282     {0, 60, 40, 20, "Regal Red"},
01283     {0, 60, 20, 20, "Deep Rose"},
01284     {0, 100,    60, 0,  "Neon Red"},
01285     {0, 60, 40, 0,  "Deep Pink"},
01286     {0, 80, 40, 0,  "Hot Pink"},
01287     {0, 40, 20, 20, "Dusty Rose"},
01288     {0, 40, 0,  60, "Plum"},
01289     {0, 60, 0,  40, "Deep Violet"},
01290     {0, 40, 0,  0,  "Light Violet"},
01291     {0, 40, 0,  20, "Violet"},
01292     {0, 20, 0,  40, "Dusty Plum"},
01293     {0, 20, 0,  20, "Pale Purple"},
01294     {20,    60, 0,  20, "Majestic Purple"},
01295     {20,    80, 0,  0,  "Neon Purple"},
01296     {20,    60, 0,  0,  "Light Purple"},
01297     {20,    40, 0,  20, "Twilight Violet"},
01298     {20,    40, 0,  0,  "Easter Purple"},
01299     {20,    40, 0,  60, "Deep Purple"},
01300     {20,    40, 0,  40, "Grape"},
01301     {40,    60, 0,  0,  "Blue Violet"},
01302     {40,    100,    0,  0,  "Blue Purple"},
01303     {40,    80, 0,  20, "Deep River"},
01304     {60,    80, 0,  0,  "Deep Azure"},
01305     {40,    60, 0,  40, "Storm Blue"},
01306     {60,    80, 0,  20, "Deep Blue"},
01307     {100,   100,    100,    100,    "100C100M100Y100K"}
01308 };
01309 
01310 /********************************************************************************************
01311 
01312 >   BOOL CDRFilter::AddStandardColourSet(Document *pDocument)
01313 
01314     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01315     Created:    05/06/95
01316     Inputs:     
01317     Returns:    
01318     Purpose:    Adds the standard set of colours to a Corel file
01319 
01320 ********************************************************************************************/
01321 
01322 BOOL CDRFilter::AddStandardColourSet(Document *pDocument)
01323 {
01324     ColourListComponent *pColours = 0;
01325 
01326     DocComponent *pComponent = pDocument->EnumerateDocComponents(NULL);
01327 
01328     while (pComponent != NULL)
01329     {
01330         // If this is the colour component, remember it
01331         if (pComponent->GetRuntimeClass() == CC_RUNTIME_CLASS(ColourListComponent))
01332         {
01333             pColours = (ColourListComponent *) pComponent;
01334             break;
01335         }
01336 
01337         // Look for next doc component
01338         pComponent = pDocument->EnumerateDocComponents(pComponent);
01339     }
01340 
01341     if(pColours == 0)
01342         return TRUE;            // can't be bothered to complain nicely about this very unlikely error
01343 
01344     // get an importedcolours object
01345     ImportedColours *pNewColours = new ImportedColours(pColours, FALSE);
01346     if(pNewColours == 0 || !pNewColours->Init())
01347         return FALSE;
01348 
01349     BOOL ok = TRUE;
01350 
01351     // add colours to it...
01352     ColourCMYK NewColour;
01353     for(INT32 l = 0; l < (sizeof(StandardCDRColours) / sizeof(StandardCDRColour)); l++)
01354     {
01355         NewColour.Cyan = ((double)StandardCDRColours[l].C) / 100;
01356         NewColour.Magenta = ((double)StandardCDRColours[l].M) / 100;
01357         NewColour.Yellow = ((double)StandardCDRColours[l].Y) / 100;
01358         NewColour.Key = ((double)StandardCDRColours[l].K) / 100;
01359         
01360         String_64 ColNameS(StandardCDRColours[l].Name);
01361         if(!pNewColours->AddColour(&ColNameS, &NewColour))
01362         {
01363             ok = FALSE;
01364             break;
01365         }
01366     }
01367 
01368     // add the colours to the document
01369     if(ok)
01370     {
01371         pNewColours->AddColoursToDocument();
01372     }
01373     else
01374     {
01375         pNewColours->DestroyColours();
01376     }
01377 
01378     // delete the imported colours object
01379     delete pNewColours;
01380 
01381     return ok;
01382 }
01383 

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