AIGradientProcessor Class Reference

Helps with the import of Adobe Illustrator 8.0 files. (at the time of writing only the version 7.0 documentation was available so some omissions are inevitable). It creates a list gradient fills and allows the filter to extract them. More...

#include <ai_grad.h>

List of all members.

Public Member Functions

 AIGradientProcessor ()
virtual ~AIGradientProcessor ()
BOOL BeginGradient ()
 Allows the gradient processor to intialize itself for a new gradient signalled by the BeginGradient comment.
BOOL DecodeBd (AI5EPSFilter &filter)
 Processes the gradient definition start operator which tells us how many colours are in it and what its name is.
BOOL DecodeBS (AI5EPSFilter &filter)
 Processes the gradient stop operator (indicating a step in the ramp).
BOOL DecodeBh (AI5EPSFilter &filter)
 The Bh operator adds a highlight to a fill. In Camelot we interpret this as a conical fill.
BOOL EndGradient (AI5EPSFilter &filter)
 Allows the gradient processor to complete the gradient signalled by the EndGradient comment.
AI5GradientFindGradient (const StringBase &name)
 Once the gradient definitions have been read, gradient instances can be created using the name to identify the gradient "style".

Private Member Functions

BOOL Approx (const double &d1, const double &d2)
 This is used to determine whether the position of one gradient stop is equivalent to another during import, mainly for working out which stops are at the start and the end.

Private Attributes

List mGradFills
BOOL mbGradFillTooComplex
AI5GradientmpCurrentFill
INT32 mMidPoint
INT32 mLastRampPoint


Detailed Description

Helps with the import of Adobe Illustrator 8.0 files. (at the time of writing only the version 7.0 documentation was available so some omissions are inevitable). It creates a list gradient fills and allows the filter to extract them.

Author:
Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/03/00

Definition at line 174 of file ai_grad.h.


Constructor & Destructor Documentation

AIGradientProcessor::AIGradientProcessor  ) 
 

Definition at line 148 of file ai_grad.cpp.

00148                                          :
00149     mbGradFillTooComplex(FALSE),
00150     mpCurrentFill(0)
00151 {
00152     // The last ramp point is set to 101, since this is effectively a
00153     // counter from 100 down to 0.
00154     mMidPoint       = 0;
00155     mLastRampPoint  = 101;
00156 }

AIGradientProcessor::~AIGradientProcessor  )  [virtual]
 

Definition at line 158 of file ai_grad.cpp.

00159 {
00160     mGradFills.DeleteAll();
00161 
00162     delete mpCurrentFill;
00163     mpCurrentFill = 0;
00164 }


Member Function Documentation

BOOL AIGradientProcessor::Approx const double &  d1,
const double &  d2
[private]
 

This is used to determine whether the position of one gradient stop is equivalent to another during import, mainly for working out which stops are at the start and the end.

Author:
?
Date:
presumably March 2000
Parameters:
d1,d2 - two doubles that are to be compared [INPUTS]
Currently the tolerance for this is 2% either way, as this seems to give good results.

Returns:
TRUE if the d1 is approximately equal to d2 FALSE if not

Definition at line 459 of file ai_grad.cpp.

00460 {
00461     const double dTolerance = 2;
00462     return ( fabs( d2 - d1 ) < dTolerance );
00463 }

BOOL AIGradientProcessor::BeginGradient  ) 
 

Allows the gradient processor to intialize itself for a new gradient signalled by the BeginGradient comment.

Author:
Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
Date:
23/03/00
Returns:
TRUE if the definition was processed, FALSE if not used by this filter..

Definition at line 181 of file ai_grad.cpp.

00182 {
00183     ENSURE( mpCurrentFill == NULL, "mpCurrentFill is not NULL");
00184 
00185     // Found the start of a gradient definition - prepare to read in the
00186     // definition...
00187     mpCurrentFill = new AI5Gradient;
00188 
00189     if ( !mpCurrentFill )
00190         return FALSE;
00191 
00192     return TRUE;
00193 }

BOOL AIGradientProcessor::DecodeBd AI5EPSFilter filter  ) 
 

