00001 // $Id: strkattr.cpp 1688 2006-08-10 12:05:20Z gerry $ 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 // strkattr.cpp - Path stroking attributes 00099 00100 #include "camtypes.h" 00101 00102 //#include "attrmgr.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00103 //#include "jason.h" 00104 #include "ppairbsh.h" // PathProcessorStrokeAirbrush 00105 #include "ppstroke.h" // PathProcessorStroke 00106 #include "ppvecstr.h" // PathProcessorStrokeVector 00107 //#include "rndrgn.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00108 #include "strkattr.h" 00109 #include "strkcomp.h" 00110 #include "valfunc.h" 00111 00112 // Native file load/save includes 00113 //#include "camfiltr.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00114 //#include "cxfdefs.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00115 //#include "cxfrec.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00116 #include "cxftags.h" 00117 //#include "tim.h" // For _R(IDE_FILE_WRITE_ERROR) 00118 00119 //#include "becomea.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00120 #include "nodepath.h" 00121 #include "pbecomea.h" // for pathbecomea 00122 // Stroke classes 00123 CC_IMPLEMENT_DYNCREATE(AttrStrokeType, NodeAttribute) 00124 CC_IMPLEMENT_DYNAMIC(StrokeTypeAttrValue, AttributeValue) 00125 00126 // Variable width classes 00127 CC_IMPLEMENT_DYNCREATE(AttrVariableWidth, NodeAttribute) 00128 CC_IMPLEMENT_DYNAMIC(VariableWidthAttrValue, AttributeValue) 00129 00130 // Version 2 file format loading handler for all Stroke attributes 00131 CC_IMPLEMENT_DYNAMIC(StrokeAttrRecordHandler, CamelotRecordHandler); 00132 00133 00134 // Declare smart memory handling in Debug builds 00135 #define new CAM_DEBUG_NEW 00136 00137 00138 00139 /******************************************************************************************** 00140 00141 > AttrStrokeType::AttrStrokeType() 00142 00143 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00144 Created: 7/1/97 00145 00146 Purpose: Default constructor for AttrStrokeType 00147 00148 ********************************************************************************************/ 00149 00150 AttrStrokeType::AttrStrokeType() 00151 { 00152 } 00153 00154 00155 00156 /******************************************************************************************** 00157 00158 > AttrStrokeType::AttrStrokeType(Node *ContextNode, 00159 AttachNodeDirection Direction, 00160 BOOL Locked, 00161 BOOL Mangled, 00162 BOOL Marked, 00163 BOOL Selected) 00164 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00165 Created: 7/1/97 00166 00167 Purpose: Constructs an AttrStrokeType Attribute 00168 00169 ********************************************************************************************/ 00170 00171 AttrStrokeType::AttrStrokeType(Node *ContextNode, 00172 AttachNodeDirection Direction, 00173 BOOL Locked, 00174 BOOL Mangled, 00175 BOOL Marked, 00176 BOOL Selected) 00177 : NodeAttribute(ContextNode, Direction, Locked, Mangled, Marked, Selected) 00178 { 00179 } 00180 00181 00182 00183 /******************************************************************************************** 00184 00185 > virtual void AttrStrokeType::Render(RenderRegion *pRender) 00186 00187 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00188 Created: 7/1/97 00189 00190 Purpose: Renders this attribute (by simply calling the Render function of 00191 its contained AttributeValue) 00192 00193 ********************************************************************************************/ 00194 00195 void AttrStrokeType::Render(RenderRegion *pRender) 00196 { 00197 GetAttributeValue()->Render(pRender); 00198 } 00199 00200 00201 00202 /*********************************************************************************************** 00203 00204 > virtual void AttrStrokeType::CopyNodeContents(AttrStrokeType *NodeCopy) 00205 00206 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00207 Created: 8/1/97 00208 00209 Outputs: NodeCopy - returned containing a copy of this node 00210 00211 Purpose: Copies the node's contents to the node pointed to by NodeCopy 00212 00213 ***********************************************************************************************/ 00214 00215 void AttrStrokeType::CopyNodeContents(AttrStrokeType *NodeCopy) 00216 { 00217 // Let the base class do its bit 00218 NodeAttribute::CopyNodeContents(NodeCopy); 00219 00220 // And then copy our Value 00221 *(NodeCopy->GetAttributeValue()) = *(GetAttributeValue()); 00222 } 00223 00224 00225 00226 /*********************************************************************************************** 00227 > void AttrStrokeType::PolyCopyNodeContents(NodeRenderable* pNodeCopy) 00228 00229 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 00230 Created: 18/12/2003 00231 Outputs: - 00232 Purpose: Polymorphically copies the contents of this node to another 00233 Errors: An assertion failure will occur if NodeCopy is NULL 00234 Scope: protected 00235 00236 ***********************************************************************************************/ 00237 00238 void AttrStrokeType::PolyCopyNodeContents(NodeRenderable* pNodeCopy) 00239 { 00240 ENSURE(pNodeCopy, "Trying to copy a node's contents into a NULL node"); 00241 ENSURE(IS_A(pNodeCopy, AttrStrokeType), "PolyCopyNodeContents given wrong dest node type"); 00242 00243 if (IS_A(pNodeCopy, AttrStrokeType)) 00244 CopyNodeContents((AttrStrokeType*)pNodeCopy); 00245 } 00246 00247 00248 00249 /*********************************************************************************************** 00250 00251 > virtual INT32 AttrStrokeType::operator==(const NodeAttribute &NodeAttrib); 00252 00253 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00254 Created: 8/1/97 00255 00256 Inputs: NodeAttrib - The node to compare this node to 00257 Returns: TRUE if the nodes are considered equal 00258 00259 Purpose: Comparison operator - determines if the AttributeValues of both objects are == 00260 00261 ***********************************************************************************************/ 00262 00263 INT32 AttrStrokeType::operator==(const NodeAttribute &NodeAttrib) 00264 { 00265 // First check they are of the same type 00266 if (((NodeAttribute*)&NodeAttrib)->GetAttributeType() != GetAttributeType()) 00267 return FALSE; 00268 00269 // Make a more sensible pointer 00270 AttrStrokeType *Attr = (AttrStrokeType *) &NodeAttrib; 00271 00272 // Now let the AttributeValues compare themselves 00273 return( *((StrokeTypeAttrValue *) Attr->GetAttributeValue()) == 00274 *((StrokeTypeAttrValue *) GetAttributeValue()) ); 00275 } 00276 00277 00278 00279 /******************************************************************************************** 00280 00281 > virtual Node *AttrStrokeType::SimpleCopy() 00282 00283 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00284 Created: 8/1/97 00285 00286 Returns: A copy of the node, or NULL if memory runs out 00287 00288 Purpose: This method returns a shallow copy of the node with all Node pointers NULL. 00289 The function is virtual, and must be defined for all derived classes. 00290 00291 ********************************************************************************************/ 00292 00293 Node *AttrStrokeType::SimpleCopy() 00294 { 00295 AttrStrokeType* NodeCopy = new AttrStrokeType; 00296 if (NodeCopy == NULL) 00297 return(NULL); 00298 00299 // Call the base class 00300 NodeAttribute::CopyNodeContents(NodeCopy); 00301 00302 // And call our AttributeValue to copy itself too 00303 NodeCopy->GetAttributeValue()->SimpleCopy(GetAttributeValue()); 00304 00305 return(NodeCopy); 00306 } 00307 00308 00309 00310 /******************************************************************************************** 00311 00312 > virtual UINT32 AttrStrokeType::GetAttrNameID(void) 00313 00314 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00315 Created: 8/1/97 00316 00317 Returns: Attribute description string-resource ID 00318 00319 Purpose: Retrieves a string resource ID describing this attribute 00320 00321 ********************************************************************************************/ 00322 00323 UINT32 AttrStrokeType::GetAttrNameID(void) 00324 { 00325 return(_R(IDS_ATTRSTROKETYPE)); 00326 } 00327 00328 /******************************************************************************************** 00329 > virtual BOOL AttrStokeType::NeedsTransparency() const 00330 00331 Author: Richard_Millican (Xara Group Ltd) <camelotdev@xara.com> 00332 Created: 7/2/97 00333 Inputs: - 00334 Outputs: - 00335 Returns: TRUE if this Attribute requires transparency mode to render properly. 00336 Purpose: Strokes like the airbrush require transparency to be turned on to work. 00337 Errors: - 00338 ********************************************************************************************/ 00339 00340 BOOL AttrStrokeType::NeedsTransparency() const 00341 { 00342 BOOL SoWeDoReallyNeedTransparencyThenDoWe = FALSE; 00343 00344 PathProcessorStroke *pPathProc = Value.GetPathProcessor(); 00345 if(pPathProc != NULL) 00346 { 00347 SoWeDoReallyNeedTransparencyThenDoWe = pPathProc->NeedsTransparency(); 00348 } 00349 00350 return SoWeDoReallyNeedTransparencyThenDoWe; 00351 } 00352 00353 00354 /******************************************************************************************** 00355 00356 > virtual void AttrStrokeType::GetDebugDetails(StringBase *Str) 00357 00358 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00359 Created: 8/1/97 00360 00361 Outputs: On return, Str is filled in with details on this node 00362 00363 Purpose: Produces debug details about this node 00364 00365 ********************************************************************************************/ 00366 00367 void AttrStrokeType::GetDebugDetails(StringBase *Str) 00368 { 00369 #ifdef _DEBUG 00370 NodeAttribute::GetDebugDetails(Str); 00371 00372 String_256 TempStr; 00373 TempStr._MakeMsg( _T("\r\nStroke type #1%s\r\n"), 00374 (Value.GetPathProcessor() == NULL) ? _T("old-style line") : _T("new stroke:") ); 00375 *Str += TempStr; 00376 00377 if (Value.GetPathProcessor() != NULL) 00378 { 00379 TempStr._MakeMsg( _T(" #1%s\r\n"), 00380 Value.GetPathProcessor()->GetRuntimeClass()->GetClassName() ); 00381 *Str += TempStr; 00382 } 00383 00384 TempStr._MakeMsg( _T("\r\nNeedsTransparency=#1%s\r\n"), NeedsTransparency() ? _T("TRUE") : _T("FALSE") ); 00385 *Str += TempStr; 00386 00387 #endif 00388 } 00389 00390 00391 /******************************************************************************************** 00392 00393 > BOOL AttrStrokeType::HasPathProcessor() 00394 00395 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00396 Created: 17/3/2000 00397 Inputs: - 00398 Outputs: - 00399 Returns: TRUE if attribute value has a path processor, FALSE otherwise 00400 Purpose: A good way to determine if this is one of the default attributes 00401 00402 ********************************************************************************************/ 00403 00404 BOOL AttrStrokeType::HasPathProcessor() 00405 { 00406 if (Value.GetPathProcessor() == NULL) 00407 return FALSE; 00408 return TRUE; 00409 } 00410 00411 00412 /******************************************************************************************** 00413 00414 > PathProcessorStroke* AttrStrokeType::GetPathProcessor() 00415 00416 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00417 Created: 17/3/2000 00418 Inputs: - 00419 Outputs: - 00420 Returns: the path processor of our attribute value 00421 Purpose: Convenience function 00422 00423 ********************************************************************************************/ 00424 00425 PathProcessorStroke* AttrStrokeType::GetPathProcessor() 00426 { 00427 return Value.GetPathProcessor(); 00428 } 00429 00430 00431 00432 /******************************************************************************************** 00433 00434 > virtual BOOL AttrStrokeType::DoBecomeA(BecomeA* pBecomeA, Node* pParent) 00435 00436 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00437 Created: 17/3/2000 00438 Inputs: pBecomeA - the becomeA object that tells us what to do 00439 pParent - the node that this attribute is applied to 00440 Outputs: 00441 Returns: TRUE if everything went ok, 00442 Purpose: Its a little unusual for attributes to have their own dobecomea function but 00443 this stroke attribute requires one due to all the work it does on paths. 00444 00445 ********************************************************************************************/ 00446 00447 BOOL AttrStrokeType::DoBecomeA(BecomeA* pBecomeA, Node* pParent) 00448 { 00449 ERROR2IF(pBecomeA == NULL, FALSE, "BecomeA pointer is NULL in AttrBrushType::DoBecomeA"); 00450 ERROR2IF(pParent == NULL, FALSE, "Parent node is NULL in AttrBrushType::DoBecomeA"); 00451 return Value.DoBecomeA(pBecomeA, pParent); 00452 } 00453 00454 00455 /******************************************************************************************** 00456 00457 > virtual UINT32 AttrStrokeType::GetNodeSize() const 00458 00459 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00460 Created: 8/1/97 00461 00462 Returns: The size of this node, in bytes 00463 00464 Purpose: For finding the size of the node, in bytes 00465 00466 ********************************************************************************************/ 00467 00468 UINT32 AttrStrokeType::GetNodeSize() const 00469 { 00470 return(sizeof(AttrStrokeType)); 00471 } 00472 00473 00474 00475 /******************************************************************************************** 00476 00477 > virtual BOOL AttrStrokeType::WritePreChildrenWeb(BaseCamelotFilter *pFilter) 00478 > virtual BOOL AttrStrokeType::WritePreChildrenNative(BaseCamelotFilter *pFilter) 00479 00480 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00481 Created: 8/1/97 00482 00483 Inputs: pFilter - filter to write to 00484 00485 Returns: TRUE if the Node has written out a record to the filter 00486 00487 Purpose: Writes out a record that represents the node, to either Native or Web 00488 file format. 00489 00490 This function is called before any of the AttrStrokeType's children 00491 are written to the filter. 00492 00493 If the AttrStrokeType writes out a record successfully to the file, 00494 it will return TRUE. 00495 00496 If the AttrStrokeType chooses not to write itself to the filter 00497 (e.g. because it is not appropriate for this filter), then this 00498 function will return FALSE. 00499 00500 Notes: Simple StrokeTypes (not using fancy bitmap/vector brushes) just 00501 write out a 4-byte (UINT32) record containing the stroke type. 00502 Defined stroke types at this time are: 00503 0 - Simple variable width stroke 00504 00505 SeeAlso: Node::WritePreChildrenNative; Node::WritePreChildrenWeb; 00506 StrokeAttrRecordHandler::HandleRecord 00507 00508 ********************************************************************************************/ 00509 00510 BOOL AttrStrokeType::WritePreChildrenWeb(BaseCamelotFilter *pFilter) 00511 { 00512 return(WritePreChildrenNative(pFilter)); 00513 } 00514 00515 BOOL AttrStrokeType::WritePreChildrenNative(BaseCamelotFilter *pFilter) 00516 { 00517 #ifdef DO_EXPORT 00518 ERROR3IF(pFilter == NULL, "Illegal NULL param"); 00519 00520 BOOL ok = TRUE; 00521 PathProcessorStroke *pProcessor = Value.GetPathProcessor(); 00522 00523 // Jason's being lazy this month, I'm afraid, because he won't be here next month... 00524 if (pProcessor == NULL || 00525 !pProcessor->IsKindOf(CC_RUNTIME_CLASS(PathProcessorStrokeAirbrush))) 00526 { 00527 // It is a simple var-width stroke, or it is a vector stroke. These both export as 00528 // the same basic record tag, but with different "handle" words 00529 StrokeHandle Handle = 0x02000000; 00530 00531 // Get the handle of the stroke 00532 if (pProcessor == NULL) 00533 Handle = 0x01000000; 00534 else if (pProcessor->IsKindOf(CC_RUNTIME_CLASS(PathProcessorStrokeVector))) 00535 { 00536 Handle = ((PathProcessorStrokeVector *)pProcessor)->GetStrokeDefinition(); 00537 ERROR3IF((Handle & 0xff000000) != 0, "Handle overflow"); 00538 00539 // Make sure the stroke definition has preceeded any references to it 00540 ok = StrokeComponent::ExportStroke(pFilter, Handle); 00541 } 00542 //else 00543 // it's a simple variable-width (base class) stroker, so we need not do anything 00544 00545 // And write the record 00546 if (ok) 00547 { 00548 CamelotFileRecord Rec(pFilter, TAG_STROKETYPE, TAG_STROKETYPE_SIZE); 00549 00550 if (ok) ok = Rec.Init(); 00551 if (ok) ok = Rec.WriteUINT32((UINT32) Handle); 00552 if (ok) ok = pFilter->Write(&Rec); 00553 } 00554 } 00555 else 00556 { 00557 PathProcessorStrokeAirbrush *pProcessor = (PathProcessorStrokeAirbrush *) 00558 Value.GetPathProcessor(); 00559 00560 ValueFunction *pFunction = pProcessor->GetIntensityFunction(); 00561 ERROR3IF(pFunction == NULL, "No intensity function!?"); 00562 00563 // Currently, an airbrush record consists only of its intensity ValueFunction 00564 CamelotFileRecord *pRec = pFunction->WriteFileRecord(TAG_STROKEAIRBRUSH, 0, pFilter); 00565 if (pRec != NULL) 00566 { 00567 ok = pFilter->Write(pRec); 00568 delete pRec; 00569 pRec = NULL; 00570 } 00571 else 00572 ok = FALSE; 00573 } 00574 00575 if (!ok) 00576 pFilter->GotError(_R(IDE_FILE_WRITE_ERROR)); 00577 00578 return(ok); 00579 #else 00580 return FALSE; 00581 #endif 00582 } 00583 00584 00585 00586 00587 00588 00589 00590 00591 00592 00593 00594 00595 00596 00597 00598 00599 /******************************************************************************************** 00600 00601 > StrokeTypeAttrValue::StrokeTypeAttrValue(PathProcessorStroke *pPathProcessor = NULL); 00602 00603 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00604 Created: 7/1/97 00605 00606 Inputs: pPathProcessor - the stroke path-processor which will do the stroking 00607 effect "applied" by this attribute. NULL indicates that this attribute 00608 does no stroking (i.e. that the path should have an old-style "line") 00609 00610 NOTE that this object is NOW OWNED by this StrokeTypeAttrValue, and will be 00611 deleted when the attribute value is deleted. 00612 00613 Purpose: Default Constuctor for StrokeTypeAttrValue 00614 00615 ********************************************************************************************/ 00616 00617 StrokeTypeAttrValue::StrokeTypeAttrValue(PathProcessorStroke *pPathProcessor) 00618 { 00619 // Remember our processor, and let it know that we "own" it 00620 pProcessor = pPathProcessor; 00621 if (pProcessor != NULL) 00622 pProcessor->SetParentAttr(this); 00623 } 00624 00625 00626 00627 /******************************************************************************************** 00628 00629 > StrokeTypeAttrValue::~StrokeTypeAttrValue() 00630 00631 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00632 Created: 7/1/97 00633 00634 Purpose: Destructor 00635 Deletes any attached PathProcessor (see the constructor) 00636 00637 ********************************************************************************************/ 00638 00639 StrokeTypeAttrValue::~StrokeTypeAttrValue() 00640 { 00641 if (pProcessor != NULL) 00642 delete pProcessor; 00643 } 00644 00645 00646 00647 /******************************************************************************************** 00648 00649 > static BOOL StrokeTypeAttrValue::Init(void) 00650 00651 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00652 Created: 7/1/97 00653 00654 Returns: TRUE if it initilised successfully 00655 00656 Purpose: Registers a default attribute of this type with the attribute manager 00657 00658 ********************************************************************************************/ 00659 00660 BOOL StrokeTypeAttrValue::Init(void) 00661 { 00662 // The default attribute is one that has no effect (i.e. produces old-style "lines") 00663 StrokeTypeAttrValue *pAttr = new StrokeTypeAttrValue; 00664 if (pAttr == NULL) 00665 return FALSE; 00666 00667 UINT32 ID = AttributeManager::RegisterDefaultAttribute(CC_RUNTIME_CLASS(StrokeTypeAttrValue), 00668 pAttr); 00669 00670 ERROR2IF(ID == ATTR_BAD_ID, FALSE, "Bad ID when Initialising StrokeTypeAttrValue"); 00671 00672 return(TRUE); 00673 } 00674 00675 00676 00677 /******************************************************************************************** 00678 00679 > virtual void StrokeTypeAttrValue::Render(RenderRegion *pRegion, BOOL Temp) 00680 00681 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00682 Created: 7/1/97 00683 00684 Inputs: pRegion - the render region to render this attribute into. 00685 00686 Purpose: Sets the StrokeTypeAttrValue attribute for the given render region. 00687 00688 Notes: This attribute makes itself current in the render region, and 00689 also (possibly) adds a PathProcessor to handle stroking of 00690 all future rendered paths (until the attr is "restored") 00691 00692 SeeAlso: StrokeTypeAttrValue::Restore 00693 00694 ********************************************************************************************/ 00695 00696 void StrokeTypeAttrValue::Render(RenderRegion *pRegion, BOOL Temp) 00697 { 00698 // Stack the current attribute and set ourselves up as the new one 00699 pRegion->SetStrokeType(this, Temp); 00700 00701 // Find if we have a path processor to do the stroking, and if we do, 00702 // stack a copy of it (a copy must be used to be thread-safe & bgrender-safe) 00703 if (pProcessor != NULL) 00704 { 00705 PathProcessorStroke *pNewProcessor = pProcessor->Clone(); 00706 if (pNewProcessor != NULL) 00707 pRegion->PushPathProcessor(pNewProcessor); 00708 } 00709 } 00710 00711 00712 00713 /******************************************************************************************** 00714 00715 > virtual void StrokeTypeAttrValue::Restore(RenderRegion *pRegion, BOOL Temp) 00716 00717 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00718 Created: 7/1/97 00719 00720 Inputs: pRegion - the render region to restore the attribute into. 00721 Temp - TRUE if this is a temporary attribute, FALSE if it is 00722 permanent (e.g. it's in a document tree). 00723 00724 Purpose: Restores the StrokeTypeAttrValue attribute for the given render region. 00725 00726 Notes: This attribute makes sure it removes any PathProcessor it added 00727 to handle path stroking in StrokeTypeAttrValue::Render 00728 00729 ********************************************************************************************/ 00730 00731 void StrokeTypeAttrValue::Restore(RenderRegion *pRegion, BOOL Temp) 00732 { 00733 pRegion->RestoreStrokeType(this, Temp); 00734 } 00735 00736 00737 00738 /******************************************************************************************** 00739 00740 > void StrokeTypeAttrValue::GoingOutOfScope(RenderRegion *pRegion) 00741 00742 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00743 Created: 9/1/97 00744 00745 Inputs: pRegion - the render region the attribute is in use by 00746 00747 Purpose: A sister function to Render() 00748 00749 This is called by a render region when an attribute goes out of 00750 scope, i.e. when the attribute is no longer in use and is popped 00751 off the stack for the last time. (Do NOT confuse this with being 00752 pushed onto the render stack when overridden by another attr) 00753 00754 It gives the attribute a chance to remove any PathProcessor(s) 00755 it added to the RenderRegion when it was Render()ed. 00756 00757 Notes: This attribute makes sure it removes any PathProcessor it added 00758 to handle path stroking in StrokeTypeAttrValue::Render 00759 00760 SeeAlso: StrokeTypeAttrValue::Render() 00761 00762 ********************************************************************************************/ 00763 00764 void StrokeTypeAttrValue::GoingOutOfScope(RenderRegion *pRegion) 00765 { 00766 if (pProcessor != NULL) 00767 pRegion->PopPathProcessor(); 00768 } 00769 00770 00771 00772 /******************************************************************************************** 00773 00774 > virtual void StrokeTypeAttrValue::SimpleCopy(AttributeValue *pValue) 00775 00776 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00777 Created: 7/1/97 00778 00779 Inputs: pValue - pointer to the AttributeValue to copy 00780 00781 Purpose: See AttributeValue::SimpleCopy 00782 00783 ********************************************************************************************/ 00784 00785 void StrokeTypeAttrValue::SimpleCopy(AttributeValue *pValue) 00786 { 00787 ERROR3IF(!IS_A(pValue, StrokeTypeAttrValue), 00788 "Invalid Attribute value passed to StrokeTypeAttrValue::SimpleCopy"); 00789 00790 // Just uses the assignment operator 00791 *this = *((StrokeTypeAttrValue *) pValue); 00792 } 00793 00794 00795 00796 /******************************************************************************************** 00797 00798 > virtual NodeAttribute *StrokeTypeAttrValue::MakeNode() 00799 00800 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00801 Created: 7/1/97 00802 00803 Returns: Pointer to the new node, or NULL if out of memory. 00804 00805 Purpose: Make a new attribute node for this type of attr value - see base class 00806 00807 SeeAlso: AttributeValue::MakeNode 00808 00809 ********************************************************************************************/ 00810 00811 NodeAttribute *StrokeTypeAttrValue::MakeNode() 00812 { 00813 // Create new attribute node 00814 AttrStrokeType *pAttr = new AttrStrokeType; 00815 if (pAttr == NULL) 00816 return NULL; 00817 00818 // Copy attribute value (if any) into the new node. 00819 if (pAttr->GetAttributeValue() != NULL) 00820 pAttr->GetAttributeValue()->SimpleCopy(this); 00821 00822 return(pAttr); 00823 } 00824 00825 00826 00827 /******************************************************************************************** 00828 00829 > virtual BOOL StrokeTypeAttrValue::IsDifferent(AttributeValue *pAttr) 00830 00831 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00832 Created: 7/1/97 00833 00834 Purpose: Determines if this AttrValue is different from the given one 00835 00836 Errors: ERROR3 if the two attributes are not of the same type 00837 00838 SeeAlso: AttributeValue::IsDifferent 00839 00840 ********************************************************************************************/ 00841 00842 BOOL StrokeTypeAttrValue::IsDifferent(AttributeValue *pAttr) 00843 { 00844 ERROR3IF(!pAttr->IsKindOf(CC_RUNTIME_CLASS(StrokeTypeAttrValue)), 00845 "Different attribute types in StrokeTypeAttrValue::IsDifferent()"); 00846 00847 // Check they are NOT the same using the == operator 00848 return ( !(*((StrokeTypeAttrValue *)pAttr) == *this) ); 00849 } 00850 00851 00852 00853 /******************************************************************************************** 00854 00855 > virtual StrokeTypeAttrValue &StrokeTypeAttrValue::operator=(StrokeTypeAttrValue &Attrib) 00856 00857 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00858 Created: 7/1/97 00859 00860 Inputs: Attrib - the attribute to copy 00861 00862 Purpose: Assignment operator 00863 00864 ********************************************************************************************/ 00865 00866 StrokeTypeAttrValue &StrokeTypeAttrValue::operator=(StrokeTypeAttrValue &Attrib) 00867 { 00868 // Get rid of our old processor (if any) 00869 if (pProcessor != NULL) 00870 delete pProcessor; 00871 pProcessor = NULL; 00872 00873 // Copy the other attr's processor. If this fails, we'll get back a NULL pointer, 00874 // and will simply "convert" into a simple no-stroke attribute. 00875 if (Attrib.pProcessor != NULL) 00876 { 00877 pProcessor = Attrib.pProcessor->Clone(); 00878 if (pProcessor != NULL) 00879 pProcessor->SetParentAttr(this); 00880 } 00881 00882 return(*this); 00883 } 00884 00885 00886 00887 /******************************************************************************************** 00888 00889 > virtual INT32 StrokeTypeAttrValue::operator==(const StrokeTypeAttrValue &Attrib) 00890 00891 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00892 Created: 7/1/97 00893 00894 Inputs: Attrib - the attribute to compare this attribute with 00895 00896 Returns: TRUE if the attributes are considered equal 00897 00898 Purpose: Comparison operator 00899 00900 ********************************************************************************************/ 00901 00902 INT32 StrokeTypeAttrValue::operator==(const StrokeTypeAttrValue &Attrib) 00903 { 00904 ERROR3IF(!Attrib.IsKindOf(CC_RUNTIME_CLASS(StrokeTypeAttrValue)), 00905 "Other attribute value isn't an StrokeTypeAttrValue"); 00906 00907 StrokeTypeAttrValue *Other = (StrokeTypeAttrValue *) &Attrib; 00908 00909 // Equal if they both have same processor (only applies if they are both NULL) 00910 if (pProcessor == Other->pProcessor) 00911 return(TRUE); 00912 00913 // Otherwise, if one of them is NULL, they can't be the same 00914 if (pProcessor == NULL || Other->pProcessor == NULL) 00915 return(FALSE); 00916 00917 // Finally, ask the processors if they are of the same type 00918 return(!pProcessor->IsDifferent(Other->pProcessor)); 00919 } 00920 00921 00922 00923 /******************************************************************************************** 00924 00925 > void StrokeTypeAttrValue::SetPathProcessor(PathProcessorStroke *pNewProcessor) 00926 00927 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 00928 Created: 7/1/97 00929 00930 Inputs: pNewProcessor - The new PathProcessorStroke to be used by this attr. 00931 May be NULL, in which case it sets "old style lines" stroking mode. 00932 00933 Purpose: To set the path processor used by this object. The processor is now 00934 "owned" by this attribute, and will be auto-deleted upon destruction 00935 00936 ********************************************************************************************/ 00937 00938 void StrokeTypeAttrValue::SetPathProcessor(PathProcessorStroke *pNewProcessor) 00939 { 00940 if (pProcessor != NULL) 00941 delete pProcessor; 00942 00943 pProcessor = pNewProcessor; 00944 if (pProcessor != NULL) 00945 pProcessor->SetParentAttr(this); 00946 } 00947 00948 00949 /******************************************************************************************** 00950 00951 > BOOL StrokeTypeAttrValue::DoBecomeA(BecomeA* pBecomeA, Node* pParent) 00952 00953 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00954 Created: 17/3/2000 00955 Inputs: pBecomeA - the object that tells us what to become, and recieves the results 00956 pParent - the node that this attribute is applied to 00957 Outputs: 00958 Returns: TRUE if everything went ok, 00959 Purpose: To convert our stroke into something more palatable. pParent 00960 should always be a nodepath 00961 00962 Notes: Due to problems with bevelling and contouring this function does not get 00963 called in the normal DoBecomeA procedure unless you specifically locate this 00964 attribute and call this function directly. 00965 ********************************************************************************************/ 00966 00967 BOOL StrokeTypeAttrValue::DoBecomeA(BecomeA* pBecomeA, Node* pParent) 00968 { 00969 ERROR2IF(pBecomeA == NULL, FALSE, "BecomeA pointer is NULL in VariableWidthAttrValue::DoBecomeA"); 00970 ERROR2IF(pParent == NULL, FALSE, "Parent node is NULL in VariableWidthAttrValue::DoBecomeA"); 00971 00972 if (pProcessor == NULL) 00973 return FALSE; 00974 00975 if (!pBecomeA->BAPath()) 00976 return FALSE; 00977 00978 BOOL Success = FALSE; 00979 // UINT32 Dummy = 0; 00980 // if we have a nodepath then we can simply use its member path, otherwise we 00981 // have to ask it to become a nodepath 00982 if (pParent->IsNodePath()) 00983 { 00984 // we have a special calculation for nodepaths, because we can use their path 00985 Success = pProcessor->DoBecomeA(pBecomeA, &((NodePath*)pParent)->InkPath, pParent); 00986 } 00987 else if (pParent->CanBecomeA(pBecomeA)) 00988 { 00989 // we must be applied to some arbitrary shape. The thing is that we need to have 00990 // a path to pass to the PPB, so want to get a passback of all the paths in 00991 // the node 00992 00993 // we need to allocate a path 00994 Path* pPath = new Path; 00995 if (pPath != NULL && pPath->Initialise()) 00996 { 00997 PathBecomeA BecomeAPath(BECOMEA_PASSBACK, CC_RUNTIME_CLASS(NodePath), NULL, FALSE, pPath); 00998 if (pParent->DoBecomeA(&BecomeAPath)) 00999 { 01000 Success = pProcessor->DoBecomeA(pBecomeA, pPath, pParent); 01001 } 01002 delete pPath; 01003 } 01004 } 01005 return Success; 01006 } 01007 01008 01009 01010 01011 01012 01013 01014 01015 01016 01017 /******************************************************************************************** 01018 01019 > AttrVariableWidth::AttrVariableWidth() 01020 01021 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01022 Created: 7/1/97 01023 01024 Purpose: Default constructor for AttrVariableWidth 01025 01026 ********************************************************************************************/ 01027 01028 AttrVariableWidth::AttrVariableWidth() 01029 { 01030 } 01031 01032 01033 01034 /******************************************************************************************** 01035 01036 > AttrVariableWidth::AttrVariableWidth(Node *ContextNode, 01037 AttachNodeDirection Direction, 01038 BOOL Locked, 01039 BOOL Mangled, 01040 BOOL Marked, 01041 BOOL Selected) 01042 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01043 Created: 7/1/97 01044 01045 Purpose: Constructs an AttrVariableWidth Attribute 01046 01047 ********************************************************************************************/ 01048 01049 AttrVariableWidth::AttrVariableWidth(Node *ContextNode, 01050 AttachNodeDirection Direction, 01051 BOOL Locked, 01052 BOOL Mangled, 01053 BOOL Marked, 01054 BOOL Selected) 01055 : NodeAttribute(ContextNode, Direction, Locked, Mangled, Marked, Selected) 01056 { 01057 } 01058 01059 01060 01061 /******************************************************************************************** 01062 01063 > virtual void AttrVariableWidth::Render(RenderRegion *pRender) 01064 01065 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01066 Created: 7/1/97 01067 01068 Purpose: Renders this attribute (by simply calling the Render function of 01069 its contained AttributeValue) 01070 01071 ********************************************************************************************/ 01072 01073 void AttrVariableWidth::Render(RenderRegion *pRender) 01074 { 01075 GetAttributeValue()->Render(pRender); 01076 } 01077 01078 01079 01080 /*********************************************************************************************** 01081 01082 > virtual void AttrVariableWidth::CopyNodeContents(AttrVariableWidth *NodeCopy) 01083 01084 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01085 Created: 7/1/97 01086 01087 Outputs: NodeCopy - returned containing a copy of this node 01088 01089 Purpose: Copies the node's contents to the node pointed to by NodeCopy 01090 01091 ***********************************************************************************************/ 01092 01093 void AttrVariableWidth::CopyNodeContents(AttrVariableWidth *NodeCopy) 01094 { 01095 // Let the base class do its bit 01096 NodeAttribute::CopyNodeContents(NodeCopy); 01097 01098 // And then copy our Value 01099 *(NodeCopy->GetAttributeValue()) = *(GetAttributeValue()); 01100 } 01101 01102 01103 01104 /*********************************************************************************************** 01105 > void AttrVariableWidth::PolyCopyNodeContents(NodeRenderable* pNodeCopy) 01106 01107 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 01108 Created: 18/12/2003 01109 Outputs: - 01110 Purpose: Polymorphically copies the contents of this node to another 01111 Errors: An assertion failure will occur if NodeCopy is NULL 01112 Scope: protected 01113 01114 ***********************************************************************************************/ 01115 01116 void AttrVariableWidth::PolyCopyNodeContents(NodeRenderable* pNodeCopy) 01117 { 01118 ENSURE(pNodeCopy, "Trying to copy a node's contents into a NULL node"); 01119 ENSURE(IS_A(pNodeCopy, AttrVariableWidth), "PolyCopyNodeContents given wrong dest node type"); 01120 01121 if (IS_A(pNodeCopy, AttrVariableWidth)) 01122 CopyNodeContents((AttrVariableWidth*)pNodeCopy); 01123 } 01124 01125 01126 01127 /*********************************************************************************************** 01128 01129 > virtual INT32 AttrVariableWidth::operator==(const NodeAttribute &NodeAttrib); 01130 01131 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01132 Created: 8/7/97 01133 01134 Inputs: NodeAttrib - The node to compare this node to 01135 Returns: TRUE if the nodes are considered equal 01136 01137 Purpose: Comparison operator - determines if the AttributeValues of both objects are == 01138 01139 ***********************************************************************************************/ 01140 01141 INT32 AttrVariableWidth::operator==(const NodeAttribute &NodeAttrib) 01142 { 01143 // First check they are of the same type 01144 if (((NodeAttribute*)&NodeAttrib)->GetAttributeType() != GetAttributeType()) 01145 return FALSE; 01146 01147 // Make a more sensible pointer 01148 AttrVariableWidth *Attr = (AttrVariableWidth *) &NodeAttrib; 01149 01150 // Now let the AttributeValues compare themselves 01151 return( *((VariableWidthAttrValue *) Attr->GetAttributeValue()) == 01152 *((VariableWidthAttrValue *) GetAttributeValue()) ); 01153 } 01154 01155 01156 01157 /******************************************************************************************** 01158 01159 > virtual Node *AttrVariableWidth::SimpleCopy() 01160 01161 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01162 Created: 8/1/97 01163 01164 Returns: A copy of the node, or NULL if memory runs out 01165 01166 Purpose: This method returns a shallow copy of the node with all Node pointers NULL. 01167 The function is virtual, and must be defined for all derived classes. 01168 01169 ********************************************************************************************/ 01170 01171 Node *AttrVariableWidth::SimpleCopy() 01172 { 01173 AttrVariableWidth* NodeCopy = new AttrVariableWidth; 01174 if (NodeCopy == NULL) 01175 return(NULL); 01176 01177 // Call the base class 01178 NodeAttribute::CopyNodeContents(NodeCopy); 01179 01180 // And call our AttributeValue to copy itself too 01181 NodeCopy->GetAttributeValue()->SimpleCopy(GetAttributeValue()); 01182 01183 return(NodeCopy); 01184 } 01185 01186 01187 01188 /******************************************************************************************** 01189 01190 > virtual UINT32 AttrVariableWidth::GetAttrNameID(void) 01191 01192 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01193 Created: 8/1/97 01194 01195 Returns: Attribute description string-resource ID 01196 01197 Purpose: Retrieves a string resource ID describing this attribute 01198 01199 ********************************************************************************************/ 01200 01201 UINT32 AttrVariableWidth::GetAttrNameID(void) 01202 { 01203 return(_R(IDS_ATTRVARWIDTH)); 01204 } 01205 01206 01207 01208 /******************************************************************************************** 01209 01210 > virtual void AttrVariableWidth::GetDebugDetails(StringBase *Str) 01211 01212 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01213 Created: 8/1/97 01214 01215 Outputs: On return, Str is filled in with details on this node 01216 01217 Purpose: Produces debug details about this node 01218 01219 ********************************************************************************************/ 01220 01221 void AttrVariableWidth::GetDebugDetails(StringBase *Str) 01222 { 01223 #ifdef _DEBUG 01224 NodeAttribute::GetDebugDetails(Str); 01225 01226 String_256 TempStr; 01227 TempStr._MakeMsg( _T("\r\nVariable width of type:\r\n") ); 01228 *Str += TempStr; 01229 01230 if (Value.GetWidthFunction() != NULL) 01231 { 01232 TempStr._MakeMsg( _T(" #1%s\r\n"), 01233 Value.GetWidthFunction()->GetRuntimeClass()->GetClassName() ); 01234 } 01235 else 01236 TempStr._MakeMsg( _T(" old-style constant width\r\n") ); 01237 01238 *Str += TempStr; 01239 #endif 01240 } 01241 01242 01243 01244 /******************************************************************************************** 01245 01246 > virtual UINT32 AttrVariableWidth::GetNodeSize() const 01247 01248 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01249 Created: 8/1/97 01250 01251 Returns: The size of this node, in bytes 01252 01253 Purpose: For finding the size of the node, in bytes 01254 01255 ********************************************************************************************/ 01256 01257 UINT32 AttrVariableWidth::GetNodeSize() const 01258 { 01259 return(sizeof(AttrVariableWidth)); 01260 } 01261 01262 01263 01264 /******************************************************************************************** 01265 01266 > BOOL AttrVariableWidth::HasActiveValueFunction() const 01267 01268 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01269 Created: 27/11/2000 01270 01271 Returns: True if our attr value has a value function, false if not 01272 01273 Purpose: To find out if this attribute is actually going to do anything or not 01274 01275 ********************************************************************************************/ 01276 01277 BOOL AttrVariableWidth::HasActiveValueFunction() 01278 { 01279 return (Value.GetWidthFunction() != NULL); 01280 } 01281 01282 /******************************************************************************************** 01283 01284 > virtual BOOL AttrVariableWidth::WritePreChildrenWeb(BaseCamelotFilter *pFilter) 01285 > virtual BOOL AttrVariableWidth::WritePreChildrenNative(BaseCamelotFilter *pFilter) 01286 01287 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01288 Created: 8/1/97 01289 01290 Inputs: pFilter - filter to write to 01291 01292 Returns: TRUE if the Node has written out a record to the filter 01293 01294 Purpose: Writes out a record that represents the node, to either Native or Web 01295 file format. 01296 01297 This function is called before any of the AttrVariableWidth's children 01298 are written to the filter. 01299 01300 If the AttrVariableWidth writes out a record successfully to the file, 01301 it will return TRUE. 01302 01303 If the AttrVariableWidth chooses not to write itself to the filter 01304 (e.g. because it is not appropriate for this filter), then this 01305 function will return FALSE. 01306 01307 Notes: Simple 01308 01309 SeeAlso: Node::WritePreChildrenNative; Node::WritePreChildrenWeb; 01310 StrokeAttrRecordHandler::HandleRecord 01311 01312 ********************************************************************************************/ 01313 01314 BOOL AttrVariableWidth::WritePreChildrenWeb(BaseCamelotFilter *pFilter) 01315 { 01316 return(WritePreChildrenNative(pFilter)); 01317 } 01318 01319 BOOL AttrVariableWidth::WritePreChildrenNative(BaseCamelotFilter *pFilter) 01320 { 01321 #ifdef DO_EXPORT 01322 ERROR3IF(pFilter == NULL, "Illegal NULL param"); 01323 01324 BOOL ok = TRUE; 01325 VariableWidthID PredefinedFunctionID = Value.GetWidthFunctionID(); 01326 01327 if (PredefinedFunctionID == VarWidth_NotPredefined) 01328 { 01329 ValueFunction *pFunction = Value.GetWidthFunction(); 01330 if (pFunction != NULL) 01331 { 01332 CamelotFileRecord *pRec = pFunction->WriteFileRecord(TAG_VARIABLEWIDTHTABLE, 0, pFilter); 01333 if (pRec != NULL) 01334 { 01335 pFilter->Write(pRec); 01336 delete pRec; 01337 pRec = NULL; 01338 } 01339 else 01340 ok = FALSE; 01341 } 01342 else 01343 { 01344 // The default attribute (for simple old-style lines) has no ValueFunction 01345 CamelotFileRecord Rec(pFilter, TAG_VARIABLEWIDTHFUNC, TAG_VARIABLEWIDTHFUNC_SIZE); 01346 if (ok) ok = Rec.Init(); 01347 if (ok) ok = Rec.WriteUINT32((UINT32) 0); 01348 if (ok) ok = pFilter->Write(&Rec); 01349 } 01350 } 01351 else 01352 { 01353 CamelotFileRecord Rec(pFilter, TAG_VARIABLEWIDTHFUNC, TAG_VARIABLEWIDTHFUNC_SIZE); 01354 01355 if (ok) ok = Rec.Init(); 01356 if (ok) ok = Rec.WriteUINT32((UINT32) PredefinedFunctionID); 01357 if (ok) ok = pFilter->Write(&Rec); 01358 } 01359 01360 if (!ok) 01361 pFilter->GotError(_R(IDE_FILE_WRITE_ERROR)); 01362 01363 return(ok); 01364 #else 01365 return FALSE; 01366 #endif 01367 } 01368 01369 01370 01371 01372 01373 01374 01375 01376 01377 01378 01379 01380 01381 01382 01383 /******************************************************************************************** 01384 01385 > VariableWidthAttrValue::VariableWidthAttrValue(ValueFunction *pValueFunction = NULL) 01386 01387 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01388 Created: 7/1/97 01389 01390 Inputs: pValueFunction - NULL (for simple constant-width "line") or a ValueFunction 01391 describing the variable width of paths affected by this attr. 01392 01393 NOTE that this object now BELONGS to the new attr, and 01394 will be deleted automatically when this object is destructed 01395 01396 Purpose: Constuctor for VariableWidthAttrValue 01397 01398 ********************************************************************************************/ 01399 01400 VariableWidthAttrValue::VariableWidthAttrValue(ValueFunction *pValueFunction) 01401 { 01402 WidthFunction = pValueFunction; 01403 PredefinedFunctionID = VarWidth_NotPredefined; 01404 } 01405 01406 01407 01408 /******************************************************************************************** 01409 01410 > VariableWidthAttrValue::~VariableWidthAttrValue() 01411 01412 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01413 Created: 7/1/97 01414 01415 Purpose: Destructor for VariableWidthAttrValue 01416 01417 ********************************************************************************************/ 01418 01419 VariableWidthAttrValue::~VariableWidthAttrValue() 01420 { 01421 if (WidthFunction != NULL) 01422 delete WidthFunction; 01423 } 01424 01425 01426 01427 /******************************************************************************************** 01428 01429 > static BOOL VariableWidthAttrValue::Init(void) 01430 01431 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01432 Created: 7/1/97 01433 01434 Returns: TRUE if it initilised successfully 01435 01436 Purpose: Registers a default attribute of this type with the attribute manager 01437 01438 ********************************************************************************************/ 01439 01440 BOOL VariableWidthAttrValue::Init(void) 01441 { 01442 // The default attribute is one that has no effect (i.e. produces constant-width "lines") 01443 VariableWidthAttrValue *pAttr = new VariableWidthAttrValue; 01444 if (pAttr == NULL) 01445 return FALSE; 01446 01447 UINT32 ID = AttributeManager::RegisterDefaultAttribute(CC_RUNTIME_CLASS(VariableWidthAttrValue), 01448 pAttr); 01449 01450 ERROR2IF(ID == ATTR_BAD_ID, FALSE, "Bad ID when Initialising VariableWidthAttrValue"); 01451 01452 return(TRUE); 01453 } 01454 01455 01456 01457 /******************************************************************************************** 01458 01459 > virtual void VariableWidthAttrValue::Render(RenderRegion *pRegion, BOOL Temp) 01460 01461 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01462 Created: 7/1/97 01463 01464 Inputs: pRegion - the render region to render this attribute into. 01465 01466 Purpose: Sets the VariableWidthAttrValue attribute for the given render region. 01467 01468 Notes: This attribute is so simple that its state can be read directly off 01469 the render region's stack. Thus, there is minimal special render region 01470 support for this attribute - we just stack and unstack it directly here. 01471 01472 ********************************************************************************************/ 01473 01474 void VariableWidthAttrValue::Render(RenderRegion *pRegion, BOOL Temp) 01475 { 01476 pRegion->SetVariableWidth(this, Temp); 01477 } 01478 01479 01480 01481 /******************************************************************************************** 01482 01483 > virtual void VariableWidthAttrValue::Restore(RenderRegion *pRegion, BOOL Temp) 01484 01485 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01486 Created: 7/1/97 01487 01488 Inputs: pRegion - the render region to restore the attribute into. 01489 Temp - TRUE if this is a temporary attribute, FALSE if it is 01490 permanent (e.g. it's in a document tree). 01491 01492 Purpose: Restores the VariableWidthAttrValue attribute for the given render region. 01493 01494 Notes: This attribute is so simple that its state can be read directly off 01495 the render region's stack. Thus, there is minimal special render region 01496 support for this attribute - we just stack and unstack it directly here. 01497 01498 ********************************************************************************************/ 01499 01500 void VariableWidthAttrValue::Restore(RenderRegion *pRegion, BOOL Temp) 01501 { 01502 pRegion->RestoreVariableWidth(this, Temp); 01503 } 01504 01505 01506 01507 /******************************************************************************************** 01508 01509 > virtual void VariableWidthAttrValue::SimpleCopy(AttributeValue *pValue) 01510 01511 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01512 Created: 7/1/97 01513 01514 Inputs: pValue - pointer to the AttributeValue to copy 01515 01516 Purpose: See AttributeValue::SimpleCopy 01517 01518 ********************************************************************************************/ 01519 01520 void VariableWidthAttrValue::SimpleCopy(AttributeValue *pValue) 01521 { 01522 ERROR3IF(!IS_A(pValue, VariableWidthAttrValue), 01523 "Invalid Attribute value passed to VariableWidthAttrValue::SimpleCopy"); 01524 01525 // Just uses the assignment operator 01526 *this = *((VariableWidthAttrValue *) pValue); 01527 } 01528 01529 01530 01531 /******************************************************************************************** 01532 01533 > virtual NodeAttribute *VariableWidthAttrValue::MakeNode() 01534 01535 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01536 Created: 7/1/97 01537 01538 Returns: Pointer to the new node, or NULL if out of memory. 01539 01540 Purpose: Make a new attribute node for this type of attr value - see base class 01541 01542 SeeAlso: AttributeValue::MakeNode 01543 01544 ********************************************************************************************/ 01545 01546 NodeAttribute *VariableWidthAttrValue::MakeNode() 01547 { 01548 // Create new attribute node 01549 AttrVariableWidth *pAttr = new AttrVariableWidth(); 01550 if (pAttr == NULL) 01551 return NULL; 01552 01553 // Copy attribute value (if any) into the new node. 01554 if (pAttr->GetAttributeValue() != NULL) 01555 pAttr->GetAttributeValue()->SimpleCopy(this); 01556 01557 return(pAttr); 01558 } 01559 01560 01561 01562 /******************************************************************************************** 01563 01564 > virtual BOOL VariableWidthAttrValue::IsDifferent(AttributeValue *pAttr) 01565 01566 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01567 Created: 7/1/97 01568 01569 Purpose: Determines if this AttrValue is different from the given one 01570 01571 Errors: ERROR3 if the two attributes are not of the same type 01572 01573 SeeAlso: AttributeValue::IsDifferent 01574 01575 ********************************************************************************************/ 01576 01577 BOOL VariableWidthAttrValue::IsDifferent(AttributeValue *pAttr) 01578 { 01579 ERROR3IF(!pAttr->IsKindOf(CC_RUNTIME_CLASS(VariableWidthAttrValue)), 01580 "Different attribute types in VariableWidthAttrValue::IsDifferent()"); 01581 01582 // Check they are NOT the same using the == operator 01583 return ( !(*((VariableWidthAttrValue *)pAttr) == *this) ); 01584 } 01585 01586 01587 01588 /******************************************************************************************** 01589 01590 > virtual VariableWidthAttrValue &VariableWidthAttrValue::operator=(VariableWidthAttrValue &Attrib) 01591 01592 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01593 Created: 7/1/97 01594 01595 Inputs: Attrib - the attribute to copy 01596 01597 Purpose: Assignment operator 01598 01599 ********************************************************************************************/ 01600 01601 VariableWidthAttrValue &VariableWidthAttrValue::operator=(VariableWidthAttrValue &Attrib) 01602 { 01603 // Delete our existing WidthFunction (if any) 01604 if (WidthFunction != NULL) 01605 delete WidthFunction; 01606 WidthFunction = NULL; 01607 01608 // Try to clone the other attribute's width function. If this fails, we'll just 01609 // end up as a constant-width line (NULL ValueFunction pointer) 01610 if (Attrib.GetWidthFunction() != NULL) 01611 WidthFunction = Attrib.GetWidthFunction()->Clone(); 01612 01613 // And copy its ID member across too 01614 PredefinedFunctionID = Attrib.PredefinedFunctionID; 01615 01616 return(*this); 01617 } 01618 01619 01620 01621 /******************************************************************************************** 01622 01623 > virtual INT32 VariableWidthAttrValue::operator==(const VariableWidthAttrValue &Attrib) 01624 01625 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01626 Created: 7/1/97 01627 01628 Inputs: Attrib - the attribute to compare this attribute with 01629 01630 Returns: TRUE if the attributes are considered equal 01631 01632 Purpose: Comparison operator 01633 01634 ********************************************************************************************/ 01635 01636 INT32 VariableWidthAttrValue::operator==(const VariableWidthAttrValue &Attrib) 01637 { 01638 ERROR3IF(!Attrib.IsKindOf(CC_RUNTIME_CLASS(VariableWidthAttrValue)), 01639 "Other attribute value isn't an VariableWidthAttrValue"); 01640 01641 // VariableWidthAttrValue *Other = (VariableWidthAttrValue *) &Attrib; 01642 01643 // If both width functions are NULL, we are equal 01644 if (WidthFunction == NULL && Attrib.WidthFunction == NULL) 01645 return(TRUE); 01646 01647 // If only one function is NULL, we ca't be considered equal 01648 if (WidthFunction == NULL || Attrib.WidthFunction == NULL) 01649 return(FALSE); 01650 01651 // Finally, if both have a valid width function, ask them if they're equal 01652 return(!WidthFunction->IsDifferent(Attrib.WidthFunction)); 01653 } 01654 01655 01656 01657 /******************************************************************************************** 01658 01659 > void VariableWidthAttrValue::SetWidthFunction(ValueFunction *pNewFunction) 01660 01661 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01662 Created: 7/1/97 01663 01664 Inputs: pNewFunction - The new value function to use for variable-width strokes 01665 affected by this attribute. May be NULL, in which case all strokes will 01666 be simple constant-width strokes. 01667 01668 NOTE that this object now belongs to this Attr, and will be automatically 01669 deleted upon destruction of the attr. 01670 01671 Purpose: To set the width function used in stroking 01672 01673 Notes: See the alternative form of this method - it uses predefined function 01674 "shapes", which save in a more compact format. 01675 01676 ********************************************************************************************/ 01677 01678 void VariableWidthAttrValue::SetWidthFunction(ValueFunction *pNewFunction) 01679 { 01680 if (WidthFunction != NULL) 01681 delete WidthFunction; 01682 01683 WidthFunction = pNewFunction; 01684 PredefinedFunctionID = VarWidth_NotPredefined; 01685 } 01686 01687 01688 01689 /******************************************************************************************** 01690 01691 > void VariableWidthAttrValue::SetWidthFunction(VariableWidthID PredefinedFuncID) 01692 01693 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01694 Created: 7/1/97 01695 01696 Inputs: PredefinedFuncID - The ID of which predefined width function type you 01697 wish to use. Predefined types are used to save space in the file format 01698 when exporting simple variable width attributes. 01699 01700 Purpose: To set the width function used in stroking 01701 01702 ********************************************************************************************/ 01703 01704 void VariableWidthAttrValue::SetWidthFunction(VariableWidthID PredefinedFuncID) 01705 { 01706 ERROR3IF(PredefinedFuncID == VarWidth_NotPredefined, "You what?!"); 01707 01708 // get rid of any old width function 01709 if (WidthFunction != NULL) 01710 { 01711 delete WidthFunction; 01712 WidthFunction = NULL; 01713 } 01714 01715 // Remember the new predefined-width-function identifier, so that we 01716 // know that our width is a spaecial predefined form which can be saved 01717 // in a much simpler & smaller format 01718 PredefinedFunctionID = PredefinedFuncID; 01719 01720 switch(PredefinedFunctionID) 01721 { 01722 case VarWidth_Constant: 01723 WidthFunction = new ValueFunctionConstant(1.0); 01724 break; 01725 01726 case VarWidth_LinRamp: 01727 WidthFunction = new ValueFunctionRampLinear(1.0, 0.0); 01728 break; 01729 01730 case VarWidth_SRamp: 01731 WidthFunction = new ValueFunctionRampS(1.0, 0.0); 01732 break; 01733 01734 default: 01735 ERROR3("Unsupported predefined width function"); 01736 break; 01737 } 01738 } 01739 01740 01741 01742 01743 01744 01745 01746 01747 01748 /******************************************************************************************** 01749 01750 > virtual UINT32 *StrokeAttrRecordHandler::GetTagList() 01751 01752 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01753 Created: 7/1/97 01754 01755 Returns: A list of tag values, terminated by CXFRH_TAG_LIST_END 01756 01757 Purpose: Provides the record handler system with a list of records handled by this 01758 handler - all StrokeType attributes: 01759 Stroke (by type) 01760 Stroke (by vector subtree definition) 01761 Stroke (airbrush) 01762 Variable width function (predefined) 01763 Variable width function (recorded) 01764 01765 SeeAlso: StrokeTypeAttrRecordHandler::HandleRecord 01766 01767 ********************************************************************************************/ 01768 01769 UINT32 *StrokeAttrRecordHandler::GetTagList() 01770 { 01771 static UINT32 TagList[] = 01772 { 01773 TAG_STROKEDEFINITION, 01774 TAG_STROKETYPE, 01775 TAG_STROKEAIRBRUSH, 01776 01777 TAG_VARIABLEWIDTHFUNC, 01778 TAG_VARIABLEWIDTHTABLE, 01779 01780 CXFRH_TAG_LIST_END 01781 }; 01782 01783 return(TagList); 01784 } 01785 01786 01787 01788 /******************************************************************************************** 01789 01790 > virtual BOOL StrokeAttrRecordHandler::HandleRecord(CXaraFileRecord *pCXaraFileRecord) 01791 01792 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01793 Created: 7/1/97 01794 01795 Inputs: pCXaraFileRecord - The record to handle - may not be NULL 01796 Returns: TRUE if handled successfuly 01797 01798 Purpose: Handles loading of the given StrokeType attribute record 01799 01800 SeeAlso: AttrStrokeType::WritePreChildrenNative; 01801 AttrOverprintFill::WritePreChildrenNative; 01802 AttrPrintOnAllPlates::WritePreChildrenNative 01803 01804 ********************************************************************************************/ 01805 01806 BOOL StrokeAttrRecordHandler::HandleRecord(CXaraFileRecord *pCXaraFileRecord) 01807 { 01808 ERROR3IF(pCXaraFileRecord == NULL, "pCXaraFileRecord is NULL"); 01809 01810 NodeAttribute *pNewNode = NULL; 01811 01812 switch (pCXaraFileRecord->GetTag()) 01813 { 01814 case TAG_STROKEDEFINITION: 01815 return(StrokeComponent::StartImportStroke(this, pCXaraFileRecord)); 01816 01817 01818 case TAG_STROKETYPE: 01819 { 01820 UINT32 Handle = 0x01000000; 01821 pCXaraFileRecord->ReadUINT32(&Handle); 01822 01823 pNewNode = new AttrStrokeType; 01824 if (pNewNode != NULL) 01825 { 01826 PathProcessorStroke *pProcessor = NULL; 01827 01828 switch ((Handle >> 24) & 0xff) 01829 { 01830 case 0: 01831 // Complex vector stroke 01832 { 01833 StrokeHandle NewHandle = StrokeComponent::FindImportedStroke(Handle & 0x00ffffff); 01834 if (NewHandle != StrokeHandle_NoStroke) 01835 pProcessor = new PathProcessorStrokeVector; 01836 01837 if (pProcessor != NULL) 01838 ((PathProcessorStrokeVector *)pProcessor)->SetStrokeDefinition(NewHandle); 01839 } 01840 break; 01841 01842 case 1: 01843 // Simple old-style constant width line. Use pProcessor == NULL 01844 break; 01845 01846 case 2: 01847 // Simple variable-width stroke 01848 pProcessor = new PathProcessorStroke; 01849 break; 01850 01851 default: 01852 ERROR3("Unknown/Unsupported stroke type"); 01853 break; 01854 } 01855 01856 if (pProcessor != NULL) 01857 ((StrokeTypeAttrValue *)pNewNode->GetAttributeValue())->SetPathProcessor(pProcessor); 01858 } 01859 } 01860 break; 01861 01862 01863 case TAG_STROKEAIRBRUSH: 01864 { 01865 // Airbrushes currently only hold an intensity-function, so we simply read that 01866 // function and build an airbrush-stroke attribute around it. 01867 ValueFunction *pValFunc = ValueFunction::ReadFileRecord(pCXaraFileRecord); 01868 if (pValFunc != NULL) 01869 { 01870 pNewNode = new AttrStrokeType; 01871 if (pNewNode != NULL) 01872 { 01873 PathProcessorStrokeAirbrush *pProcessor = new PathProcessorStrokeAirbrush; 01874 if (pProcessor != NULL) 01875 { 01876 pProcessor->SetIntensityFunction(pValFunc); 01877 ((StrokeTypeAttrValue *)pNewNode->GetAttributeValue())->SetPathProcessor(pProcessor); 01878 } 01879 else 01880 { 01881 delete pNewNode; 01882 pNewNode = NULL; 01883 } 01884 } 01885 } 01886 01887 if (pNewNode == NULL) // We failed, so clean up 01888 delete pValFunc; 01889 } 01890 break; 01891 01892 01893 case TAG_VARIABLEWIDTHFUNC: 01894 // Create a new variable-width attribute 01895 pNewNode = new AttrVariableWidth; 01896 if (pNewNode != NULL) 01897 { 01898 // and fill in the value with the appropriate function definition 01899 VariableWidthID Function = VarWidth_NotPredefined; 01900 if (pCXaraFileRecord->ReadUINT32((UINT32 *)&Function)) 01901 { 01902 if ((UINT32)Function != 0) 01903 ((VariableWidthAttrValue *)pNewNode->GetAttributeValue())->SetWidthFunction(Function); 01904 } 01905 } 01906 break; 01907 01908 01909 case TAG_VARIABLEWIDTHTABLE: 01910 { 01911 ValueFunction *pValFunc = ValueFunction::ReadFileRecord(pCXaraFileRecord); 01912 if (pValFunc != NULL) 01913 { 01914 pNewNode = new AttrVariableWidth; 01915 if (pNewNode != NULL) 01916 ((VariableWidthAttrValue *)pNewNode->GetAttributeValue())->SetWidthFunction(pValFunc); 01917 else 01918 delete pValFunc; 01919 } 01920 } 01921 break; 01922 01923 default: 01924 ERROR3_PF(("I don't handle records with the tag (%d)\n", pCXaraFileRecord->GetTag())); 01925 break; 01926 } 01927 01928 ERROR3IF(pNewNode == NULL, "Failed to load stroke information"); 01929 01930 // Get the base class to insert the new node for us 01931 if (pNewNode != NULL) 01932 InsertNode(pNewNode); 01933 return(TRUE); 01934 } 01935 01936 01937 01938 /******************************************************************************************** 01939 01940 > virtual BOOL StrokeAttrRecordHandler::BeginSubtree(UINT32 Tag) 01941 01942 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01943 Created: 4/3/97 01944 01945 Inputs: Tag = tag value of the tag this handler last handled 01946 Returns: TRUE if this func wants exclusive handling of the tag 01947 FALSE otherwise 01948 Purpose: Informs the record handler that a subtree is following a tag of type 'Tag' 01949 01950 If you override this func and you do not wish other parts of the system to be informed of the 01951 subtree start, you should return TRUE 01952 01953 ********************************************************************************************/ 01954 01955 BOOL StrokeAttrRecordHandler::BeginSubtree(UINT32 Tag) 01956 { 01957 // We only want to know about following subtrees when doing stroke definition records. 01958 // If we are doing one, then we grab the subtree so nobody else can faff about with it 01959 if (Tag != TAG_STROKEDEFINITION) 01960 return(FALSE); 01961 01962 return(TRUE); 01963 } 01964 01965 01966 01967 /******************************************************************************************** 01968 01969 > virtual BOOL StrokeAttrRecordHandler::EndSubtree(UINT32 Tag) 01970 01971 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 01972 Created: 4/3/97 01973 01974 Inputs: Tag = tag value of the tag this handler last handled 01975 Returns: TRUE if this func wants exclusive handling of the tag 01976 FALSE otherwise 01977 01978 Purpose: Informs the record handler that a subtree that followed a tag of type 'Tag' has ended 01979 01980 If you override this func and you do not wish other parts of the system to be 01981 informed of the subtree end, you should return TRUE 01982 01983 ********************************************************************************************/ 01984 01985 BOOL StrokeAttrRecordHandler::EndSubtree(UINT32 Tag) 01986 { 01987 // We only want to know about following subtrees when doing custom print mark records. 01988 // If we are doing one, then we grab the subtree so nobody else can faff about with it 01989 if (Tag != TAG_STROKEDEFINITION) 01990 return(FALSE); 01991 01992 #if !defined(EXCLUDE_FROM_RALPH) 01993 // OK, it is the end of a stroke definition record, so complete the import 01994 StrokeComponent::EndImportStroke(this); 01995 #endif 01996 01997 return(TRUE); 01998 } 01999 02000 02001 02002 /******************************************************************************************** 02003 02004 > virtual void StrokeAttrRecordHandler::GetRecordDescriptionText(CXaraFileRecord* pRecord,StringBase* pStr) 02005 02006 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 02007 Created: 11/1/97 02008 02009 Inputs: pRecord = ptr to a record 02010 pStr = ptr to string to update 02011 02012 Returns: - 02013 Purpose: Provides descriptions for the stroke attribute records. 02014 02015 Notes: This function is only present in _DEBUG builds 02016 02017 ********************************************************************************************/ 02018 02019 #ifdef XAR_TREE_DIALOG 02020 void StrokeAttrRecordHandler::GetRecordDescriptionText(CXaraFileRecord* pRecord, StringBase* pStr) 02021 { 02022 if (pStr == NULL || pRecord == NULL) 02023 return; 02024 02025 // Call base class first to output the tag and size 02026 CamelotRecordHandler::GetRecordDescriptionText(pRecord, pStr); 02027 02028 UINT32 Tag = pRecord->GetTag(); 02029 // INT32 RecordNumber = pRecord->GetRecordNumber(); 02030 02031 switch (Tag) 02032 { 02033 case TAG_STROKETYPE: 02034 *pStr += String_64(_T("New-style stroke (basic type)")); // Only 1 stroke type so far! 02035 break; 02036 02037 case TAG_STROKEDEFINITION: 02038 *pStr += String_64(_T("New-style stroke (Vector type)")); 02039 break; 02040 02041 case TAG_STROKEAIRBRUSH: 02042 { 02043 // Load the value function and see what type of object we get back! 02044 ValueFunction *pValFunc = ValueFunction::ReadFileRecord(pRecord); 02045 if (pValFunc != NULL) 02046 { 02047 String_256 Desc; 02048 Desc._MakeMsg(_T("Airbrush stroke of class #1%s"), 02049 (TCHAR *)pValFunc->GetRuntimeClass()->m_lpszClassName); 02050 *pStr += Desc; 02051 delete pValFunc; 02052 } 02053 else 02054 *pStr += String_64(_T("Unknown Airbrush stroke type (failed to load)")); 02055 } 02056 break; 02057 break; 02058 02059 case TAG_VARIABLEWIDTHFUNC: 02060 { 02061 VariableWidthID Function = VarWidth_NotPredefined; 02062 pRecord->ReadUINT32((UINT32 *)&Function); 02063 switch(Function) 02064 { 02065 case VarWidth_Constant: 02066 *pStr += String_64(_T("Constant predefined stroke width")); 02067 break; 02068 02069 case VarWidth_LinRamp: 02070 *pStr += String_64(_T("Linear-Ramp predefined stroke width")); 02071 break; 02072 02073 case VarWidth_SRamp: 02074 *pStr += String_64(_T("S-Ramp predefined stroke width")); 02075 break; 02076 02077 default: 02078 *pStr += String_64(_T("Unknown predefined stroke width type")); 02079 break; 02080 } 02081 } 02082 break; 02083 02084 case TAG_VARIABLEWIDTHTABLE: 02085 { 02086 // Load the value function and see what type of object we get back! 02087 ValueFunction *pValFunc = ValueFunction::ReadFileRecord(pRecord); 02088 if (pValFunc != NULL) 02089 { 02090 String_256 Desc; 02091 Desc._MakeMsg(_T("VariableWidth of class #1%s"), 02092 (TCHAR *)pValFunc->GetRuntimeClass()->m_lpszClassName); 02093 *pStr += Desc; 02094 delete pValFunc; 02095 } 02096 else 02097 *pStr += String_64(_T("Unknown VariableWidth ValueFunction (failed to load)")); 02098 } 02099 break; 02100 02101 default: 02102 ERROR3(_T("Unknown tag passed to StrokeAttrRecordHandler")); 02103 break; 02104 } 02105 } 02106 02107 #endif // _DEBUG