attr.cpp

Go to the documentation of this file.
00001 // $Id: attr.cpp 1361 2006-06-25 16:43:38Z 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 // The basic Camelot attributes
00100 
00101 /*
00102 */
00103 
00104 #include "camtypes.h"
00105 
00106 
00107 //#include "attr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00108 #include "lineattr.h"
00109 #include "userattr.h"
00110 //#include "ink.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00111 //#include "fillattr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00112 //#include "attrmgr.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00113 #include "blendatt.h"
00114 #include "pathstrk.h"
00115 
00116 //#include "will2.h"
00117 
00118 DECLARE_SOURCE("$Revision: 1361 $");
00119 
00120 CC_IMPLEMENT_DYNAMIC(AttributeValue, CCObject);
00121 CC_IMPLEMENT_DYNCREATE(DashRec, CCObject);
00122 
00123 CC_IMPLEMENT_DYNCREATE(LineWidthAttribute,      AttributeValue);
00124 CC_IMPLEMENT_DYNCREATE(StartArrowAttribute,     AttributeValue);
00125 CC_IMPLEMENT_DYNCREATE(EndArrowAttribute,       AttributeValue);
00126 CC_IMPLEMENT_DYNCREATE(StartCapAttribute,       AttributeValue);
00127 CC_IMPLEMENT_DYNCREATE(JoinTypeAttribute,       AttributeValue);
00128 CC_IMPLEMENT_DYNCREATE(MitreLimitAttribute,     AttributeValue);
00129 CC_IMPLEMENT_DYNCREATE(WindingRuleAttribute,    AttributeValue);
00130 CC_IMPLEMENT_DYNCREATE(DashPatternAttribute,    AttributeValue);
00131 CC_IMPLEMENT_DYNCREATE(DrawingModeAttribute,    AttributeValue);
00132 CC_IMPLEMENT_DYNCREATE(UserAttribute,           AttributeValue);
00133 
00134 CC_IMPLEMENT_MEMDUMP(BlendAttrParam,            CC_CLASS_MEMDUMP);
00135 
00136 // Declare smart memory handling in Debug builds
00137 #define new CAM_DEBUG_NEW
00138 
00139 /********************************************************************************************
00140 
00141 >   virtual void AttributeValue::Restore(RenderRegion *pRegion, BOOL Temporary)
00142 
00143     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00144     Created:    03/02/94
00145     Inputs:     pRegion - the render region to restore the attribute into.
00146                 Temporary - TRUE if this is a temporary attribute, FALSE if it is
00147                             permanent (e.g. it's in a document tree).
00148     Purpose:    Used when restoring attributes from the render region's context stack.
00149 
00150                 This changes the relevant current rendering attribute to be that described
00151                 by this AttributeValue object.
00152                 
00153                 The Temporary flag controls what is done with this object when it is no
00154                 longer needed by the stack - i.e. the next time an attribute of this type
00155                 is restored from the stack, this attribute value will no longer be 
00156                 referenced, and so if the Temporary flag is TRUE (i.e. this object was
00157                 created to satisfy a direct attribute manipulation request as opposed to
00158                 rendering an attribute from a Camelot document tree), then the object is
00159                 deleted.
00160 
00161                 NB. This is a pure virtual function - any attribute value derived from
00162                     this class must implement this function so that it restores the
00163                     render region's attribute variables and objects to the correct state.
00164 
00165     SeeAlso:    RenderStack; AttributeValue; NodeAttribute;
00166                 AttributeValue::Render; AttributeValue::SimpleCopy
00167 
00168 ********************************************************************************************/
00169 
00170 /********************************************************************************************
00171 
00172 >   virtual void AttributeValue::Render(RenderRegion *pRegion)
00173 
00174     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00175     Created:    03/02/94
00176     Inputs:     pRegion - the render region to render this attribute into.
00177     Purpose:    Used when a render region needs to change a particular rendering attribute.
00178 
00179                 This usually occurs either because a tree is being rendered, and an
00180                 attribute node has been encountered and hence needs to be rendered, or
00181                 because a RenderRegion client (or sometimes the RenderRegion itself) has
00182                 asked to change an attribute directly, by name, as it were.  Examples of the
00183                 latter case might be:
00184 
00185                 MonoOn
00186                 pRegion->SetFillColour(COLOUR_BLACK);
00187                 pRegion->SetLineWidth(300);
00188                 pRegion->SetDrawingMode(DM_EORPEN);
00189                 MonoOff
00190 
00191                 NB. This is a pure virtual function - any attribute value derived from
00192                     this class must implement this function so that it sets the
00193                     render region's attribute variables and objects to the correct state.
00194                 
00195     SeeAlso:    RenderStack; AttributeValue; NodeAttribute;
00196                 AttributeValue::Restore; AttributeValue::SimpleCopy
00197 
00198 ********************************************************************************************/
00199 
00200 /********************************************************************************************
00201 
00202 >   virtual void AttributeValue::SimpleCopy(AttributeValue *pAttr)
00203 
00204     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00205     Created:    03/02/94
00206     Inputs:     pAttr - pointer to the AttributeValue to copy.
00207     Purpose:    This function provides a way of copying the contents of an AttributeValue
00208                 derived class to another.  It is assumed that the source object is the
00209                 same class as the destination object.
00210                 The data from the object pointed to by pAttr is copied into this object.
00211                 This is primarily used when cloning render regions - the context stack
00212                 must be copied, and if it points to any temporary objects, then they
00213                 must be copied too, to avoid multiple deletion errors.
00214     SeeAlso:    RenderStack; AttributeValue; NodeAttribute;
00215                 AttributeValue::Render; AttributeValue::Restore
00216 
00217 ********************************************************************************************/
00218 
00219 
00220 /********************************************************************************************
00221 
00222 >   NodeAttribute *AttributeValue::MakeNode()
00223 
00224     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00225     Created:    11/04/94
00226     Returns:    Pointer to NodeAttribute object, or NULL if out of memory.
00227     Purpose:    Given an AttributeValue object, construct the appropriate NodeAttribute
00228                 object which can be put into a document tree.
00229                 This should be over-ridden for all derived AttributeValue classes, except
00230                 those that cannot be put into the document tree (e.g. DrawingModeAttribute).
00231                 The base class version (i.e. this one) will always ENSURE because it
00232                 should not be called.
00233     Errors:     Out of memory.
00234     SeeAlso:    NodeAttribute
00235 
00236 ********************************************************************************************/
00237 
00238 NodeAttribute* AttributeValue::MakeNode()
00239 {
00240     TRACE( wxT("Error - Base class MakeNode() function called for a %s\n"),
00241           GetRuntimeClass()->GetClassName() );
00242     return NULL;
00243 }
00244 
00245 
00246 /********************************************************************************************
00247 >   NodeAttribute* AttributeValue::MakeNode(Node* pContextNode, AttachNodeDirection Direction)
00248 
00249     Author:     Ed_Cornes (Xara Group Ltd) <camelotdev@xara.com>
00250     Created:    26/5/95
00251     Inputs:     pContextNode - 
00252                 Direction    - 
00253     Returns:    Pointer to NodeAttribute object, or NULL if out of memory.
00254     Purpose:    Convert an attribute value into an attribute node and attatch to the context node
00255     SeeAlso:    AttributeValue::MakeNode()
00256 ********************************************************************************************/
00257 
00258 NodeAttribute* AttributeValue::MakeNode(Node* pContextNode, AttachNodeDirection Direction)
00259 {
00260     NodeAttribute* pAttrNode=MakeNode();
00261     if (pAttrNode!=NULL)
00262         pAttrNode->AttachNode(pContextNode, Direction, FALSE);
00263     return pAttrNode;
00264 }
00265 
00266 
00267 /********************************************************************************************
00268 
00269 >   BOOL AttributeValue::IsDifferent(AttributeValue *pAttr)
00270 
00271     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00272     Created:    12/04/94
00273     Inputs:     pAttr - the attribute to compare against this one.
00274     Returns:    TRUE if objects represent different attributes (e.g. one is red and the 
00275                      other is blue);
00276                 FALSE otherwise (i.e. they represent the same attribute, e.g. both 
00277                       represent 0.25pt lines).
00278     Purpose:    Compare two AttributeValue objects.
00279                 The base class version always returns TRUE - derived classes should
00280                 override this function to provide functionality.
00281     SeeAlso:    AttributeManager::ApplyBasedOnDefaults
00282 
00283 ********************************************************************************************/
00284 
00285 BOOL AttributeValue::IsDifferent(AttributeValue*)
00286 {
00287     return TRUE;
00288 }
00289 
00290 /********************************************************************************************
00291 
00292 >   BOOL AttributeValue::Blend(BlendAttrParam *pBlendParam)
00293 
00294     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00295     Created:    26/10/94
00296     Inputs:     pBlendParam = ptr to param holding all data needed for the attr val to blend
00297     Outputs:    if TRUE  returned, pBlendParam->GetBlendedAttrVal() will get ptr to the blended attr val
00298                 if FALSE returned, pBlendParam->GetBlendedAttrVal() will return NULL
00299     Returns:    TRUE if successful, FALSE otherwaie
00300     Purpose:    Blends this attr val with the attr val associated with the other NodeAttribute
00301                 ptr held in pBlendParam
00302                 This base version just returns FALSE, and sets the blended attr val ptr to NULL
00303     Errors:     Errors in debug builds
00304     SeeAlso:    -
00305 
00306 ********************************************************************************************/
00307 
00308 BOOL AttributeValue::Blend(BlendAttrParam *pBlendParam)
00309 {
00310     ERROR3("AttributeValue::Blend() called");
00311     pBlendParam->SetBlendedAttrVal(NULL);
00312     return FALSE;
00313 }
00314 
00315 
00316 /********************************************************************************************
00317 
00318 >   virtual AttributeValue *AttributeValue::MouldIntoStroke(PathStrokerVector *pMoulder,
00319                                                                 double TransScale);
00320     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00321     Created:    23/2/97
00322 
00323     Inputs:     pMoulder    - A PathStrokerVector which knows how to translate points to "mould" them
00324                               (May be NULL, in which case moulding of points does not occur)
00325 
00326                 TransScale  - A fraction between 0.0 and 1.0, by which any transparency
00327                               values in this geometry will be scaled, allowing the caller to
00328                               effectively apply a flat transparency level to everything that is
00329                               moulded. Use 1.0 to leave transparency unaltered.
00330 
00331     Returns:    NULL if there is no need to mould this attribute (so you should just
00332                 render the original attribute), else
00333                 A pointer to a copy of this object, suitably moulded and adjusted for
00334                 the transparency scaling. The caller must delete the copy when finished
00335                 with it.
00336 
00337     Purpose:    Helper function for the PathStrokerVector class, which "moulds" clipart
00338                 subtrees to lie along an arbitrary path.
00339 
00340                 This function is called to mould attributes, so that:
00341                     * Fill/Trans geometries can be moulded
00342                     * Line Widths can be scaled to an appropriate value
00343                     * A global flat transparency can be applied
00344                     etc
00345 
00346     Notes:      The base class does nothing (it returns NULL - by default, attrs assume that
00347                 they will work OK when moulded without being changed)
00348 
00349 ********************************************************************************************/
00350 
00351 AttributeValue *AttributeValue::MouldIntoStroke(PathStrokerVector *pMoulder, double TransScale)
00352 {
00353     return(NULL);
00354 }
00355 
00356 
00357 /********************************************************************************************
00358 >   virtual BOOL AttributeValue::CanBeRenderedDirectly()
00359     Author:     Ilan_Copelyn (Xara Group Ltd) <camelotdev@xara.com>
00360     Created:    27/4/00
00361     Inputs:     
00362     Outputs:    
00363     Returns:    
00364     Purpose:    There is only one case to date where AttributeValue are rendered directly ie 
00365                 without calling the render function of their associated/containing NodeAttribute
00366                 class. This occurs in RenderRegion::InitDevice().
00367                 This function is to determine if the AttributeValue can be rendered independently
00368                 of the NodeAttribute. It is only used in RR::InitDevice() at present but I am
00369                 defining it in order to highlight this new characteristic of nodes which are geometry
00370                 dependent, in order to ensure that this becomes an acknowledged attribute design
00371                 consideration (ie so that these special cases get handled correctly by future code
00372                 which may need to render AttributeValues directly)
00373     Errors:     
00374     SeeAlso:    -
00375 ********************************************************************************************/
00376 BOOL AttributeValue::CanBeRenderedDirectly()
00377 {
00378     return TRUE;
00379 }
00380 
00381 
00382 //------------------------------------------------------------
00383 //------------------------------------------------------------
00384 //------------------------------------------------------------
00385 
00386 LineWidthAttribute::LineWidthAttribute()
00387 {
00388     LineWidth = 500 + 1;  // BODGE The 1 added by Simon 25/10/95, so that the default attr 
00389                           // is different from the current attr. That way line scaling at 
00390                           // least works in simple cases.
00391 }
00392 
00393 /********************************************************************************************
00394 
00395 >   void LineWidthAttribute::Render(RenderRegion *pRegion)
00396 
00397     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00398     Created:    03/02/94
00399     Inputs:     pRegion - the render region to render this attribute into.
00400     Purpose:    Sets the line width attribute for the given render region. i.e. all
00401                 lines drawn will now be drawn with this line width.
00402     SeeAlso:    LineWidthAttribute; RenderStack; AttributeValue; NodeAttribute;
00403                 LineWidthAttribute::Restore; LineWidthAttribute::SimpleCopy;
00404                 AttributeValue::Render; AttributeValue::Restore; AttributeValue::SimpleCopy
00405 
00406 ********************************************************************************************/
00407 
00408 void LineWidthAttribute::Render(RenderRegion *pRegion, BOOL Temp)
00409 {
00410     pRegion->SetLineWidth(this, Temp);
00411 }
00412 
00413 /********************************************************************************************
00414 
00415 >   void LineWidthAttribute::Restore(RenderRegion *pRegion, BOOL Temp)
00416 
00417     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00418     Created:    03/02/94
00419     Inputs:     pRegion - the render region to restore the attribute into.
00420                 Temp    - TRUE if this is a temporary attribute, FALSE if it is
00421                           permanent (e.g. it's in a document tree).
00422     Purpose:    Restores the line width attribute for the given render region. i.e. all
00423                 lines drawn will now be drawn with this line width.
00424     SeeAlso:    LineWidthAttribute; RenderStack; AttributeValue; NodeAttribute;
00425                 LineWidthAttribute::Render; LineWidthAttribute::SimpleCopy;
00426                 AttributeValue::Render; AttributeValue::Restore; AttributeValue::SimpleCopy
00427 
00428 ********************************************************************************************/
00429 
00430 void LineWidthAttribute::Restore(RenderRegion *pRegion, BOOL Temp)
00431 {
00432     pRegion->RestoreLineWidth(this, Temp);
00433 }
00434 
00435 /********************************************************************************************
00436 
00437 >   void LineWidthAttribute::SimpleCopy(AttributeValue *pValue)
00438 
00439     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00440     Created:    03/02/94
00441     Inputs:     pAttr - pointer to the AttributeValue to copy.
00442     Purpose:    See AttributeValue::SimpleCopy
00443     SeeAlso:    LineWidthAttribute; RenderStack; AttributeValue; NodeAttribute;
00444                 LineWidthAttribute::Render; LineWidthAttribute::Restore;
00445                 AttributeValue::Render; AttributeValue::Restore; AttributeValue::SimpleCopy
00446 
00447 ********************************************************************************************/
00448 
00449 void LineWidthAttribute::SimpleCopy(AttributeValue *pValue)
00450 {
00451     LineWidth = ((LineWidthAttribute *) pValue)->LineWidth;
00452 }
00453 
00454 /********************************************************************************************
00455 
00456 >   BOOL LineWidthAttribute::Init()
00457 
00458     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00459     Created:    11/04/94
00460     Returns:    TRUE - initialised ok; FALSE if not.
00461     Purpose:    Registers line width attribute, and provides a default attribute to give
00462                 0.25pt lines.
00463     Errors:     Out of memory.
00464     SeeAlso:    AttributeManager
00465 
00466 ********************************************************************************************/
00467 
00468 BOOL LineWidthAttribute::Init()
00469 {
00470     // Default to 0.25pt lines
00471     LineWidthAttribute *pAttr = new LineWidthAttribute;
00472     if (pAttr == NULL)
00473         return FALSE;
00474 
00475     UINT32 ID = AttributeManager::RegisterDefaultAttribute(CC_RUNTIME_CLASS(NodeRenderableInk), 
00476                                                          pAttr);
00477     if (ID == ATTR_BAD_ID)
00478         return FALSE;
00479     ENSURE(ID == ATTR_LINEWIDTH, "Incorrect ID for attribute!");
00480     return TRUE;
00481 }
00482 
00483 /********************************************************************************************
00484 
00485 >   NodeAttribute *LineWidthAttribute::MakeNode()
00486 
00487     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00488     Created:    11/04/94
00489     Returns:    Pointer to the new node, or NULL if out of memory.
00490     Purpose:    Make a AttrLineWidth node from this line width attribute.
00491     Errors:     Out of memory
00492     SeeAlso:    AttributeValue::MakeNode
00493 
00494 ********************************************************************************************/
00495 
00496 NodeAttribute *LineWidthAttribute::MakeNode()
00497 {
00498     // Create new attribute node
00499     AttrLineWidth *pAttr = new AttrLineWidth();
00500 
00501     // Copy attribute value into the new node.
00502     pAttr->Value.SimpleCopy(this);
00503 
00504     // Return the new node
00505     return pAttr;
00506 }
00507 
00508 /********************************************************************************************
00509 
00510 >   BOOL LineWidthAttribute::IsDifferent(AttributeValue *pAttr)
00511 
00512     Author:     Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
00513     Created:    12/04/94
00514     Purpose:    See base class version.
00515     Errors:     The two attributes are not of the same type.
00516     SeeAlso:    AttributeValue::IsDifferent
00517 
00518 ********************************************************************************************/
00519 
00520 BOOL LineWidthAttribute::IsDifferent(AttributeValue *pAttr)
00521 {
00522     ENSURE(GetRuntimeClass() == pAttr->GetRuntimeClass(), 
00523            "Different attribute types in AttributeValue::IsDifferent()");
00524     return ((LineWidthAttribute *) pAttr)->LineWidth != LineWidth;
00525 }
00526 
00527 /********************************************************************************************
00528 
00529 >   BOOL LineWidthAttribute::Blend(BlendAttrParam *pBlendParam)
00530 
00531     Author:     Mark_Neves (Xara Group Ltd) <camelotdev@xara.com>
00532     Created:    26/10/94
00533     Inputs:     pBlendParam = ptr to param holding all data needed for the attr val to blend
00534     Outputs:    if TRUE  returned, pBlendParam->GetBlendedAttrVal() will get ptr to the blended attr val
00535                 if FALSE returned, pBlendParam->GetBlendedAttrVal() will return NULL
00536     Returns:    TRUE if successful, FALSE otherwaie
00537     Purpose:    Blends this attr val with the attr val held in pBlendParam
00538     SeeAlso:    -
00539 
00540 ********************************************************************************************/
00541 
00542 BOOL LineWidthAttribute::Blend(BlendAttrParam *pBlendParam)
00543 {
00544     // Check entry param
00545     ERROR3IF(pBlendParam == NULL,"NULL entry param");
00546     if (pBlendParam == NULL) return FALSE;
00547 
00548     LineWidthAttribute* pOtherLineAttr = (LineWidthAttribute*) pBlendParam->GetOtherAttrVal();
00549 
00550     // Check that the other line attr val is not NULL, and is a LineWidthAttribute
00551     ERROR3IF(pOtherLineAttr == NULL,"NULL other attr val");
00552     ERROR3IF(!IS_A(pOtherLineAttr,LineWidthAttribute),"other attr val not a line width attr");
00553     if (pOtherLineAttr == NULL || !IS_A(pOtherLineAttr,LineWidthAttribute)) return FALSE;
00554 
00555     // Get a new LineWidthAttribute to hold the blended version, (return FALSE if this fails)
00556     LineWidthAttribute* pBlendedLineAttr = new LineWidthAttribute;
00557     if (pBlendedLineAttr == NULL) return FALSE;
00558 
00559     // The blended line width is done by linearly tending the start line width to the
00560     // end line width, proportionally to the blend ration (0.0 to 1.0)
00561 
00562     // DeltaWidth is the amount to subtract from this LineWidth, and is proportional to BlendRatio
00563     MILLIPOINT DeltaWidth = INT32((LineWidth - pOtherLineAttr->LineWidth) * pBlendParam->GetBlendRatio());
00564 
00565     pBlendedLineAttr->LineWidth = LineWidth - DeltaWidth;
00566 
00567     // Store the ptr to the new blended line width attr val
00568     pBlendParam->SetBlendedAttrVal(pBlendedLineAttr);
00569 
00570     return TRUE;
00571 }
00572 
00573 /********************************************************************************************
00574 
00575 >   virtual AttributeValue *LineWidthAttribute::MouldIntoStroke(PathStrokerVector *pMoulder,
00576                                                                 double TransScale);
00577     Author:     Jason_Williams (Xara Group Ltd) <camelotdev@xara.com>
00578     Created:    23/2/97
00579 
00580     Inputs:     pMoulder    - A PathStrokerVector which knows how to translate points to "mould" them
00581                               (May be NULL, in which case moulding of points does not occur)
00582 
00583                 TransScale  - A fraction between 0.0 and 1.0, by which any transparency
00584                               values in this geometry will be scaled, allowing the caller to
00585                               effectively apply a flat transparency level to everything that is
00586                               moulded. Use 1.0 to leave transparency unaltered.
00587 
00588     Returns:    NULL if there is no need to mould this attribute (so you should just
00589                 render the original attribute), else
00590                 A pointer to a copy of this object, suitably moulded and adjusted for
00591                 the transparency scaling. The caller must delete the copy when finished
00592                 with it.
00593 
00594     Purpose:    Helper function for the PathStrokerVector class, which "moulds" clipart
00595                 subtrees to lie along an arbitrary path.
00596 
00597                 This function is called to mould attributes, so that:
00598                     * Fill/Trans geometries can be moulded
00599                     * Line Widths can be scaled to an appropriate value
00600                     * A global flat transparency can be applied
00601                     etc
00602 
00603     Notes:      The base class does nothing (it returns NULL - by default, attrs assume that
00604                 they will work OK when moulded without being changed)
00605 
00606 ********************************************************************************************/
00607 
00608 AttributeValue *LineWidthAttribute::MouldIntoStroke(PathStrokerVector *pMoulder, double TransScale)
00609 {
00610 #ifdef VECTOR_STROKING // Neville 6/8/97
00611     LineWidthAttribute* pMouldedAttr = new LineWidthAttribute;
00612     if (pMouldedAttr != NULL)
00613     {
00614         double ScaledWidth = pMoulder->GetScaleFactor() * (double)LineWidth;
00615         if (ScaledWidth < 1.0)
00616             ScaledWidth = 1.0;
00617         else if (pMouldedAttr->LineWidth > 1000000.0)
00618             ScaledWidth = 1000000.0;
00619         pMouldedAttr->LineWidth = (INT32)ScaledWidth;
00620     }
00621 
00622     return(pMouldedAttr);
00623 #else
00624     return NULL;
00625 #endif
00626 }
00627 
00628 
00629 
00630 //-----------------------------------------------------------------------
00631 //-----------------------------------------------------------------------
00632 //-----------------------------------------------------------------------
00633 //-----------------------------------------------------------------------
00634 
00635 /********************************************************************************************
00636 
00637 >   DashPatternAttribute::DashPatternAttribute()
00638 
00639     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00640     Created:    14/10/94
00641     Purpose:    Default Constructor for dash pattern attribute.
00642     Errors:     -
00643     SeeAlso:    -
00644 
00645 ********************************************************************************************/
00646 
00647 DashPatternAttribute::DashPatternAttribute()
00648 {
00649     DashPattern.Elements = 0;
00650     DashPattern.DashStart = 0;
00651 
00652     DashPattern.ElementData = NULL;
00653 
00654     DashPattern.LineWidth = 72000/4;
00655 }
00656 
00657 /********************************************************************************************
00658 
00659 >   DashPatternAttribute::~DashPatternAttribute()
00660 
00661     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00662     Created:    14/10/94
00663     Purpose:    Destructor for dash pattern attribute.
00664     SeeAlso:    -
00665 
00666 ********************************************************************************************/
00667 
00668 DashPatternAttribute::~DashPatternAttribute()
00669 {
00670     if (DashPattern.ElementData)
00671         delete DashPattern.ElementData;
00672 }
00673 
00674 /********************************************************************************************
00675 
00676 >   void DashPatternAttribute::Render(RenderRegion *pRegion)
00677 
00678     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00679     Created:    21/10/94
00680     Inputs:     pRegion - the render region to render this attribute into.
00681     Purpose:    Sets the dash pattern attribute for the given render region. i.e. all
00682                 lines drawn will now be drawn with this dash pattern.
00683     SeeAlso:    -
00684 
00685 ********************************************************************************************/
00686 
00687 void DashPatternAttribute::Render(RenderRegion *pRegion, BOOL Temp)
00688 {
00689     pRegion->SetDashPattern(this, Temp);
00690 }
00691 
00692 /********************************************************************************************
00693 
00694 >   void DashPatternAttribute::Restore(RenderRegion *pRegion, BOOL Temp)
00695 
00696     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00697     Created:    21/10/94
00698     Inputs:     pRegion - the render region to restore the attribute into.
00699                 Temp    - TRUE if this is a temporary attribute, FALSE if it is
00700                           permanent (e.g. it's in a document tree).
00701     Purpose:    Restores the dash pattern attribute for the given render region. i.e. all
00702                 lines drawn will now be drawn with this dash pattern.
00703     SeeAlso:    -
00704 
00705 ********************************************************************************************/
00706 
00707 void DashPatternAttribute::Restore(RenderRegion *pRegion, BOOL Temp)
00708 {
00709     pRegion->RestoreDashPattern(this, Temp);
00710 }
00711 
00712 /********************************************************************************************
00713 
00714 >   BOOL DashPatternAttribute::SetDashPattern(DashRec& NewDash)
00715 
00716     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00717     Created:    14/10/94
00718     Purpose:    Sets the dash pattern for this attribute.
00719     Errors:     No memory.
00720     SeeAlso:    -
00721 
00722 ********************************************************************************************/
00723 
00724 BOOL DashPatternAttribute::SetDashPattern(DashRec& NewDash)
00725 {
00726     DashPattern.Elements            = NewDash.Elements;
00727     DashPattern.DashStart           = NewDash.DashStart;
00728     DashPattern.LineWidth           = NewDash.LineWidth;
00729     DashPattern.DashID              = NewDash.DashID;
00730     DashPattern.ScaleWithLineWidth  = NewDash.ScaleWithLineWidth;
00731 
00732     if (NewDash.Elements == 0)
00733         return TRUE;
00734 
00735     if (DashPattern.ElementData != NULL)
00736         delete DashPattern.ElementData;
00737 
00738     DashPattern.ElementData = new INT32[NewDash.Elements];
00739 
00740     if (DashPattern.ElementData == NULL)
00741         return FALSE;
00742 
00743     for (INT32 element = 0; element < NewDash.Elements; element++)
00744     {
00745         DashPattern.ElementData[element] = NewDash.ElementData[element];
00746     }
00747 
00748     return TRUE;
00749 }
00750 
00751 /********************************************************************************************
00752 
00753 >   BOOL DashPatternAttribute::SetStockDashPattern(StockDash NewDash)
00754 
00755     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00756     Created:    14/10/94
00757     Purpose:    Sets the dash pattern for this attribute.
00758     Errors:     No memory.
00759     SeeAlso:    -
00760 
00761 ********************************************************************************************/
00762 
00763 BOOL DashPatternAttribute::SetStockDashPattern(StockDash NewDash)
00764 {
00765     DashRec StockDash;
00766     DashElement DashArray[8];
00767 
00768     const INT32 DashUnit = StockDash.LineWidth;
00769 
00770     StockDash.DashID = NewDash;
00771 
00772     switch (NewDash)
00773     {
00774         case SD_SOLID:
00775             StockDash.Elements = 0;
00776             SetDashPattern(StockDash);
00777             break;
00778 
00779         case SD_DASH1:
00780             StockDash.Elements = 2;
00781             StockDash.DashStart = 0;
00782             StockDash.ElementData = DashArray;
00783             DashArray[0] = DashUnit*2;
00784             DashArray[1] = DashUnit*2;
00785 
00786             SetDashPattern(StockDash);
00787             break;
00788 
00789         case SD_DASH2:
00790             StockDash.Elements = 2;
00791             StockDash.DashStart = 0;
00792             StockDash.ElementData = DashArray;
00793             DashArray[0] = DashUnit*4;
00794             DashArray[1] = DashUnit*2;
00795 
00796             SetDashPattern(StockDash);
00797             break;
00798 
00799         case SD_DASH3:
00800             StockDash.Elements = 2;
00801             StockDash.DashStart = 0;
00802             StockDash.ElementData = DashArray;
00803             DashArray[0] = DashUnit*8;
00804             DashArray[1] = DashUnit*2;
00805 
00806             SetDashPattern(StockDash);
00807             break;
00808 
00809         case SD_DASH4:
00810             StockDash.Elements = 2;
00811             StockDash.DashStart = 0;
00812             StockDash.ElementData = DashArray;
00813             DashArray[0] = DashUnit*16;
00814             DashArray[1] = DashUnit*2;
00815 
00816             SetDashPattern(StockDash);
00817             break;
00818 
00819         case SD_DASH5:
00820             StockDash.Elements = 2;
00821             StockDash.DashStart = 0;
00822             StockDash.ElementData = DashArray;
00823             DashArray[0] = DashUnit*24;
00824             DashArray[1] = DashUnit*2;
00825 
00826             SetDashPattern(StockDash);
00827             break;
00828 
00829         case SD_DASH6:
00830             StockDash.Elements = 2;
00831             StockDash.DashStart = 0;
00832             StockDash.ElementData = DashArray;
00833             DashArray[0] = DashUnit*4;
00834             DashArray[1] = DashUnit*4;
00835 
00836             SetDashPattern(StockDash);
00837             break;
00838 
00839         case SD_DASH7:
00840             StockDash.Elements = 2;
00841             StockDash.DashStart = 0;
00842             StockDash.ElementData = DashArray;
00843             DashArray[0] = DashUnit*8;
00844             DashArray[1] = DashUnit*4;
00845 
00846             SetDashPattern(StockDash);
00847             break;
00848 
00849         case SD_DASH8:
00850             StockDash.Elements = 2;
00851             StockDash.DashStart = 0;
00852             StockDash.ElementData = DashArray;
00853             DashArray[0] = DashUnit*16;
00854             DashArray[1] = DashUnit*4;
00855 
00856             SetDashPattern(StockDash);
00857             break;
00858 
00859         case SD_DASH9:
00860             StockDash.Elements = 2;
00861             StockDash.DashStart = 0;
00862             StockDash.ElementData = DashArray;
00863             DashArray[0] = DashUnit*8;
00864             DashArray[1] = DashUnit*8;
00865 
00866             SetDashPattern(StockDash);
00867             break;
00868 
00869         case SD_DASH10:
00870             StockDash.Elements = 2;
00871             StockDash.DashStart = 0;
00872             StockDash.ElementData = DashArray;
00873             DashArray[0] = DashUnit*16;
00874             DashArray[1] = DashUnit*8;
00875 
00876             SetDashPattern(StockDash);
00877             break;
00878 
00879         case SD_DASH11:
00880             StockDash.Elements = 4;
00881             StockDash.DashStart = 0;
00882             StockDash.ElementData = DashArray;
00883             DashArray[0] = DashUnit*4;
00884             DashArray[1] = DashUnit*2;
00885             DashArray[2] = DashUnit*2;
00886             DashArray[3] = DashUnit*2;
00887 
00888             SetDashPattern(StockDash);
00889             break;
00890 
00891         case SD_DASH12:
00892             StockDash.Elements = 4;
00893             StockDash.DashStart = 0;
00894             StockDash.ElementData = DashArray;
00895             DashArray[0] = DashUnit*8;
00896             DashArray[1] = DashUnit*2;
00897             DashArray[2] = DashUnit*2;
00898             DashArray[3] = DashUnit*2;
00899 
00900             SetDashPattern(StockDash);
00901             break;
00902 
00903         case SD_DASH13:
00904             StockDash.Elements = 4;
00905             StockDash.DashStart = 0;
00906             StockDash.ElementData = DashArray;
00907             DashArray[0] = DashUnit*16;
00908             DashArray[1] = DashUnit*2;
00909             DashArray[2] = DashUnit*2;
00910             DashArray[3] = DashUnit*2;
00911 
00912             SetDashPattern(StockDash);
00913             break;
00914 
00915         case SD_DASH14:
00916             StockDash.Elements = 4;
00917             StockDash.DashStart = 0;
00918             StockDash.ElementData = DashArray;
00919             DashArray[0] = DashUnit*8;
00920             DashArray[1] = DashUnit*2;
00921             DashArray[2] = DashUnit*4;
00922             DashArray[3] = DashUnit*2;
00923 
00924             SetDashPattern(StockDash);
00925             break;
00926 
00927         case SD_DASH15:
00928             StockDash.Elements = 4;
00929             StockDash.DashStart = 0;
00930             StockDash.ElementData = DashArray;
00931             DashArray[0] = DashUnit*16;
00932             DashArray[1] = DashUnit*2;
00933             DashArray[2] = DashUnit*4;
00934             DashArray[3] = DashUnit*2;
00935 
00936             SetDashPattern(StockDash);
00937             break;
00938 
00939         case SD_DASH16:
00940             StockDash.Elements = 6;
00941             StockDash.DashStart = 0;
00942             StockDash.ElementData = DashArray;
00943             DashArray[0] = DashUnit*8;
00944             DashArray[1] = DashUnit*2;
00945             DashArray[2] = DashUnit*2;
00946             DashArray[3] = DashUnit*2;
00947             DashArray[4] = DashUnit*2;
00948             DashArray[5] = DashUnit*2;
00949 
00950             SetDashPattern(StockDash);
00951             break;
00952 
00953         case SD_DASH17:
00954             StockDash.Elements = 6;
00955             StockDash.DashStart = 0;
00956             StockDash.ElementData = DashArray;
00957             DashArray[0] = DashUnit*16;
00958             DashArray[1] = DashUnit*2;
00959             DashArray[2] = DashUnit*2;
00960             DashArray[3] = DashUnit*2;
00961             DashArray[4] = DashUnit*2;
00962             DashArray[5] = DashUnit*2;
00963 
00964             SetDashPattern(StockDash);
00965             break;
00966 
00967         case SD_DASH18:
00968             StockDash.Elements = 8;
00969             StockDash.DashStart = 0;
00970             StockDash.ElementData = DashArray;
00971             DashArray[0] = DashUnit*8;
00972             DashArray[1] = DashUnit*2;
00973             DashArray[2] = DashUnit*2;
00974             DashArray[3] = DashUnit*2;
00975             DashArray[4] = DashUnit*2;
00976             DashArray[5] = DashUnit*2;
00977             DashArray[6] = DashUnit*2;
00978             DashArray[7] = DashUnit*2;
00979 
00980             SetDashPattern(StockDash);
00981             break;
00982 
00983         case SD_DASH19:
00984             StockDash.Elements = 8;
00985             StockDash.DashStart = 0;
00986             StockDash.ElementData = DashArray;
00987             DashArray[0] = DashUnit*16;
00988             DashArray[1] = DashUnit*2;
00989             DashArray[2] = DashUnit*2;
00990             DashArray[3] = DashUnit*2;
00991             DashArray[4] = DashUnit*2;
00992             DashArray[5] = DashUnit*2;
00993             DashArray[6] = DashUnit*2;
00994             DashArray[7] = DashUnit*2;
00995 
00996             SetDashPattern(StockDash);
00997             break;
00998 
00999         case SD_DASH20:
01000             StockDash.Elements = 8;
01001             StockDash.DashStart = 0;
01002             StockDash.ElementData = DashArray;
01003             DashArray[0] = DashUnit*8;
01004             DashArray[1] = DashUnit*2;
01005             DashArray[2] = DashUnit*2;
01006             DashArray[3] = DashUnit*2;
01007             DashArray[4] = DashUnit*4;
01008             DashArray[5] = DashUnit*2;
01009             DashArray[6] = DashUnit*2;
01010             DashArray[7] = DashUnit*2;
01011 
01012             SetDashPattern(StockDash);
01013             break;
01014 
01015         case SD_DASH_GUIDELAYER:
01016             // This is the dash pattern used to render objects in guide layers with.
01017             // It's different to the others in that the dashed aren't scaled relative to the line width
01018             StockDash.Elements = 2;
01019             StockDash.DashStart = 0;
01020             StockDash.ElementData = DashArray;
01021             StockDash.ScaleWithLineWidth = FALSE;
01022             DashArray[0] = DashUnit*2;
01023             DashArray[1] = DashUnit*2;
01024 
01025             SetDashPattern(StockDash);
01026             break;
01027 
01028         default:
01029             StockDash.Elements = 0;
01030             StockDash.DashStart = 0;
01031             StockDash.ElementData = NULL;
01032 
01033             SetDashPattern(StockDash);
01034             break;
01035     }
01036 
01037     return TRUE;
01038 }
01039 
01040 DashRec::DashRec()
01041 {
01042     Elements = 0;
01043     DashStart = 0;
01044     ElementData = NULL;
01045     DashID = 0;
01046     ScaleWithLineWidth = TRUE;
01047 
01048     LineWidth = 72000/4;
01049 }
01050 
01051 String_256 DashRec::GetStockDashName(StockDash DashType)
01052 {
01053     String_256 DashName;
01054 
01055     switch (DashType)
01056     {
01057         case SD_SOLID:
01058             DashName.Load(_R(IDS_K_ATTR_SOLIDLINE));
01059             break;
01060 
01061         default:
01062             DashName.Load(_R(IDS_K_ATTR_DASHLINE));
01063             break;
01064     }
01065 
01066     return DashName;
01067 }
01068 
01069 /********************************************************************************************
01070 
01071 >   void DashRec::CheckAndFix()
01072 
01073     Author:     Ben_Summers (Xara Group Ltd) <camelotdev@xara.com>
01074     Created:    04/07/95
01075     Purpose:    Checks a dash pattern, and fixes it if it's not very nice.
01076     Errors:     No errors.
01077     SeeAlso:    -
01078 
01079 ********************************************************************************************/
01080 
01081 void DashRec::CheckAndFix()
01082 {
01083     // check the dash offset
01084     if(DashStart < 0)
01085         DashStart = 0;
01086 
01087     if(Elements == 0)
01088         return;
01089 
01090     // check the dash pattern elements
01091     INT32 End = 0;
01092     INT32 l;
01093 
01094     for(l = 0; l < Elements; l++)
01095     {
01096 
01097         // is this element OK?
01098         if(ElementData[l] > 0)
01099         {
01100             // element is OK...
01101             if(End != l)
01102             {
01103                 // move it back if something has been deleted before it
01104                 ElementData[End] = ElementData[l];
01105             }
01106             End++;
01107         }
01108     }
01109 
01110     // have we got enough elements?
01111     if(End < 1)
01112     {
01113         // no elements - make it a solid outline
01114         Elements = 0;
01115         DashID = SD_SOLID;
01116     }
01117     else
01118     {
01119         Elements = End;
01120     }
01121 }
01122 
01123 /********************************************************************************************
01124 
01125 >   void DashRec::CheckIfDefaultPattern()
01126 
01127     Author:     Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com>
01128     Created:    26/07/96
01129     Purpose:    Checks a dash pattern to see if it is one of the built in ones and if so
01130                 then sets the ID to be correct.
01131                 Not the best way but a) its quick, b) it works, c) not three million
01132                 big rebuilds of 330 files to get it right
01133 
01134                 This is mainly required for the following reason:
01135                 When we save Native files we at present save out a dash pattern ID and then
01136                 save out the full dash pattern definition! This is ok apart from wasting space.
01137                 The problem happens when we load the information back in, we load the id and apply
01138                 the relevent dash pattern and then load the definition and apply it, zapping the
01139                 id.
01140     Errors:     No errors.
01141     SeeAlso:    -
01142 
01143 ********************************************************************************************/
01144 
01145 /* Disable the code as completely useless as we scale the line widths when we first save them
01146    in a old format xar file! So the simple fix becomes a nightmare!
01147 
01148 void DashRec::CheckIfDefaultPattern()
01149 {
01150     // Check to see if the pattern corresponds to one of our built in ones
01151     // If so then set the DashID accordingly
01152     // Default is do nothing
01153     // SD_SOLID == 0 so if this then do nothing
01154 
01155     const INT32 DefLineWidth = 72000/4;
01156     const INT32 DashUnit = DefLineWidth;
01157 
01158     // All the useful defaults are defined like this using the default constructed
01159     // values, so if they are different then its not default pattern
01160     if (LineWidth != DefLineWidth || DashID != 0 || DashStart != 0 || Elements == 0)
01161         return;
01162     
01163     // The SD_DASH_GUIDELAYER has 2 elements and is the only one to have ScaleWithLineWidth = FALSE
01164     if (ScaleWithLineWidth != TRUE && Elements != 2)
01165         return;
01166 
01167     switch (Elements)
01168     {
01169         case 2:
01170         {
01171             switch (ElementData[1])
01172             {
01173                 case DashUnit*2:
01174                 {
01175                     switch (ElementData[0])
01176                     {
01177                         case DashUnit*2:
01178                             if (ScaleWithLineWidth)
01179                                 DashID = SD_DASH1;
01180                             else
01181                                 DashID = SD_DASH_GUIDELAYER;
01182                             break;
01183                         case DashUnit*4:
01184                             DashID = SD_DASH2;
01185                             break;
01186                         case DashUnit*8:
01187                             DashID = SD_DASH3;
01188                             break;
01189                         case DashUnit*16:
01190                             DashID = SD_DASH4;
01191                             break;
01192                         case DashUnit*24:
01193                             DashID = SD_DASH5;
01194                             break;
01195                     }
01196                 }
01197                 break;
01198 
01199                 case DashUnit*4:
01200                 {
01201                     switch (ElementData[0])
01202                     {
01203                         case DashUnit*4:
01204                             DashID = SD_DASH6;
01205                             break;
01206                         case DashUnit*8:
01207                             DashID = SD_DASH7;
01208                             break;
01209                         case DashUnit*16:
01210                             DashID = SD_DASH8;
01211                             break;
01212                     }
01213                 }
01214                 break;
01215 
01216                 case DashUnit*8:
01217                 {
01218                     switch (ElementData[0])
01219                     {
01220                         case DashUnit*8:
01221                             DashID = SD_DASH9;
01222                             break;
01223                         case DashUnit*16:
01224                             DashID = SD_DASH10;
01225                             break;
01226                     }
01227                 }
01228                 break;
01229             }
01230             break;
01231         }
01232 
01233         case 4:
01234         { 
01235             // All our current definitions have the 1st and 3rd elements == DashUnit*2 
01236             if (
01237                     ElementData[1] != DashUnit*2 ||
01238                     ElementData[3] != DashUnit*2
01239                )
01240                 return;
01241             
01242             switch (ElementData[2])
01243             {
01244                 case DashUnit*2:
01245                     switch (ElementData[0])
01246                     {
01247                         case DashUnit*4:
01248                             DashID = SD_DASH11;
01249                             break;
01250                         case DashUnit*8:
01251                             DashID = SD_DASH12;
01252                             break;
01253                         case DashUnit*16:
01254                             DashID = SD_DASH13;
01255                             break;
01256                     }
01257                     break;
01258                 case DashUnit*4:
01259                     switch (ElementData[0])
01260                     {
01261                         case DashUnit*8:
01262                             DashID = SD_DASH14;
01263                             break;
01264                         case DashUnit*16:
01265                             DashID = SD_DASH15;
01266                             break;
01267                     }
01268                     break;
01269             }
01270 
01271             break;
01272         }
01273 
01274         case 6: 
01275         {
01276             if (
01277                     ElementData[0] == DashUnit*8 &&
01278                     ElementData[1] == DashUnit*2 &&
01279                     ElementData[2] == DashUnit*2 &&
01280                     ElementData[3] == DashUnit*2 &&
01281                     ElementData[4] == DashUnit*2 &&
01282                     ElementData[5] == DashUnit*2
01283                 )
01284                     DashID = SD_DASH16;
01285             else if (
01286                         ElementData[0] == DashUnit*16 &&
01287                         ElementData[1] == DashUnit*2 &&
01288                         ElementData[2] == DashUnit*2 &&
01289                         Eleme