Processes the gradient definition start operator which tells us how many colours are in it and what its name is.

Author:
Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
Date:
23/03/00
Returns:
TRUE if the definition was processed, FALSE if not used by this filter..

Definition at line 211 of file ai_grad.cpp.

00212 {
00213     if ( !mpCurrentFill )
00214         return FALSE;
00215 
00217     // Name, type, and number of steps in gradient fill
00219     INT32 colours = 0;
00220     INT32 type = 0;
00221 
00222     if (!filter.GetStack().Pop(&colours) || 
00223         !filter.GetStack().Pop(&type) || 
00224         !filter.GetStack().Pop(&mpCurrentFill->Name))
00225         // Error in syntax
00226         return FALSE;
00227 
00228     // Translate fill type
00229     switch (type)
00230     {
00231         case 0:     mpCurrentFill->IsRadial = FALSE;    break;
00232         case 1:     mpCurrentFill->IsRadial = TRUE;     break;
00233         default:    return FALSE;
00234     }
00235 
00236     return TRUE;
00237 }

BOOL AIGradientProcessor::DecodeBh AI5EPSFilter filter  ) 
 

The Bh operator adds a highlight to a fill. In Camelot we interpret this as a conical fill.

Author:
Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
Date:
23/03/00
Returns:
TRUE if the definition was processed happily FALSE if not
The format of the operator is: xHilight yHilight angle length Bh

Arguments to the Bh operator are as follows: xHilight yHilight These arguments specify the hilight placement, in x and y offsets from the gradient vector origin. angle This argument is the angle to the hilight point, measured counterclockwise from the x axis. length This argument is the distance of the hilight from the origin, expressed as a fraction of the radius a value between 0 and 1.

Definition at line 409 of file ai_grad.cpp.

00410 {
00412     // read the arguments from the stack
00414 
00415     INT32 nAngle        = 0;
00416     double dLength  = 0.0;
00417     DocCoord hilight;
00418 
00419     if ( !filter.GetStack().Pop(&dLength) || !filter.GetStack().Pop(&nAngle) ||
00420         !filter.GetStack().PopCoordPair(&hilight) )
00421         return FALSE;
00422 
00424     // Check if these are values we can handle
00426 
00428     // Attach the highlight details so we can work out what to do later
00429     // but if there's already a highlight ignore this one
00431 /*
00432 
00433   Won't do this for now
00434 
00435 
00436     mpCurrentHighlight = new AI5Gradient::Highlight( nAngle, dLength, hilight );
00437 */
00438     return TRUE;
00439 }

BOOL AIGradientProcessor::DecodeBS AI5EPSFilter filter  ) 
 

Processes the gradient stop operator (indicating a step in the ramp).

Author:
Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
Date:
23/03/00
Returns:
TRUE if the definition was processed, FALSE if not used by this filter..

Definition at line 252 of file ai_grad.cpp.

