coplfilr.cpp

Go to the documentation of this file.
00001 // $Id: coplfilr.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 
00099 /*
00100 */
00101 
00102 #include "camtypes.h"
00103 #include "coplfilr.h"
00104 
00105 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00106 //#include "ccfile.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00107 #include "cdrcol.h"
00108 //#include "oilfltrs.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00109 #include "optsunit.h"
00110 #include "progress.h"
00111 #include "scunit.h"
00112 #include "sgcolour.h"
00113 //#include "isetres.h"
00114 
00115 //#include "ben.h"
00116 //#include "filtrres.h"
00117 //#include "peter.h"
00118 //#include "will2.h"
00119 
00120 DECLARE_SOURCE("$Revision: 1282 $");
00121 
00122 CC_IMPLEMENT_DYNAMIC(PaletteFilter, Filter)
00123 CC_IMPLEMENT_DYNAMIC(CorelPaletteFilter, PaletteFilter)
00124 CC_IMPLEMENT_DYNAMIC(MSPaletteFilter, PaletteFilter)
00125 CC_IMPLEMENT_DYNAMIC(AdobeColourTableFilter, PaletteFilter)
00126 CC_IMPLEMENT_DYNAMIC(AdobeColourSwatchFilter, PaletteFilter)
00127 CC_IMPLEMENT_DYNAMIC(JCWColourFilter, PaletteFilter)
00128 CC_IMPLEMENT_DYNAMIC(PaintShopProPaletteFilter, PaletteFilter)
00129 
00130 #define new CAM_DEBUG_NEW
00131 
00132 typedef struct {
00133     WORD Unknown;
00134     BYTE Entries[2];
00135 } cpl_header;
00136 
00137 #define CPL_MIN_ENTRY_SIZE      14      // minimum size of an entry in a cpl file
00138 #define CPL_MAX_ENTRY_SIZE      (13+32) // max size
00139 #define CPL_CHECK_TEXT_START    16      // place to start checking the text
00140 #define CPF_MAX_COLNAME_SIZE 32
00141 
00142 #define CPL_FVU     -1      // version unknown
00143 #define CPL_FV4     4       // version 4
00144 #define CPL_FV5     5       // version 5
00145 
00146 
00147 
00148 /********************************************************************************************
00149 >   PaletteFilter::PaletteFilter()
00150 
00151     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00152     Created:    30/4/96
00153     Inputs:     -
00154     Returns:    -
00155     Purpose:    Constructor for a base palette filter
00156     SeeAlso:    Filter
00157 ********************************************************************************************/
00158 PaletteFilter::PaletteFilter()
00159 {
00160     m_pNewColours = NULL;
00161 
00162     ImportIntoGallery = TRUE;
00163     CurrentGalleryGroup = NULL;
00164 }
00165 
00166 
00167 /********************************************************************************************
00168 >   PaletteFilter::~PaletteFilter()
00169 
00170     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00171     Created:    30/4/96
00172     Inputs:     -
00173     Returns:    -
00174     Purpose:    Destructor for a base palette filter
00175     SeeAlso:    Filter
00176 ********************************************************************************************/
00177 PaletteFilter::~PaletteFilter()
00178 {
00179     if (m_pNewColours != NULL)
00180     {
00181         m_pNewColours->DestroyColours();
00182         delete m_pNewColours;
00183         m_pNewColours = NULL;
00184     }
00185 }
00186 
00187 
00188 /********************************************************************************************
00189 >   virtual BOOL PaletteFilter::IsDefaultDocRequired(const TCHAR* pcszPathName)
00190 
00191     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00192     Created:    30/4/96
00193     Inputs:     pcszPathName - pointer to the name of the file that is about to be imported
00194     Returns:    TRUE if a document is required to import this file into,
00195                 FALSE if file supplies the document
00196     Purpose:    For determining wether this filter needs a document to be created to import
00197                 into.
00198 ********************************************************************************************/
00199 BOOL PaletteFilter::IsDefaultDocRequired(const TCHAR* pcszPathName)
00200 {
00201     // Since palette files are unlikely to supply a document we will return TRUE.
00202     // Derived classes can still virtually override this function and return FALSE if required.
00203 
00204     return TRUE;
00205 }
00206 
00207 
00208 /********************************************************************************************
00209 >   virtual BOOL PaletteFilter::DoImport(SelOperation* pOp, CCLexFile* pFile, Document* pDoc, BOOL AutoChosen, ImportPosition *Pos,
00210                              KernelBitmap** ppImportedBitmap, DocCoord* pPosTranslate, String_256* URL)
00211 
00212     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00213     Created:    30/4/96
00214     Inputs:     pOp     - The operation this import is running under
00215                 pFile   - The file to import from
00216                 pDoc    - The document to import into
00217                 AutoChosen  - TRUE if this filter was chosen by the system, FALSE if chosen by the user
00218                 ImportPos   - The position to import the file data at
00219                 Pos -
00220                 ppImportedBitmap - this is used mainly in the bitfltr.cpp for the HTML
00221                 import filter. HTMLFilter::DoImport() needs a pointer to a kernel bitmap
00222                 to set the background bitmap up into Camelot.
00223                 pPosTranslate - This is used too by the HTMLFilter in order to do a formatting.
00224                 URL - original URL of the imported file
00225     Returns:    TRUE for successful import, FALSE if an error occured.
00226     Purpose:    Base class for handling palette import
00227 
00228     Notes:      **** IMPORTANT **************************************************************
00229                 Palette filters can be called directly from the colour gallery (sgcolour.cpp)
00230                 library groups to import palette files directly into the gallery.
00231                 In this case, pOp and pDoc are NULL, and the member vars CurrentGalleryGroup
00232                 and ImportIntoGallery are set up suitably. It is this important that these
00233                 filters continue to be happy about not importing into a document!
00234                 *****************************************************************************
00235 
00236     SeeAlso:    Filter::DoImport
00237 ********************************************************************************************/
00238 BOOL PaletteFilter::DoImport(SelOperation* pOp, CCLexFile* pFile, Document* pDoc, BOOL AutoChosen, ImportPosition *Pos,
00239                              KernelBitmap** ppImportedBitmap, DocCoord* pPosTranslate, String_256* URL)
00240 {
00241     BOOL ok = TRUE;
00242 
00243     // Copy parameters into member vars.
00244     // NOTE that we allow pOp and pDoc to be NULL, when we are importing into a gallery!
00245     ERROR2IF(pFile==NULL, FALSE, "NULL parameter passed");
00246     m_pImportOp = pOp;
00247     m_pImportFile = pFile;
00248     m_pImportDoc = pDoc;
00249 
00250     // Determine if this is really a huge bodge and we're importing directly into the colour gallery
00251 #if !defined(EXCLUDE_FROM_RALPH) && !defined(EXCLUDE_FROM_XARALX)
00252     //ColourSGallery *ParentGal = (ColourSGallery *) OpDisplayColourGallery::FindGallery();
00253     ColourSGallery *ParentGal = ColourSGallery::GetInstance();
00254     if (ParentGal != NULL)
00255         CurrentGalleryGroup = ParentGal->GetCurrentImportGroup();
00256     else
00257 #endif
00258         CurrentGalleryGroup = NULL;
00259 
00260     ImportIntoGallery = (CurrentGalleryGroup != NULL);
00261     ERROR2IF(!ImportIntoGallery && (pDoc == NULL || pOp == NULL), FALSE, "NULL doc/op when not importing into gallery");
00262 
00263     // Initialise base class services
00264     if (ok)
00265         ok = PrepareForImport();
00266 
00267     // Call derived loading functions                                                                                   
00268     if (ok)
00269         ok = PreImport();
00270     if (ok)
00271         ok = ImportPalette();
00272     if (ok)
00273         ok = PostImport();
00274 
00275     // Finialise base class importation
00276     if (ok)
00277         ok = FinishImport(TRUE);
00278     else
00279         FinishImport(FALSE);
00280 
00281     CurrentGalleryGroup = NULL;
00282     ImportIntoGallery = FALSE;
00283 
00284     return ok;
00285 }
00286 
00287 
00288 /********************************************************************************************
00289 >   virtual BOOL PaletteFilter::DoExport(Operation* pOp, CCLexFile* pFile,
00290                                          PathName* pPath, Document* pDoc,
00291                                          BOOL ShowOptions)
00292     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00293     Created:    30/4/96
00294     Inputs:     pOp         - The operation this import is running under
00295                 pFile       - The file to import from
00296                 pPath       - Importing path
00297                 pDoc        - The document to import into
00298                 ShowOptions - Show the export options dialogue.
00299     Outputs:    -
00300     Returns:    TRUE for successful export, FALSE if an error occured.
00301     Purpose:    Base class for handling palette export
00302     SeeAlso:    Filter::DoImport
00303 ********************************************************************************************/
00304 BOOL PaletteFilter::DoExport(Operation* pOp, CCLexFile* pFile,
00305                              PathName* pPath, Document* pDoc,
00306                              BOOL ShowOptions)
00307 {
00308     // For the moment palettes are not exported.
00309     return FALSE;
00310 }
00311 
00312 
00313 /********************************************************************************************
00314 >   BOOL PaletteFilter::PrepareForImport()
00315 
00316     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00317     Created:    1/5/96
00318     Inputs:     -
00319     Outputs:    -
00320     Returns:    TRUE for success, FALSE if an error occured.
00321     Purpose:    Initialises the base class before import
00322 ********************************************************************************************/
00323 BOOL PaletteFilter::PrepareForImport()
00324 {
00325     if (!ImportIntoGallery)
00326     {
00327         ERROR2IF(m_pImportDoc==NULL, FALSE, "NULL pointer");
00328 
00329         // Find the colour list document component
00330         ColourListComponent* pColours = NULL;
00331         DocComponent *pComponent = m_pImportDoc->EnumerateDocComponents(NULL);
00332         while (pComponent != NULL)
00333         {
00334             // If this is the colour component, remember it
00335             if (IS_A(pComponent, ColourListComponent))
00336                 pColours = (ColourListComponent*) pComponent;
00337 
00338             // Look for next doc component
00339             pComponent = m_pImportDoc->EnumerateDocComponents(pComponent);
00340         }
00341         ERROR2IF(pColours==NULL, FALSE, "Import document had no colour list");
00342 
00343         // Create a new imported colours manager
00344         ERROR3IF(m_pNewColours != NULL, "ColourImport manager already present\n");
00345         if (m_pNewColours != NULL)
00346         {
00347             m_pNewColours->DestroyColours();
00348             delete m_pNewColours;
00349         }
00350 
00351         m_pNewColours = new ImportedColours(pColours, FALSE);
00352         if ((m_pNewColours == NULL) || !m_pNewColours->Init())
00353             return FALSE;
00354     }
00355 
00356     return TRUE;
00357 }
00358 
00359 
00360 /********************************************************************************************
00361 >   BOOL PaletteFilter::FinishImport(BOOL Success)
00362 
00363     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00364     Created:    1/5/96
00365     Inputs:     Success - TRUE if import has been successful
00366     Outputs:    -
00367     Returns:    TRUE for success, FALSE if an error occured.
00368     Purpose:    Finialises colour import
00369 ********************************************************************************************/
00370 BOOL PaletteFilter::FinishImport(BOOL Success)
00371 {
00372     BOOL ok = TRUE;
00373 
00374     if (!ImportIntoGallery)
00375     {
00376         // If we didn't even get to initialise, then return quietly.
00377         if (m_pNewColours == NULL)
00378             return FALSE;
00379 
00380         EndSlowJob();
00381         BeginSlowJob(-1, FALSE);
00382 
00383         // Import is finished, so add any outstanding colours to the document (if the
00384         // import was successful), and delete the colour table
00385         if (Success)
00386             ok = m_pNewColours->AddColoursToDocument();
00387         else
00388             m_pNewColours->DestroyColours();
00389 
00390         // Clean up claimed memory
00391         delete m_pNewColours;
00392         m_pNewColours = NULL;
00393     }
00394 
00395     return ok;
00396 }
00397 
00398 
00399 /********************************************************************************************
00400 >   BOOL PaletteFilter::ProcessRGBColour(double Red, double Green, double Blue, const StringBase* pColName = NULL)
00401 
00402     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00403     Created:    1/5/96
00404     Inputs:     Red - red value 0..1
00405                 Green - green value 0..1
00406                 Blue - blue value 0..1
00407                 pColName - name to give the colour (NULL if no name)
00408     Outputs:    -
00409     Returns:    TRUE for success, FALSE if an error occured.
00410     Purpose:    Generates a Camelot RGB colour and adds it to the imported colours list
00411 ********************************************************************************************/
00412 BOOL PaletteFilter::ProcessRGBColour(double Red, double Green, double Blue, const StringBase* pColName)
00413 {
00414     // Ensure colour components are in range
00415     ERROR3IF(Red<0, "Red component less than 0");
00416     ERROR3IF(Red>1, "Red component greater than 1");
00417     ERROR3IF(Green<0, "Green component less than 0");
00418     ERROR3IF(Green>1, "Green component greater than 1");
00419     ERROR3IF(Blue<0, "Blue component less than 0");
00420     ERROR3IF(Blue>1, "Blue component greater than 1");
00421     Red = ClampZeroToOne(Red);
00422     Green = ClampZeroToOne(Green);
00423     Blue = ClampZeroToOne(Blue);
00424 
00425     // Make a Camelot RGB colour
00426     ColourRGBT NewColour;
00427     NewColour.Red = Red;
00428     NewColour.Green = Green;
00429     NewColour.Blue = Blue;
00430     NewColour.Transparent = 0;
00431 
00432     // Name the colour
00433     String_64 NewColourName;
00434     BOOL ok = TRUE;
00435     if (pColName==NULL || pColName->IsEmpty())
00436         ok = NameRGBColour(&NewColour, &NewColourName);
00437     else
00438         NewColourName = *pColName;      
00439 
00440     if (ok)
00441     {
00442         if (ImportIntoGallery)
00443             ok = AddColourToGallery(PalettePrefix_None, &NewColourName, (ColourGeneric *)&NewColour, COLOURMODEL_RGBT);
00444         else
00445             ok = m_pNewColours->AddColour(&NewColourName, &NewColour);
00446     }
00447 
00448     return ok;
00449 }
00450 
00451 
00452 /********************************************************************************************
00453 >   BOOL PaletteFilter::ProcessCMYKColour(double Cyan, double Magenta, double Yellow, double Key, const StringBase* pColName = NULL)
00454 
00455     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00456     Created:    2/5/96
00457     Inputs:     Cyan - cyan value 0..1
00458                 Magenta - green value 0..1
00459                 Yellow - blue value 0..1
00460                 Key - black value 0..1
00461                 pColName - name to give the colour (NULL if no name)
00462     Outputs:    -
00463     Returns:    TRUE for success, FALSE if an error occured.
00464     Purpose:    Generates a Camelot CMYK colour and adds it to the imported colours list
00465 ********************************************************************************************/
00466 BOOL PaletteFilter::ProcessCMYKColour(double Cyan, double Magenta, double Yellow, double Key, const StringBase* pColName)
00467 {
00468     // Ensure colour components are in range
00469     ERROR3IF(Cyan<0, "Cyan component less than 0");
00470     ERROR3IF(Cyan>1, "Cyan component greater than 1");
00471     ERROR3IF(Magenta<0, "Magenta component less than 0");
00472     ERROR3IF(Magenta>1, "Magenta component greater than 1");
00473     ERROR3IF(Yellow<0, "Yellow component less than 0");
00474     ERROR3IF(Yellow>1, "Yellow component greater than 1");
00475     ERROR3IF(Key<0, "Key component less than 0");
00476     ERROR3IF(Key>1, "Key component greater than 1");
00477     Cyan = ClampZeroToOne(Cyan);
00478     Magenta = ClampZeroToOne(Magenta);
00479     Yellow = ClampZeroToOne(Yellow);
00480     Key = ClampZeroToOne(Key);
00481 
00482     // Make a Camelot CMYK colour
00483     ColourCMYK NewColour;
00484     NewColour.Cyan = Cyan;
00485     NewColour.Magenta = Magenta;
00486     NewColour.Yellow = Yellow;
00487     NewColour.Key = Key;
00488 
00489     // Name the colour
00490     String_64 NewColourName;
00491     BOOL ok = TRUE;
00492     if (pColName==NULL || pColName->IsEmpty())
00493         ok = NameCMYKColour(&NewColour, &NewColourName);
00494     else
00495         NewColourName = *pColName;      
00496 
00497     if (ok)
00498     {
00499         if (ImportIntoGallery)
00500             ok = AddColourToGallery(PalettePrefix_None, &NewColourName, (ColourGeneric *)&NewColour, COLOURMODEL_CMYK);
00501         else
00502             ok = m_pNewColours->AddColour(&NewColourName, &NewColour);
00503     }
00504 
00505     return ok;
00506 }
00507 
00508 
00509 /********************************************************************************************
00510 >   BOOL PaletteFilter::ProcessHSVColour(double Hue, double Sat, double Value, const StringBase* pColName = NULL)
00511 
00512     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00513     Created:    2/5/96
00514     Inputs:     Hue - Hue value 0..1
00515                 Sat - Saturation value 0..1
00516                 Value - Brightness value 0..1
00517                 pColName - name to give the colour (NULL if no name)
00518     Outputs:    -
00519     Returns:    TRUE for success, FALSE if an error occured.
00520     Purpose:    Generates a Camelot HSV colour and adds it to the imported colours list
00521 ********************************************************************************************/
00522 BOOL PaletteFilter::ProcessHSVColour(double Hue, double Sat, double Value, const StringBase* pColName)
00523 {
00524     // Ensure colour components are in range
00525     ERROR3IF(Hue<0, "Hue component less than 0");
00526     ERROR3IF(Hue>1, "Hue component greater than 1");
00527     ERROR3IF(Sat<0, "Saturation component less than 0");
00528     ERROR3IF(Sat>1, "Saturation component greater than 1");
00529     ERROR3IF(Value<0, "Value component less than 0");
00530     ERROR3IF(Value>1, "Value component greater than 1");
00531     Hue = ClampZeroToOne(Hue);
00532     Sat = ClampZeroToOne(Sat);
00533     Value = ClampZeroToOne(Value);
00534 
00535     // Make a Camelot HSV colour
00536     ColourHSVT NewColour;
00537     NewColour.Hue = Hue;
00538     NewColour.Saturation = Sat;
00539     NewColour.Value = Value;
00540     NewColour.Transparent = 0;
00541 
00542     // Name the colour
00543     String_64 NewColourName;
00544     BOOL ok = TRUE;
00545     if (pColName==NULL || pColName->IsEmpty())
00546         ok = NameHSVColour(&NewColour, &NewColourName);
00547     else
00548         NewColourName = *pColName;      
00549 
00550     if (ok)
00551     {
00552         if (ImportIntoGallery)
00553             ok = AddColourToGallery(PalettePrefix_None, &NewColourName, (ColourGeneric *)&NewColour, COLOURMODEL_HSVT);
00554         else
00555             ok = m_pNewColours->AddColour(&NewColourName, &NewColour);
00556     }
00557 
00558     return ok;
00559 }
00560 
00561 
00562 /********************************************************************************************
00563 >   BOOL PaletteFilter::ProcessLabColour(double Luminance, double A, double B, const StringBase* pColName = NULL)
00564 
00565     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00566     Created:    7/5/96
00567     Inputs:     Luminance - Luminance value 0..100 (black to white)
00568                 A - a value +127..-128 (green to red)
00569                 B - b value +127..-128 (blue to yellow)
00570                 pColName - name to give the colour (NULL if no name)
00571     Outputs:    -
00572     Returns:    TRUE for success, FALSE if an error occured.
00573     Purpose:    Generates a name for this colour and adds it to the imported colours list
00574                 N.B. Camelot does not support Lab colours so the colour is converted to 
00575                      RGB or greyscale.
00576 ********************************************************************************************/
00577 BOOL PaletteFilter::ProcessLabColour(double Luminance, double A, double B, const StringBase* pColName)
00578 {
00579     // Ensure colour components are in range
00580     ERROR3IF(Luminance<0, "Luminance component less than 0");
00581     ERROR3IF(Luminance>100, "Luminance component greater than 100");
00582     ERROR3IF(A<-128, "A component less than -128");
00583     ERROR3IF(A> 127, "A component greater than 127");
00584     ERROR3IF(B<-128, "B component less than -128");
00585     ERROR3IF(B> 127, "B component greater than 127");
00586     Luminance = __min(100, __max(0, Luminance));
00587     A = __min(127, __max(-128, A));
00588     B = __min(127, __max(-128, B));
00589 
00590     // Convert to RGB values
00591     Vector3D Lab(Luminance, A, B);
00592     Vector3D RGBResult;
00593     PaletteFilter::ConvertLABToRGB(Lab, &RGBResult);
00594 
00595     return ProcessRGBColour(RGBResult.x, RGBResult.y, RGBResult.z, pColName );
00596 }
00597 
00598 
00599 /********************************************************************************************
00600 >   BOOL PaletteFilter::ProcessGreyColour(double Intensity, const StringBase* pColName = NULL)
00601 
00602     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00603     Created:    7/5/96
00604     Inputs:     Intensity - 0..1 (black to white)
00605                 pColName - name to give the colour (NULL if no name)
00606     Outputs:    -
00607     Returns:    TRUE for success, FALSE if an error occured.
00608     Purpose:    Generates a Camelot greyscale colour and adds it to the imported colours list
00609 ********************************************************************************************/
00610 BOOL PaletteFilter::ProcessGreyColour(double Intensity, const StringBase* pColName)
00611 {
00612     // Ensure colour components are in range
00613     ERROR3IF(Intensity<0, "Intensity component less than 0");
00614     ERROR3IF(Intensity>1, "Intensity component greater than 1");
00615     Intensity = ClampZeroToOne(Intensity);
00616 
00617     // Make a Camelot greyscale colour
00618     ColourGreyT NewColour;
00619     NewColour.Intensity = Intensity;
00620     NewColour.Reserved1 = 0;
00621     NewColour.Reserved2 = 0;
00622     NewColour.Transparent = 0;
00623 
00624     // Name the colour
00625     String_64 NewColourName;
00626     BOOL ok = TRUE;
00627     if (pColName==NULL || pColName->IsEmpty())
00628         ok = NameGreyColour(&NewColour, &NewColourName);
00629     else
00630         NewColourName = *pColName;      
00631 
00632     if (ok)
00633     {
00634         if (ImportIntoGallery)
00635             ok = AddColourToGallery(PalettePrefix_None, &NewColourName, (ColourGeneric *)&NewColour, COLOURMODEL_GREYT);
00636         else
00637             ok = m_pNewColours->AddColour(&NewColourName, &NewColour);
00638     }
00639 
00640     return ok;
00641 }
00642  
00643 
00644 /********************************************************************************************
00645 >   BOOL PaletteFilter::NameRGBColour(ColourRGBT* pColour, StringBase* pName)
00646 
00647     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00648     Created:    3/5/96
00649     Inputs:     pColour - the Camelot colour to name
00650     Outputs:    pName holds the generated name
00651     Returns:    TRUE for success, FALSE if an error occured.
00652     Purpose:    Generates a name for this RGB colour
00653 ********************************************************************************************/
00654 BOOL PaletteFilter::NameRGBColour(ColourRGBT* pColour, StringBase* pName)
00655 {
00656     ERROR2IF(pColour==NULL || pName==NULL, FALSE, "NULL Pointer");
00657 
00658     if (UsePercentageColour())
00659     {
00660         pName->MakeMsg(_R(IDS_PALETTEIMPORT_RGBPERCENT),
00661                                 (INT32)(pColour->Red.MakeDouble()*100+0.4999),
00662                                 (INT32)(pColour->Green.MakeDouble()*100+0.4999),
00663                                 (INT32)(pColour->Blue.MakeDouble()*100+0.4999) );
00664     }
00665     else
00666     {
00667         pName->MakeMsg(_R(IDS_PALETTEIMPORT_RGBVALUE),
00668                                 (INT32)(pColour->Red.MakeDouble()*255+0.4999),
00669                                 (INT32)(pColour->Green.MakeDouble()*255+0.4999),
00670                                 (INT32)(pColour->Blue.MakeDouble()*255+0.4999) );
00671     }
00672 
00673     return TRUE;
00674 }
00675 
00676 
00677 /********************************************************************************************
00678 >   BOOL PaletteFilter::NameCMYKColour(ColourCMYK* pColour, StringBase* pName)
00679 
00680     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00681     Created:    3/5/96
00682     Inputs:     pColour - the Camelot colour to name
00683     Outputs:    pName holds the generated name
00684     Returns:    TRUE for success, FALSE if an error occured.
00685     Purpose:    Generates a name for this CMYK colour
00686 ********************************************************************************************/
00687 BOOL PaletteFilter::NameCMYKColour(ColourCMYK* pColour, StringBase* pName)
00688 {
00689     ERROR2IF(pColour==NULL || pName==NULL, FALSE, "NULL Pointer");
00690     
00691     if (UsePercentageColour())
00692     {
00693         pName->MakeMsg(_R(IDS_PALETTEIMPORT_CMYKPERCENT),
00694                                 (INT32)(pColour->Cyan.MakeDouble()*100+0.4999),
00695                                 (INT32)(pColour->Magenta.MakeDouble()*100+0.4999),
00696                                 (INT32)(pColour->Yellow.MakeDouble()*100+0.4999),
00697                                 (INT32)(pColour->Key.MakeDouble()*100+0.4999) );
00698     }
00699     else
00700     {
00701         pName->MakeMsg(_R(IDS_PALETTEIMPORT_CMYKVALUE),
00702                                 (INT32)(pColour->Cyan.MakeDouble()*255+0.4999),
00703                                 (INT32)(pColour->Magenta.MakeDouble()*255+0.4999),
00704                                 (INT32)(pColour->Yellow.MakeDouble()*255+0.4999),
00705                                 (INT32)(pColour->Key.MakeDouble()*255+0.4999) );
00706     }
00707 
00708     return TRUE;
00709 }
00710 
00711 
00712 /********************************************************************************************
00713 >   BOOL PaletteFilter::NameHSVColour(ColourHSVT* pColour, StringBase* pName)
00714 
00715     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00716     Created:    3/5/96
00717     Inputs:     pColour - the Camelot colour to name
00718     Outputs:    pName holds the generated name
00719     Returns:    TRUE for success, FALSE if an error occured.
00720     Purpose:    Generates a name for this CMYK colour
00721 ********************************************************************************************/
00722 BOOL PaletteFilter::NameHSVColour(ColourHSVT* pColour, StringBase* pName)
00723 {
00724     ERROR2IF(pColour==NULL || pName==NULL, FALSE, "NULL Pointer");
00725     
00726     if (UsePercentageColour())
00727     {
00728         pName->MakeMsg(_R(IDS_PALETTEIMPORT_HSVPERCENT),
00729                                 (INT32)(pColour->Hue.MakeDouble()*360+0.4999),
00730                                 (INT32)(pColour->Saturation.MakeDouble()*100+0.4999),
00731                                 (INT32)(pColour->Value.MakeDouble()*100+0.4999) );
00732     }
00733     else
00734     {
00735         pName->MakeMsg(_R(IDS_PALETTEIMPORT_HSVVALUE),
00736                                 (INT32)(pColour->Hue.MakeDouble()*360+0.4999),
00737                                 (INT32)(pColour->Saturation.MakeDouble()*255+0.4999),
00738                                 (INT32)(pColour->Value.MakeDouble()*255+0.4999) );
00739     }
00740 
00741     return TRUE;
00742 }
00743 
00744 
00745 /********************************************************************************************
00746 >   BOOL PaletteFilter::NameGreyColour(ColourGreyT* pColour, StringBase* pName)
00747 
00748     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00749     Created:    7/5/96
00750     Inputs:     pColour - the Camelot colour to name
00751     Outputs:    pName holds the generated name
00752     Returns:    TRUE for success, FALSE if an error occured.
00753     Purpose:    Generates a name for this greyscale colour
00754 ********************************************************************************************/
00755 BOOL PaletteFilter::NameGreyColour(ColourGreyT* pColour, StringBase* pName)
00756 {
00757     ERROR2IF(pColour==NULL || pName==NULL, FALSE, "NULL Pointer");
00758 
00759     if (pColour->Intensity.MakeDouble() <= 0.0)
00760         *pName = String_32(_R(IDS_PALETTEIMPORT_GREYBLACK));
00761     else if (pColour->Intensity.MakeDouble() >= 1.0)
00762             *pName = String_32(_R(IDS_PALETTEIMPORT_GREYWHITE));
00763         else
00764             pName->MakeMsg(_R(IDS_PALETTEIMPORT_GREYPERCENT), (INT32)(pColour->Intensity.MakeDouble()*100+0.4999));
00765 
00766     return TRUE;
00767 }
00768 
00769 
00770 /********************************************************************************************
00771 >   BOOL PaletteFilter::UsePercentageColour()
00772 
00773     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00774     Created:    29/5/96
00775     Inputs:     -
00776     Outputs:    -
00777     Returns:    TRUE if the colour editor preference is for percentages, FALSE if not
00778     Purpose:    To  see wether or not to use the precentage colour naming scheme
00779 ********************************************************************************************/
00780 BOOL PaletteFilter::UsePercentageColour()
00781 {
00782 // WEBSTER - markn 24/4/97
00783 #ifdef WEBSTER
00784     // Always use percentages for colour units in Webster
00785     return TRUE;
00786 #else
00787     #if !defined(EXCLUDE_FROM_RALPH) && !defined(EXCLUDE_FROM_XARALX)
00788         // Read what the colour editors preference is
00789         ScaleUnit* pUnit = UnitsTab::GetColourUnitPreference();
00790 
00791         return (pUnit == &StandardUnit::UnitPercent);
00792     #else
00793         return FALSE;
00794     #endif
00795 #endif // WEBSTER
00796 }
00797 
00798 
00799 /********************************************************************************************
00800 >   BOOL PaletteFilter::StartPercentage(INT32 UpTo = -1)
00801 
00802     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00803     Created:    1/5/96
00804     Inputs:     UpTo - the 100% value
00805     Outputs:    -
00806     Returns:    TRUE for success, FALSE if an error occured.
00807     Purpose:    Starts a percentage delay indicator that runs from 0 to 100.  If you don't
00808                 know how many colours you are importing pass -1 and the length of the file
00809                 is used
00810 ********************************************************************************************/
00811 BOOL PaletteFilter::StartPercentage(INT32 UpTo)
00812 {
00813 #if !defined(EXCLUDE_FROM_RALPH) && !defined(EXCLUDE_FROM_XARALX)
00814     if (UpTo == -1)
00815     {
00816         if (m_pImportFile != NULL)
00817             BeginSlowJob(m_pImportFile->Size());
00818         else
00819             BeginSlowJob();
00820     }
00821     else
00822         BeginSlowJob(UpTo);
00823 #endif
00824     return TRUE;
00825 }
00826 
00827 
00828 /********************************************************************************************
00829 >   BOOL PaletteFilter::SetPercentage(INT32 GotTo)
00830 
00831     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00832     Created:    1/5/96
00833     Inputs:     GotTo - the current position
00834     Outputs:    -
00835     Returns:    TRUE for success, FALSE if an error occured.
00836     Purpose:    Continues a percentage delay indicator.  Pass -1 to use the current import
00837                 file position as a progress indicator.
00838 ********************************************************************************************/
00839 BOOL PaletteFilter::SetPercentage(INT32 GotTo)
00840 {
00841 #if !defined(EXCLUDE_FROM_RALPH) && !defined(EXCLUDE_FROM_XARALX)
00842     if (GotTo == -1)
00843     {
00844         if (m_pImportFile != NULL)
00845             ContinueSlowJob(m_pImportFile->tell());
00846         else
00847             ContinueSlowJob();
00848     }
00849     else
00850         ContinueSlowJob(GotTo);
00851 #endif
00852     return TRUE;
00853 }
00854 
00855 
00856 
00857 /********************************************************************************************
00858 >   void PaletteFilter::ConvertXYZToRGB(const Vector3D& icol, Vector3D& ocol)
00859 
00860     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00861     Created:    13/04/96
00862     Inputs:     icon = The (Xn, Yn, Zn) coordinates of the white colour in CIE XYZ space.
00863     Outputs:    ocol  = RGB colour (0..1)
00864     Returns:    -
00865     Purpose:    To convert colours from CIE XYZ to RGB
00866 ********************************************************************************************/
00867 void PaletteFilter::ConvertXYZToRGB(const Vector3D& icol, Vector3D& ocol)
00868 {
00869     // Convert from HDTV Rec709 to RGB
00870     ocol.x = ( 3.240479*icol.x) + (-1.537150*icol.y) + (-0.498535*icol.z);
00871     ocol.y = (-0.969256*icol.x) + ( 1.875992*icol.y) + ( 0.041556*icol.z);
00872     ocol.z = ( 0.055648*icol.x) + (-0.204043*icol.y) + ( 1.057311*icol.z);
00873     
00874     ClampZeroToOne(ocol.x);
00875     ClampZeroToOne(ocol.y);
00876     ClampZeroToOne(ocol.z);
00877 }
00878 
00879 
00880 
00881 /********************************************************************************************
00882 >   void PaletteFilter::ConvertLABtoXYZ(const Vector3D& white, const Vector3D& icol, Vector3D& ocol)
00883 
00884     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00885     Created:    13/04/96
00886     Inputs:     white = The (Xn, Yn, Zn) coordinates of the white colour in CIE XYZ space.
00887                 icol  = CIE LAB colour
00888     Outputs:    ocol  = CIE XYZ colour
00889     Returns:    -
00890     Purpose:    To convert colours from CIE LUV to CIE XYZ  
00891 ********************************************************************************************/
00892 void PaletteFilter::ConvertLABtoXYZ(const Vector3D& white, const Vector3D& icol, Vector3D& ocol)
00893 {
00894     double d,e;
00895     static double third = 1.0/3.0;
00896 
00897     if (icol.x < 7.9996248) 
00898         ocol.y = icol.x * white.y / 903.3;
00899     else 
00900         ocol.y = pow((double)((icol.x + 16.0) / 116.0), (double)3.0) * white.y;
00901 
00902     e = pow((double)(ocol.y / white.y), third);
00903     d = e + (double)(icol.y / 500);
00904     
00905     ocol.x = pow(d, (double)3.0) * white.x;
00906 
00907     d = e - (double)(icol.z / 200);
00908     
00909     ocol.z = pow(d, (double)3.0) * white.z;
00910 }
00911 
00912 
00913 /********************************************************************************************
00914 >   void PaletteFilter::ConvertCIEtoXYZ(const Vector3D icol, Vector3D& ocol)
00915 
00916     Author:     Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
00917     Created:    13/04/96
00918     Inputs:     icol = (x,y) is the chromaticity value
00919                           YY is the corresponding luminance value
00920     Outputs:    ocol = (X,Y,Z) coordinates in the CIE XYZ space
00921                         
00922     Returns:    -
00923     Purpose:    To convert the given x, y and Y to X, Y and Z in CIE XYZ space
00924 ********************************************************************************************/
00925 void PaletteFilter::ConvertCIEtoXYZ(const Vector3D& icol, Vector3D& ocol)
00926 {
00927     double d = icol.z / icol.y;
00928 
00929     ocol.x = icol.x * d;
00930     ocol.y = icol.z;
00931     ocol.z = (1.0 - icol.x - icol.y) * d;
00932 }
00933 
00934 
00935 /********************************************************************************************
00936 >   void PaletteFilter::ConvertLABToRGB(const Vector3D& icol, Vector3D* ocol)
00937 
00938     Author:     Peter_Arnold (Xara Group Ltd) <camelotdev@xara.com>
00939     Created:    10/5/96
00940     Inputs:     icol = (x, y, z) - Lab colour (0..100, -128..127, -128..127)
00941     Outputs:    ocol = (x, y, z) - RGB colour (0..1, 0..1, 0..1)
00942     Returns:    -
00943     Purpose:    To convert the given Lab colour to a (near) equivelent RGB colour
00944                 This uses the above conversion functions from Mike.  They are *not* accurate
00945                 but do give a reasonable approximation of the colour.
00946 ********************************************************************************************/
00947 void PaletteFilter::ConvertLABToRGB(const Vector3D& icol, Vector3D* ocol)
00948 {
00949     // First calculate a XYZ white point
00950     Vector3D CIEWhite = Vector3D(0.3127, 0.3290, 1.0 );
00951     Vector3D XYZWhite;
00952     PaletteFilter::ConvertCIEtoXYZ(CIEWhite, XYZWhite);
00953 
00954     Vector3D LabAsXYZ;
00955     PaletteFilter::ConvertLABtoXYZ(XYZWhite, icol, LabAsXYZ);
00956 
00957     // Finally convert XYZ to RGB
00958     Vector3D RGB;
00959     PaletteFilter::ConvertXYZToRGB(LabAsXYZ, RGB);
00960 
00961     ocol->x = ClampZeroToOne( pow(RGB.x, 1.0/2.5) );
00962     ocol->y = ClampZeroToOne( pow(RGB.y, 1.0/2.5) );
00963     ocol->z = ClampZeroToOne( pow(RGB.z, 1.0/2.5) );
00964 }
00965 
00966 
00967 
00968 /********************************************************************************************
00969 
00970 >   BOOL PaletteFilter::AddColourToGallery(PalettePrefix Prefix, String_64 *Name,
00971                                             ColourGeneric *Definition, ColourModel Model,
00972                                             BOOL NewlineAfter = FALSE, IsSpotColour = FALSE)
00973     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00974     Created:    8/8/96
00975     Inputs:     Prefix - Indicates a standard library prefix which should be prepended
00976                             to the name (remembering the prefix ID is much better than
00977                             storing a great long string in every colour)
00978                 Name - the name
00979                 Definition - the colour definition
00980                 Model - The colour model that Definition is given in
00981                 NewlineAfter - TRUE to hint to the colour gallery that it should divide
00982                 the colour items (by starting a new line in the display) in order to
00983                 display them more usefully.
00984 
00985     Returns:    TRUE if it succeeeds
00986 
00987     Purpose:    Sticks the given colour into the colour gallery
00988 
00989 ********************************************************************************************/
00990 
00991 BOOL PaletteFilter::AddColourToGallery(PalettePrefix Prefix, String_64 *Name,
00992                                         ColourGeneric *Definition, ColourModel Model,
00993                                         BOOL NewlineAfter, BOOL IsSpotColour)
00994 {
00995 #if !defined(EXCLUDE_FROM_RALPH) && !defined(EXCLUDE_FROM_XARALX)
00996     if (CurrentGalleryGroup == NULL)
00997         return(FALSE);
00998 
00999     // Create a new DocColour for this colour
01000     DocColour NewCol(Model, Definition);
01001     
01002     if (Prefix == PalettePrefix_Pantone || Prefix == PalettePrefix_PantoneSpot)
01003     {
01004         // Set the "PANTONE bodge" flag which rounds the colour components to the nearest half percent.
01005         // This gets around errors introduced by storing the 200 possible half-percent values in a 0-255 BYTE
01006         NewCol.ForceRounding(TRUE);
01007     }
01008 
01009     SGDisplayLibColour *NewItem = new SGDisplayLibColour(&NewCol, Name, Prefix, NewlineAfter, IsSpotColour);
01010     if (NewItem == NULL)
01011         return(FALSE);
01012 
01013     CurrentGalleryGroup->AddItem(NewItem);
01014 #endif
01015     return(TRUE);
01016 }
01017 
01018 
01019 
01020 
01021 
01022 
01023 /********************************************************************************************
01024 >   CorelPaletteFilter::CorelPaletteFilter()
01025 
01026     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01027     Created:    15 03 95
01028     Inputs:     As for the Filter class
01029     Returns:    As for the Filter class
01030     Purpose:    Constructor
01031     SeeAlso:    Filter
01032 ********************************************************************************************/
01033 CorelPaletteFilter::CorelPaletteFilter()
01034 {
01035     // Set up filter descriptions.
01036     FilterName.Load(_R(IDT_CORELPALETTEFILTER_FILTERNAME));
01037     FilterInfo.Load(_R(IDT_CORELPALETTEFILTER_FILTERINFO));
01038     FilterID = FILTERID_CORELPALETTEFILE;
01039 
01040 #ifndef STANDALONE
01041     Flags.CanImport = TRUE;
01042     Flags.CanExport = FALSE;
01043 #else
01044     Flags.CanImport = FALSE;
01045     Flags.CanExport = FALSE;
01046 #endif
01047 
01048 #ifndef DO_EXPORT
01049     Flags.CanExport = FALSE;
01050 #endif
01051 
01052     m_FileVersion = CPL_FVU;
01053 }
01054 
01055 
01056 /********************************************************************************************
01057 >   BOOL CorelPaletteFilter::Init(void)
01058 
01059     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01060     Created:    15 03 95
01061     Inputs:     As for the Filter class
01062     Returns:    As for the Filter class
01063     Purpose:    Initialisation
01064     SeeAlso:    Filter
01065 ********************************************************************************************/
01066 BOOL CorelPaletteFilter::Init(void)
01067 {
01068     // Get the OILFilter object
01069     pOILFilter = new CorelPaletteFileOILFilter(this);
01070     if (pOILFilter == NULL)
01071         return FALSE;
01072 
01073     // All ok
01074     return TRUE;
01075 }
01076 
01077 
01078 /********************************************************************************************
01079 >   INT32 CorelPaletteFilter::HowCompatible(PathName& Filename, ADDR  HeaderStart,
01080                                                             UINT32 HeaderSize, UINT32 FileSize)
01081 
01082     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01083     Created:    15 03 95
01084     Inputs:     As for the Filter class
01085     Returns:    As for the Filter class
01086     Purpose:    Examines a file to see how compatable it is with this filter.
01087     SeeAlso:    Filter
01088 ********************************************************************************************/
01089 INT32 CorelPaletteFilter::HowCompatible(PathName& Filename, ADDR  HeaderStart, UINT32 HeaderSize, UINT32 FileSize)
01090 {
01091 PORTNOTE("byteorder", "TODO: Check byte ordering")
01092     // Check the filetype matches
01093     if (!pOILFilter->DoesExtensionOfPathNameMatch(&Filename))
01094         return 0;
01095 
01096     m_FileVersion = CPL_FVU;
01097     
01098     // is it a .pal file (textualally based)?
01099     INT32 result = 0;
01100     if ((result = HowCompatible4(Filename, HeaderStart, HeaderSize, FileSize)) != 0)
01101         return result;
01102 
01103     // is it a .cpl file (binary)?
01104     if ((result = HowCompatible5(Filename, HeaderStart, HeaderSize, FileSize)) != 0)
01105         return result;
01106 
01107     // it's not a palette file.
01108     return 0;
01109 }
01110 
01111 
01112 /********************************************************************************************
01113 >   INT32 CorelPaletteFilter::HowCompatible4(PathName& Filename, ADDR  HeaderStart,
01114         UINT32 HeaderSize, UINT32 FileSize)
01115 
01116     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01117     Created:    17 03 95
01118     Inputs:     As for the Filter class
01119     Returns:    As for the Filter class
01120     Purpose:    Examines a file to see how compatable it is with this filter - checks for
01121                 version 3 and 4 .pal files (textual CMYK only)
01122     SeeAlso:    Filter
01123 ***************