00253 {
00254     // Decode colour/step definition
00255     INT32 rampPoint = 0, midPoint = 0;
00256 
00257     if ( !filter.GetStack().Pop(&rampPoint) || !filter.GetStack().Pop(&midPoint) )
00258         return FALSE;
00259 
00260     // Check if these are values we can handle
00261     // (We still import an approximation of the fill even if not)
00262     if ( midPoint > 100 || midPoint < 0 || rampPoint < 0 || rampPoint > 100 )
00263     {
00264         return FALSE;
00265     }
00266 
00267     // Work out what sort of colour this is - CMYK or B&W tint
00268     INT32 colorStyle;
00269     if ( !filter.GetStack().Pop(&colorStyle) )
00270         return FALSE;
00271 
00272     DocColour newColour;
00273 
00274     switch ( colorStyle )
00275     {
00276         case 0:     // grey
00277         {
00278             double dTint( 0.0 );
00279             if ( !filter.GetStack().Pop(&dTint) )
00280                 return FALSE;
00281 
00282             // Make a colour from this
00283             INT32 intensity = (INT32) (dTint * 255.0);
00284             newColour.SetRGBValue( intensity, intensity, intensity );
00285             break;
00286         }
00287 
00288         case 1:     // CMYK
00289         {
00290             PColourCMYK col;
00291             if (!filter.GetStack().PopColour(&col, TINT_NONE))
00292                 return FALSE;
00293 
00294             // Set up the colour with what we have.
00295             newColour.SetCMYKValue( &col );
00296 
00297             break;
00298         }
00299 
00300         case 2:     // RGB
00301         {
00302             INT32 red, green, blue;
00303             if (!filter.GetStack().PopColourRGB (&red, &green, &blue, TINT_NONE))
00304                 return FALSE;
00305 
00306                 // remove the CMYK colour info.
00307             (filter.GetStack()).Discard (4);
00308             newColour.SetRGBValue (red, green, blue);
00309             break;
00310         }
00311 
00312         case 3:     // CMYK custom
00313         {
00314             PColourCMYK col;
00315             FIXEDPOINT tint;
00316             String_64 name;
00317             if ( !filter.GetStack().PopColour( &col, TINT_ILLUSTRATOR, &tint, &name ) )
00318                 return FALSE;
00319 
00320             newColour.SetCMYKValue( &col );
00321 
00322             break;
00323         }
00324 
00325         case 4:     // RGB custom
00326         {
00327             INT32 red, green, blue;
00328             FIXEDPOINT tint;
00329             String_64 name;
00330 
00331             // remove the 'type' flag (is always 1 for RGB)
00332             filter.GetStack().Discard (1);
00333 
00334             if (!filter.GetStack().PopColourRGB (&red, &green, &blue, 
00335                                                 TINT_ILLUSTRATOR, &tint, &name))
00336                 return FALSE;
00337 
00338             (filter.GetStack()).Discard (4);
00339             newColour.SetRGBValue (red, green, blue);
00340 
00341             break;
00342         }
00343         default:
00344             break;
00345     }
00346 
00347 
00349     //  add the colour to the ramp
00351 
00352     double dPos = double(rampPoint) / double(100.0);
00353 
00354     if ( mpCurrentFill )
00355     {
00356         if ( !mpCurrentFill->mpCurrentRamp )
00357         {
00358             mpCurrentFill->mpCurrentRamp = new ColourRamp;
00359             if ( ! mpCurrentFill->mpCurrentRamp )
00360             {
00361                 return FALSE;
00362             }
00363         }
00364 
00365         mpCurrentFill->mpCurrentRamp->AddEntry( static_cast<float> ( dPos ), &newColour );
00366     }
00367 
00368     // Set the midpoint if this point is nearer to the start than the stored mid-point. 
00369     //  The midpoint nearest to the 0% ramp point is used, as there should only be one 
00370     //  midpoint if Xara X's profiling is going to cope with it, and the last midpoint in 
00371     //  an Illustrator gradient should always be ignored.
00372     if (rampPoint < mLastRampPoint)
00373     {
00374         mMidPoint = midPoint;
00375         mLastRampPoint = rampPoint;
00376     }
00377 
00378     return TRUE;
00379 }

BOOL AIGradientProcessor::EndGradient AI5EPSFilter filter  ) 
 

Allows the gradient processor to complete the gradient signalled by the EndGradient comment.

Author:
Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
Date:
23/03/00
Returns:
TRUE if the definition was processed, FALSE if not used by this filter..

Definition at line 480 of file ai_grad.cpp.

00481 {
00482     ENSURE( mpCurrentFill != NULL, "mpGradFill is NULL");
00483 
00484     // The end of the definition - lose the rampant '[' from the input stream.
00485     EPSCommand Cmd;
00486     if (!filter.GetStack().PopCmd(&Cmd) || (Cmd != EPSC_ArrayStart))
00487     {
00488         // if it isn't what we're hoping for, ignore it
00489         filter.GetStack().Push( Cmd );
00490     }
00491 
00493     // an n-stage multi-stage fill in camelot is divided into n - 2 ramp items
00494     // and the start and end colours of the fill.
00495     // When creating the fill we have just added ramp items, so we need to pick 
00496     // off the first and last for the start and end colours.
00498 
00499     if ( mpCurrentFill->mpCurrentRamp )
00500     {   
00501         // (ChrisG 3/4/2001) Gradient stops are now always removed from the list if they are
00502         //  used as a start or end colour. There was a check to make sure they were near the
00503         //  end, which often failed, leading to additional stops at the ends.
00504 
00505         // first the start colour
00506         ColRampItem* pFirstItem = reinterpret_cast<ColRampItem*>( mpCurrentFill->mpCurrentRamp->GetHead() );
00507         if ( pFirstItem )
00508         {
00509             // Take the first colour out of the ramp, as this is represented by the start colour
00510             mpCurrentFill->StartColour = pFirstItem->GetColour();
00511 
00512             // if the first ramp item isn't at the start of the fill, leave it as
00513             // part of the ramp and make the start the same colour
00514             if ( Approx( pFirstItem->GetPosition(), 0.0) ||
00515                  Approx( pFirstItem->GetPosition(), 100.0))
00516             {
00517                 mpCurrentFill->mpCurrentRamp->RemoveHead();
00518             }
00519         }
00520 
00521         // then the end colour
00522         ColRampItem* pLastItem = reinterpret_cast<ColRampItem*>( mpCurrentFill->mpCurrentRamp->GetTail() );
00523         if ( pLastItem )
00524         {
00525             // Take the last colour out of the ramp, as this is represented by the end colour
00526             mpCurrentFill->EndColour = pLastItem->GetColour();
00527 
00528             // if the first ramp item isn't at the start of the fill, leave it as
00529             // part of the ramp and make the start the same colour
00530             if ( Approx( pLastItem->GetPosition(), 0.0) ||
00531                  Approx( pLastItem->GetPosition(), 100.0))
00532             {
00533                 mpCurrentFill->mpCurrentRamp->RemoveTail();
00534             }
00535         }
00536     }
00537 
00538     // set the mid-point, for the profiling.
00539     mpCurrentFill->midPoint = mMidPoint;
00540 
00541     // add the current fill to our list.
00542     mGradFills.AddTail( mpCurrentFill );
00543 
00544     // We're done with this fill.
00545     mpCurrentFill = NULL;
00546 
00547     // reset the profiling variables.
00548     mMidPoint       = 0;
00549     mLastRampPoint  = 101;
00550 
00551     return TRUE;
00552 }

AI5Gradient * AIGradientProcessor::FindGradient const StringBase name  ) 
 

Once the gradient definitions have been read, gradient instances can be created using the name to identify the gradient "style".

Author:
Colin_Barfoot (Xara Group Ltd) <camelotdev@xara.com>
Date:
23/03/00
Returns:
NULL if no gradient exists with the given name Otherwise the one that does.

Definition at line 569 of file ai_grad.cpp.

00570 {
00571     // First find this named gradient fill
00572     AI5Gradient* pGradient = (AI5Gradient *) mGradFills.GetHead();
00573 
00574     while ( pGradient )
00575     {
00576         if ( pGradient->Name == name )
00577             // This is the one we want!
00578             break;
00579 
00580         // Try the next one
00581         pGradient = (AI5Gradient *) mGradFills.GetNext(pGradient);
00582     }
00583 
00584     return pGradient;
00585 }


Member Data Documentation

BOOL AIGradientProcessor::mbGradFillTooComplex [private]
 

Definition at line 195 of file ai_grad.h.

List AIGradientProcessor::mGradFills [private]
 

Definition at line 192 of file ai_grad.h.

INT32 AIGradientProcessor::mLastRampPoint [private]
 

Definition at line 204 of file ai_grad.h.

INT32 AIGradientProcessor::mMidPoint [private]
 

Definition at line 203 of file ai_grad.h.

AI5Gradient* AIGradientProcessor::mpCurrentFill [private]
 

Definition at line 198 of file ai_grad.h.


The documentation for this class was generated from the following files:
Generated on Sat Nov 10 03:49:55 2007 for Camelot by  doxygen 1.4.4