00001 // $Id: brshattr.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 00099 // Brush Attribute implementation 00100 00101 #include "camtypes.h" 00102 #include "brshattr.h" 00103 #include "brshcomp.h" 00104 //#include "rik.h" // for the strings 00105 //#include "basestr.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00106 #include "samplist.h" 00107 00108 // Native file load/save includes 00109 //#include "camfiltr.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00110 //#include "cxfdefs.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00111 //#include "cxfrec.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00112 #include "cxftags.h" 00113 //#include "tim.h" // For _R(IDE_FILE_WRITE_ERROR) 00114 //#include "ink.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00115 00116 // various includes 00117 #include "lineattr.h" 00118 #include "ndbldpth.h" // for cpathpointinfo 00119 //#include "fillval.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00120 #include "nodepath.h" 00121 #include "blendatt.h" 00122 #include "pbecomea.h" 00123 //#include "group.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00124 #include "brpress.h" 00125 #include "pen.h" 00126 //#include "colormgr.h" 00127 //#include "freehand.h" 00128 #include "progress.h" 00129 #include "nodetext.h" 00130 #include "nodetxtl.h" // for our text bodges 00131 #include "nodetxts.h" 00132 #include "ppbrush.h" 00133 00134 #ifdef NEWFASTBRUSHES 00135 #include "nodebmp.h" 00136 #endif 00137 00138 00139 CC_IMPLEMENT_DYNCREATE(AttrBrushType, NodeAttribute) 00140 CC_IMPLEMENT_DYNAMIC(BrushAttrValue, AttributeValue) 00141 CC_IMPLEMENT_DYNAMIC(BrushAttrRecordHandler, CamelotRecordHandler); 00142 00143 00144 // Declare smart memory handling in Debug builds 00145 #define new CAM_DEBUG_NEW 00146 00147 00148 /*------------------------------------------------------------------------------------------- 00149 --------------------------------------------------------------------------------------------- 00150 --------------------------------BrushAttrValue class implementation-------------------------- 00151 --------------------------------------------------------------------------------------------*/ 00152 00153 00154 /******************************************************************************************** 00155 00156 > BrushAttrValue::BrushAttrValue(PathProcessorBrush *pPathProcessor = NULL); 00157 00158 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00159 Created: 13/12/99 00160 00161 Inputs: - 00162 Purpose: Default Constuctor for BrushAttrValue 00163 00164 ********************************************************************************************/ 00165 00166 BrushAttrValue::BrushAttrValue() 00167 { 00168 #ifdef NEWFASTBRUSHES 00169 pCachedBitmap = NULL; 00170 #endif 00171 m_pProcessor = NULL; 00172 #ifdef BRUSHPOINTSCACHE 00173 m_pCachedPoints = NULL; 00174 #endif 00175 m_pTimeStampList = NULL; 00176 00177 m_pPressureVals = NULL; 00178 m_CachedBRect = DocRect(0,0,0,0); 00179 00180 m_pPressureSampler = NULL; 00181 } 00182 00183 00184 00185 /******************************************************************************************** 00186 00187 > BrushAttrValue::BrushAttrValue(PathProcessorBrush *pPathProcessor = NULL); 00188 00189 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00190 Created: 13/12/99 00191 00192 Inputs: pPathProcessor - the stroke path-processor which will do the stroking 00193 effect "applied" by this attribute. NULL indicates that this attribute 00194 does no stroking (i.e. that the path should have an old-style "line") 00195 00196 NOTE that this object is NOW OWNED by this BrushAttrValue, and will be 00197 deleted when the attribute value is deleted. 00198 00199 Purpose: Default Constuctor for BrushAttrValue 00200 00201 ********************************************************************************************/ 00202 00203 BrushAttrValue::BrushAttrValue(PathProcessorBrush *pPathProcessor) 00204 { 00205 #ifdef NEWFASTBRUSHES 00206 pCachedBitmap = NULL; 00207 #endif 00208 // Remember our processor, and let it know that we "own" it 00209 m_pProcessor = pPathProcessor; 00210 // if (m_pProcessor != NULL) 00211 // m_pProcessor->SetParentAttribute(this); 00212 #ifdef BRUSHPOINTSCACHE 00213 m_pCachedPoints = NULL; 00214 #endif 00215 m_pTimeStampList = NULL; 00216 00217 00218 m_pPressureVals = NULL; 00219 m_CachedBRect = DocRect(0,0,0,0); 00220 00221 m_pPressureSampler = NULL; 00222 } 00223 00224 00225 /******************************************************************************************** 00226 00227 > BrushAttrValue::~BrushAttrValue() 00228 00229 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00230 Created: 13/12/99 00231 00232 Purpose: Destructor 00233 Deletes any attached PathProcessor (see the constructor) 00234 00235 ********************************************************************************************/ 00236 00237 BrushAttrValue::~BrushAttrValue() 00238 { 00239 #ifdef NEWFASTBRUSHES 00240 if (pCachedBitmap != NULL) 00241 { 00242 delete (pCachedBitmap->GetBitmap ()); 00243 delete (pCachedBitmap); 00244 pCachedBitmap = NULL; 00245 } 00246 #endif 00247 if (m_pProcessor != NULL) 00248 { 00249 delete m_pProcessor; 00250 m_pProcessor = NULL; 00251 } 00252 FlushCache(); 00253 FlushTimeStampCache(); 00254 FlushPressureCache(); 00255 00256 } 00257 00258 00259 00260 /******************************************************************************************** 00261 00262 > static BOOL BrushAttrValue::Init(void) 00263 00264 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00265 Created: 13/12/99 00266 00267 Returns: TRUE if it initilised successfully 00268 00269 Purpose: Registers a default attribute of this type with the attribute manager 00270 00271 ********************************************************************************************/ 00272 00273 BOOL BrushAttrValue::Init(void) 00274 { 00275 // The default attribute is one that has no effect (i.e. produces old-style "lines") 00276 BrushAttrValue *pAttr = new BrushAttrValue; 00277 if (pAttr == NULL) 00278 return FALSE; 00279 00280 UINT32 ID = AttributeManager::RegisterDefaultAttribute(CC_RUNTIME_CLASS(AttrBrushType), 00281 pAttr); 00282 00283 if (ID == ATTR_BAD_ID) 00284 return FALSE; 00285 ENSURE(ID == ATTR_BRUSHTYPE, "Incorrect ID for attribute!"); 00286 00287 //ERROR2IF(ID == ATTR_BAD_ID, FALSE, "Bad ID when Initialising BrushAttrValue"); 00288 //ENSURE(ID == ATTR_BRUSHTYPE, "Incorrect Attribute ID"); 00289 return(TRUE); 00290 } 00291 00292 00293 00294 /******************************************************************************************** 00295 00296 > virtual void BrushAttrValue::Render(RenderRegion *pRegion, BOOL Temp) 00297 00298 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00299 Created: 13/12/99 00300 00301 Inputs: pRegion - the render region to render this attribute into. 00302 00303 Purpose: Sets the BrushAttrValue attribute for the given render region. 00304 00305 Notes: This attribute makes itself current in the render region, and 00306 also (possibly) adds a PathProcessor to handle stroking of 00307 all future rendered paths (until the attr is "restored") 00308 00309 SeeAlso: BrushAttrValue::Restore 00310 00311 ********************************************************************************************/ 00312 00313 void BrushAttrValue::Render(RenderRegion *pRegion, BOOL Temp) 00314 { 00315 // Stack the current attribute and set ourselves up as the new one 00316 pRegion->SaveAttribute(ATTR_BRUSHTYPE, this, Temp); 00317 00318 #ifdef BRUSHPOINTSCACHE 00319 // if we don't yet have a cache then make one here 00320 if (m_pCachedPoints == NULL) 00321 InitialisePointsCache(); 00322 #endif 00323 00324 // Find if we have a path processor to do the stroking, and if we do, 00325 // stack a copy of it (a copy must be used to be thread-safe & bgrender-safe) 00326 if (m_pProcessor != NULL) 00327 { 00328 // TRACEUSER("Diccon", _T("Rendering brush attribute\n") ); 00329 00330 // make a clone and push it onto the stack 00331 PathProcessorBrush *pNewProcessor = m_pProcessor->Clone(); 00332 if (pNewProcessor != NULL) 00333 { 00334 //TRACEUSER("Diccon", _T("Pushing path processor\n") ); 00335 #ifdef NEWFASTBRUSHES 00336 pNewProcessor->SetLinkedAttribute (this); 00337 #endif 00338 pRegion->PushPathProcessor(pNewProcessor); 00339 } 00340 00341 } 00342 } 00343 00344 00345 00346 /******************************************************************************************** 00347 00348 > virtual void BrushAttrValue::Restore(RenderRegion *pRegion, BOOL Temp) 00349 00350 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00351 Created: 13/12/99 00352 00353 Inputs: pRegion - the render region to restore the attribute into. 00354 Temp - TRUE if this is a temporary attribute, FALSE if it is 00355 permanent (e.g. it's in a document tree). 00356 00357 Purpose: Restores the BrushAttrValue attribute for the given render region. 00358 00359 Notes: This attribute makes sure it removes any PathProcessor it added 00360 to handle path stroking in BrushAttrValue::Render 00361 00362 ********************************************************************************************/ 00363 00364 void BrushAttrValue::Restore(RenderRegion *pRegion, BOOL Temp) 00365 { 00366 pRegion->RestoreAttribute(ATTR_BRUSHTYPE, this, Temp); 00367 } 00368 00369 00370 00371 /******************************************************************************************** 00372 00373 > void BrushAttrValue::GoingOutOfScope(RenderRegion *pRegion) 00374 00375 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00376 Created: 9/1/97 00377 00378 Inputs: pRegion - the render region the attribute is in use by 00379 00380 Purpose: A sister function to Render() 00381 00382 This is called by a render region when an attribute goes out of 00383 scope, i.e. when the attribute is no longer in use and is popped 00384 off the stack for the last time. (Do NOT confuse this with being 00385 pushed onto the render stack when overridden by another attr) 00386 00387 It gives the attribute a chance to remove any PathProcessor(s) 00388 it added to the RenderRegion when it was Render()ed. 00389 00390 Notes: This attribute makes sure it removes any PathProcessor it added 00391 to handle path stroking in BrushAttrValue::Render 00392 00393 SeeAlso: BrushAttrValue::Render() 00394 00395 ********************************************************************************************/ 00396 00397 void BrushAttrValue::GoingOutOfScope(RenderRegion *pRegion) 00398 { 00399 if (m_pProcessor != NULL) 00400 { 00401 //TRACEUSER("Diccon", _T("Popping path processor\n") ); 00402 pRegion->PopPathProcessor(); 00403 } 00404 } 00405 00406 00407 00408 /******************************************************************************************** 00409 00410 > virtual void BrushAttrValue::SimpleCopy(AttributeValue *pValue) 00411 00412 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00413 Created: 13/12/99 00414 00415 Inputs: pValue - pointer to the AttributeValue to copy 00416 00417 Purpose: See AttributeValue::SimpleCopy 00418 00419 ********************************************************************************************/ 00420 00421 void BrushAttrValue::SimpleCopy(AttributeValue *pValue) 00422 { 00423 ERROR3IF(!IS_A(pValue, BrushAttrValue), 00424 "Invalid Attribute value passed to BrushAttrValue::SimpleCopy"); 00425 00426 // Just uses the assignment operator 00427 *this = *((BrushAttrValue *) pValue); 00428 00429 00430 00431 } 00432 00433 /******************************************************************************************** 00434 00435 > BOOL BrushAttrValue::Blend(BlendAttrParam* pBlendParam) 00436 00437 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00438 Created: 17/3/2000 00439 Inputs: pBlendParam - contains the blend info, 00440 Outputs: pBlendParama - containing the blended attributes 00441 Returns: TRUE - Blend went ok, the blended attr val is valid; FALSE if not. 00442 Purpose: Blends between two brush attributes. In fact at the moment it just blends 00443 between the parameters in the two path processors. At some point it should 00444 also blend between the ink objects and attributes. 00445 00446 Errors: Out of memory. 00447 00448 ********************************************************************************************/ 00449 00450 BOOL BrushAttrValue::Blend(BlendAttrParam* pBlendParam) 00451 { 00452 ERROR2IF(pBlendParam == NULL, FALSE, "BlendAttrParam is NULL in BrushAttrValue::Blend"); 00453 00454 // First get the fill that we are blending to 00455 BrushAttrValue* pOtherBrush = 00456 (BrushAttrValue*)pBlendParam->GetOtherAttrVal(); 00457 if (pOtherBrush == NULL) 00458 return FALSE; 00459 00460 // it is ok if we have null path processors as that merely indicates a default line 00461 PathProcessorBrush* pOtherPPB = pOtherBrush->GetPathProcessor(); 00462 PathProcessorBrush* pThisPPB = GetPathProcessor(); 00463 00464 // Now make a new object of the same type as this one 00465 //CCRuntimeClass* ObjectType = GetRuntimeClass(); 00466 BrushAttrValue* pNewAttr = new BrushAttrValue; //(BrushAttrValue*)ObjectType->CreateObject(); 00467 00468 if (pNewAttr == NULL) 00469 { 00470 // Fail if we couldn't create the new fill 00471 pBlendParam->SetBlendedAttrVal(NULL); 00472 return FALSE; 00473 } 00474 00475 // Make the new fill an exact copy of this one 00476 pNewAttr->SimpleCopy(this); 00477 00478 // make a new path processor 00479 PathProcessorBrush* pBlendedPPB = new PathProcessorBrush; 00480 00481 if (pBlendedPPB == NULL) 00482 { 00483 delete pNewAttr; 00484 return FALSE; 00485 } 00486 00487 pBlendedPPB->SetBrushDefinition(BrushHandle_NoBrush); 00488 00489 // find out what point along the blend we are at 00490 double BlendRatio = pBlendParam->GetBlendRatio(); 00491 00492 // we need to ask the brush component to make a blended brush definition for us 00493 Document* pDoc = Document::GetCurrent(); 00494 ERROR2IF(pDoc == NULL, FALSE, "Wheres the document?"); 00495 BrushComponent* pBrushComp = (BrushComponent*)pDoc->GetDocComponent(CC_RUNTIME_CLASS(BrushComponent)); 00496 ERROR2IF(pBrushComp == NULL, FALSE, "No brush component"); 00497 00498 // don't want to blend the variables any more, lets just copy them 00499 BrushDefinition* pThisDef = GetBrushDefinition(); 00500 BrushDefinition* pOtherDef = pOtherBrush->GetBrushDefinition(); 00501 BrushHandle ThisHandle = BrushHandle_NoBrush; 00502 BrushHandle OtherHandle = BrushHandle_NoBrush; 00503 00504 if (pThisPPB != NULL) 00505 ThisHandle = pThisPPB->GetBrushDefinitionHandle(); 00506 00507 if (pOtherPPB != NULL) 00508 OtherHandle = pOtherPPB->GetBrushDefinitionHandle(); 00509 00510 if (BlendRatio <= 0.5) 00511 { 00512 { 00513 if (pThisDef != NULL) 00514 { 00515 // if we have a ppb then copy the data across 00516 if (pThisPPB != NULL) 00517 { 00518 BrushData ThisData; 00519 pThisPPB->CopyBrushData(&ThisData); 00520 pBlendedPPB->CopyDataFromObject(&ThisData); 00521 } 00522 else // otherwise go with the definition 00523 pThisDef->CopyDataToProcessor(pBlendedPPB); 00524 00525 pBlendedPPB->SetBrushDefinition(GetBrushHandle()); 00526 pBlendedPPB->SetMaxScaling(pThisDef->GetMaxScaling()); 00527 } 00528 else 00529 { 00530 // turns out we're not really a brush so delete our processor 00531 delete pBlendedPPB; 00532 pBlendedPPB = NULL; 00533 } 00534 } 00535 } 00536 else 00537 { 00538 /* if (ThisHandle == OtherHandle) 00539 { 00540 if (pOtherPPB != NULL) 00541 { 00542 delete pBlendedPPB; 00543 pBlendedPPB = pOtherPPB->Clone(); 00544 } 00545 //pBlendedPPB->SetBrushDefinition(BrushHandle_NoBrush); 00546 } 00547 else */ 00548 { 00549 if (pOtherDef != NULL) 00550 { 00551 if (pOtherPPB != NULL) 00552 { 00553 BrushData OtherData; 00554 pOtherPPB->CopyBrushData(&OtherData); 00555 pBlendedPPB->CopyDataFromObject(&OtherData); 00556 00557 // little hack that we need to ensure the scaling is correct 00558 AttrBrushType* pAttrBrush = pOtherPPB->GetParentAttribute(); 00559 if (pAttrBrush != NULL) 00560 { 00561 MILLIPOINT LineWidth = pAttrBrush->GetAppliedLineWidth(); 00562 pOtherPPB->ScaleToValue(LineWidth); 00563 } 00564 00565 } 00566 else 00567 pOtherDef->CopyDataToProcessor(pBlendedPPB); 00568 pBlendedPPB->SetMaxScaling(pOtherDef->GetMaxScaling()); 00569 } 00570 else 00571 { 00572 // special case to deal with blend between a brushed and non=brushed object 00573 delete pBlendedPPB; 00574 pBlendedPPB = NULL; 00575 pNewAttr->SetPathProcessor(NULL); 00576 pBlendParam->SetBlendedAttrVal(pNewAttr); 00577 return TRUE; 00578 } 00579 pBlendedPPB->SetBrushDefinition(pOtherBrush->GetBrushHandle()); 00580 } 00581 } 00582 00583 // trudge through all the variables and blend them 00584 /* 00585 // blend scaling variables 00586 double BlendedScaling = BlendDouble(m_pProcessor->GetBrushScaling(), pOtherPPB->GetBrushScaling(), BlendRatio); 00587 pBlendedPPB->SetBrushScaling(BlendedScaling); 00588 double BlendedScalingIncr = BlendDouble(m_pProcessor->GetBrushScalingIncr(), pOtherPPB->GetBrushScalingIncr(), BlendRatio); 00589 pBlendedPPB->SetBrushScalingIncr(BlendedScalingIncr); 00590 00591 // blend spacing variables 00592 MILLIPOINT BlendedSpacing = BlendINT32(m_pProcessor->GetSpacing(), pOtherPPB->GetSpacing(), BlendRatio); 00593 pBlendedPPB->SetSpacing(BlendedSpacing); 00594 MILLIPOINT BlendedSpacingIncrConst = BlendINT32(m_pProcessor->GetSpacingIncrConst(), pOtherPPB->GetSpacingIncrConst(), BlendRatio); 00595 pBlendedPPB->SetSpacingIncrConst(BlendedSpacingIncrConst); 00596 double BlendedSpacingIncrProp = BlendDouble(m_pProcessor->GetSpacingIncrProp(), pOtherPPB->GetSpacingIncrProp(), BlendRatio); 00597 pBlendedPPB->SetSpacingIncrProp(BlendedSpacingIncrProp); 00598 UINT32 BlendedSpacingMaxRand = BlendUINT32(m_pProcessor->GetSpacingMaxRand(), pOtherPPB->GetSpacingMaxRand(), BlendRatio); 00599 pBlendedPPB->SetSpacingMaxRand(BlendedSpacingMaxRand); 00600 00601 // for the random seed don't blend, just use one or the other 00602 if (BlendRatio <= 0.5) 00603 pBlendedPPB->SetSpacingRandSeed(m_pProcessor->GetSpacingRandSeed()); 00604 else 00605 pBlendedPPB->SetSpacingRandSeed(pOtherPPB->GetSpacingRandSeed()); 00606 00607 // Offset variables 00608 MILLIPOINT BlendedOffsetValue = BlendINT32(m_pProcessor->GetPathOffsetValue(), pOtherPPB->GetPathOffsetValue(), BlendRatio); 00609 pBlendedPPB->SetPathOffsetValue(BlendedOffsetValue); 00610 MILLIPOINT BlendedOffsetIncrConst = BlendINT32(m_pProcessor->GetPathOffsetIncrConst(), pOtherPPB->GetPathOffsetIncrConst(), BlendRatio); 00611 pBlendedPPB->SetPathOffsetIncrConst(BlendedOffsetIncrConst); 00612 double BlendedOffsetIncrProp = BlendDouble(m_pProcessor->GetPathOffsetIncrProp(), pOtherPPB->GetPathOffsetIncrProp(), BlendRatio); 00613 pBlendedPPB->SetPathOffsetIncrProp(BlendedOffsetIncrProp); 00614 UINT32 BlendedOffsetMaxRand = BlendUINT32(m_pProcessor->GetOffsetValueMaxRand(), pOtherPPB->GetOffsetValueMaxRand(), BlendRatio); 00615 pBlendedPPB->SetOffsetValueMaxRand(BlendedOffsetMaxRand); 00616 00617 // don't blend offset type, just use one or the other, likewise random seed 00618 if (BlendRatio <= 0.5) 00619 { 00620 pBlendedPPB->SetPathOffsetType(m_pProcessor->GetPathOffsetType()); 00621 pBlendedPPB->SetOffsetTypeRandSeed(m_pProcessor->GetOffsetTypeRandSeed()); 00622 pBlendedPPB->SetOffsetValueRandSeed(m_pProcessor->GetOffsetValueRandSeed()); 00623 } 00624 else 00625 { 00626 pBlendedPPB->SetPathOffsetType(pOtherPPB->GetPathOffsetType()); 00627 pBlendedPPB->SetOffsetTypeRandSeed(pOtherPPB->GetOffsetTypeRandSeed()); 00628 pBlendedPPB->SetOffsetValueRandSeed(pOtherPPB->GetOffsetValueRandSeed()); 00629 } 00630 00631 // rotation 00632 double BlendedRotateAngle = BlendDouble(m_pProcessor->GetRotationAngle(), pOtherPPB->GetRotationAngle(), BlendRatio); 00633 pBlendedPPB->SetRotationAngle(BlendedRotateAngle); 00634 00635 // do all the flags at once 00636 if (BlendRatio <= 0.5) 00637 { 00638 pBlendedPPB->SetRotated(m_pProcessor->IsRotated()); 00639 pBlendedPPB->SetTiling(m_pProcessor->IsTiled()); 00640 pBlendedPPB->SetUseLocalFillColour(m_pProcessor->GetUseLocalFillColour()); 00641 pBlendedPPB->SetScaleToLineWidth(m_pProcessor->IsScalingToLineWidth()); 00642 pBlendedPPB->SetBrushDefinition(m_pProcessor->GetBrushDefinitionHandle()); 00643 } 00644 else 00645 { 00646 pBlendedPPB->SetRotated(pOtherPPB->IsRotated()); 00647 pBlendedPPB->SetTiling(pOtherPPB->IsTiled()); 00648 pBlendedPPB->SetUseLocalFillColour(pOtherPPB->GetUseLocalFillColour()); 00649 pBlendedPPB->SetScaleToLineWidth(pOtherPPB->IsScalingToLineWidth()); 00650 pBlendedPPB->SetBrushDefinition(pOtherPPB->GetBrushDefinitionHandle()); 00651 } 00652 */ 00653 // whew, think thats the lot, now attach the processor to the new attribute 00654 pNewAttr->SetPathProcessor(pBlendedPPB); 00655 00656 // and attach the attribute to the blend param 00657 pBlendParam->SetBlendedAttrVal(pNewAttr); 00658 00659 return TRUE; 00660 } 00661 00662 00663 00664 /******************************************************************************************** 00665 00666 > BOOL BrushAttrValue::DoBecomeA(BecomeA* pBecomeA, Node* pParent) 00667 00668 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00669 Created: 17/3/2000 00670 Inputs: pBecomeA - the object that tells us what to become, and recieves the results 00671 pParent - the node that this attribute is applied to 00672 Outputs: 00673 Returns: TRUE if everything went ok, 00674 Purpose: To convert our brush into its individual paths and attributes, works in a very 00675 similar way to the bounding box, by finding the paths of our parent node and 00676 asking our path processor to do the calculations 00677 00678 ********************************************************************************************/ 00679 00680 BOOL BrushAttrValue::DoBecomeA(BecomeA* pBecomeA, Node* pParent) 00681 { 00682 ERROR2IF(pBecomeA == NULL, FALSE, "BecomeA pointer is NULL in BrushAttrValue::DoBecomeA"); 00683 ERROR2IF(pParent == NULL, FALSE, "Parent node is NULL in BrushAttrValue::DoBecomeA"); 00684 00685 if (m_pProcessor == NULL) 00686 return FALSE; 00687 00688 BOOL Success = FALSE; 00689 // UINT32 Dummy = 0; 00690 // if we have a nodepath then we can simply use its member path, otherwise we 00691 // have to ask it to become a nodepath 00692 if (pParent->IsNodePath()) 00693 { 00694 // we have a special calculation for nodepaths, because we can use their path 00695 Success = m_pProcessor->DoBecomeA(pBecomeA, &((NodePath*)pParent)->InkPath, pParent); 00696 } 00697 else 00698 { 00699 BecomeA TestBecomeAPath(BECOMEA_TEST, CC_RUNTIME_CLASS(NodePath)); 00700 if (pParent->CanBecomeA(&TestBecomeAPath)) 00701 { 00702 // we must be applied to some arbitrary shape. The thing is that we need to have 00703 // a path to pass to the PPB, so want to get a passback of all the paths in 00704 // the node 00705 00706 // we need to allocate a path 00707 Path* pPath = new Path; 00708 if (pPath != NULL && pPath->Initialise()) 00709 { 00710 PathBecomeA BecomeAPath(BECOMEA_PASSBACK, CC_RUNTIME_CLASS(NodePath), NULL, FALSE, pPath); 00711 if (pParent->DoBecomeA(&BecomeAPath)) 00712 { 00713 Success = m_pProcessor->DoBecomeA(pBecomeA, pPath, pParent); 00714 } 00715 delete pPath; 00716 } 00717 } 00718 } 00719 return Success; 00720 } 00721 00722 /******************************************************************************************** 00723 00724 > static UINT32 BrushAttrValue::BlendUINT32(UINT32 First, UINT32 Second, double BlendRatio) 00725 00726 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00727 Created: 13/12/99 00728 Inputs: First - the first number to blend 00729 Second - the second number to blend 00730 BlendRatio - the proportion of first to second number 00731 Returns: the blended result 00732 00733 Purpose: to blend between two numbers and return the result 00734 00735 ********************************************************************************************/ 00736 00737 UINT32 BrushAttrValue::BlendUINT32(UINT32 First, UINT32 Second, double BlendRatio) 00738 { 00739 double InvRatio = 1 - BlendRatio; 00740 double BlendedVal = ((double)First * InvRatio) + ((double)Second*BlendRatio); 00741 00742 return (UINT32)BlendedVal; 00743 } 00744 00745 00746 /******************************************************************************************** 00747 00748 > static INT32 BrushAttrValue::BlendINT32(INT32 First, INT32 Second, double BlendRatio) 00749 00750 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00751 Created: 13/12/99 00752 Inputs: First - the first number to blend 00753 Second - the second number to blend 00754 BlendRatio - the proportion of first to second number 00755 Returns: the blended result 00756 00757 Purpose: to blend between two numbers and return the result 00758 00759 ********************************************************************************************/ 00760 00761 INT32 BrushAttrValue::BlendINT32(INT32 First, INT32 Second, double BlendRatio) 00762 { 00763 double InvRatio = 1 - BlendRatio; 00764 double BlendedVal = ((double)First * InvRatio) + ((double)Second*BlendRatio); 00765 00766 return (INT32)BlendedVal; 00767 00768 } 00769 00770 00771 /******************************************************************************************** 00772 00773 > static double BrushAttrValue::BlendDouble(double First, double Second, double BlendRatio) 00774 00775 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00776 Created: 13/12/99 00777 Inputs: First - the first number to blend 00778 Second - the second number to blend 00779 BlendRatio - the proportion of first to second number 00780 Returns: the blended result 00781 00782 Purpose: to blend between two numbers and return the result 00783 00784 ********************************************************************************************/ 00785 00786 double BrushAttrValue::BlendDouble(double First, double Second, double BlendRatio) 00787 { 00788 double InvRatio = 1 - BlendRatio; 00789 double BlendedVal = ((double)First * InvRatio) + ((double)Second*BlendRatio); 00790 00791 return BlendedVal; 00792 00793 } 00794 00795 00796 /******************************************************************************************** 00797 00798 > void BrushAttrValue::InitialisePointsCache() 00799 00800 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00801 Created: 13/12/99 00802 00803 Inputs: - 00804 00805 Purpose: allocates the map to store cached points 00806 00807 ********************************************************************************************/ 00808 00809 void BrushAttrValue::InitialisePointsCache() 00810 { 00811 00812 #ifdef BRUSHPOINTSCACHE 00813 // get rid of the existing one (if there is one) 00814 FlushCache(); 00815 //allocate a new map 00816 m_pCachedPoints = new PointsMap; 00817 PORTNOTE("other","Not use hash based map, InitHashTable makes no sense") 00818 #ifndef EXCLUDE_FROM_XARALX 00819 if (m_pCachedPoints != NULL) 00820 m_pCachedPoints->InitHashTable(1277); // Init hash table size to a suitably large prime number 00821 #endif 00822 #endif 00823 00824 } 00825 00826 00827 /******************************************************************************************** 00828 00829 > void BrushAttrValue::SetPointsCache(PointsMap * pMap) 00830 00831 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00832 Created: 13/12/99 00833 00834 Inputs: pointer to list to use as cache 00835 00836 Purpose: sets the cache member variable 00837 ********************************************************************************************/ 00838 00839 void BrushAttrValue::SetCache(PointsMap* pMap) 00840 { 00841 #ifdef BRUSHPOINTSCACHE 00842 FlushCache(); 00843 m_pCachedPoints = pMap; 00844 #endif 00845 } 00846 00847 00848 /******************************************************************************************** 00849 00850 > void BrushAttrValue::SetPressureCache(CDistanceSampler *pSampler) 00851 00852 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00853 Created: 13/12/99 00854 00855 Inputs: pointer to array to use as cache 00856 00857 Purpose: sets the pressure array memeber variable 00858 ********************************************************************************************/ 00859 00860 void BrushAttrValue::SetPresssureCache(CDistanceSampler *pSampler) 00861 { 00862 // Do we want to delete any existing cache? 00863 if (m_pPressureSampler != NULL) 00864 { 00865 delete m_pPressureSampler; 00866 } 00867 m_pPressureSampler = pSampler; 00868 } 00869 00870 00871 /******************************************************************************************** 00872 00873 > void BrushAttrValue::FlushPressureCache() 00874 00875 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00876 Created: 13/12/99 00877 Inputs: - 00878 Returns: - 00879 Purpose: clears out and deletes the cache of pressure values 00880 ********************************************************************************************/ 00881 00882 void BrushAttrValue::FlushPressureCache() 00883 { 00884 if (m_pPressureSampler != NULL) 00885 { 00886 delete m_pPressureSampler; 00887 m_pPressureSampler = NULL; 00888 } 00889 } 00890 /******************************************************************************************** 00891 00892 > PressureArray* BrushAttrValue::GetPressureCache() 00893 00894 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00895 Created: 13/12/99 00896 00897 Returns: the pressure cache 00898 00899 Purpose: as above 00900 ********************************************************************************************/ 00901 00902 CDistanceSampler* BrushAttrValue::GetPressureCache() 00903 { 00904 return m_pPressureSampler; 00905 } 00906 00907 00908 /******************************************************************************************** 00909 00910 > UINT32 BrushAttrValue::GetPressureValue(UINT32 Index) 00911 00912 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00913 Created: 13/12/99 00914 00915 Returns: the pressure value at that index, or PRESSURE_INVALID if index is out of range 00916 00917 Purpose: as above 00918 ********************************************************************************************/ 00919 00920 UINT32 BrushAttrValue::GetPressureValue(UINT32 Index) 00921 { 00922 if (m_pPressureVals == NULL) 00923 return PRESSURE_INVALID; 00924 if (Index >= (UINT32)m_pPressureVals->size()) 00925 return PRESSURE_INVALID; 00926 00927 PressureItem Item = (*m_pPressureVals)[Index]; 00928 return Item.m_Pressure; 00929 } 00930 00931 00932 /******************************************************************************************** 00933 00934 > BOOL BrushAttrValue::SetPressureValue(UINT32 Index, UINT32 Value) 00935 00936 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00937 Created: 13/12/99 00938 Inputs: Index - the index in to the array 00939 Value - the value to set 00940 Returns: TRUE if all went well 00941 00942 Purpose: as above 00943 ********************************************************************************************/ 00944 00945 BOOL BrushAttrValue::SetPressureValue(UINT32 Index, PressureItem Value) 00946 { 00947 if (m_pPressureVals == NULL) 00948 return FALSE; 00949 00950 size_t NumValues = m_pPressureVals->size(); 00951 if (Index > NumValues) 00952 return FALSE; 00953 00954 // if index is one greater than our current size then we can expanf 00955 if (Index == NumValues) 00956 m_pPressureVals->push_back( Value ); 00957 else 00958 (*m_pPressureVals)[Index] = Value; 00959 00960 return FALSE; 00961 } 00962 00963 00964 00965 00966 /******************************************************************************************** 00967 00968 > static void BrushAttrValue::ShuffleArrayUp(PressureArray* pArray, UINT32 StartIndex) 00969 00970 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00971 Created: 13/12/99 00972 Inputs: pArray - the array to shuffle 00973 StartIndex - the index to shuffle from 00974 00975 Returns: - 00976 00977 Purpose: shuffles each element in the array up by one, assumes that there is already 00978 a spare element at the top of the array. 00979 ********************************************************************************************/ 00980 00981 void BrushAttrValue::ShuffleArrayUp(PressureArray* pPressure, UINT32 StartIndex) 00982 { 00983 if (pPressure == NULL) 00984 { 00985 ERROR3("Pressure array is NULL"); 00986 return; 00987 } 00988 00989 size_t NumValues = pPressure->size(); 00990 if (StartIndex >= NumValues) 00991 { 00992 ERROR3("Start index is greater than size of array"); 00993 return; 00994 } 00995 00996 // we count down from the top value and move 00997 // each one up, recall that the extra array element has already been allocated 00998 PressureItem Item; 00999 for( size_t i = NumValues - 2; i >= StartIndex; i-- ) 01000 { 01001 Item = (*pPressure)[i]; 01002 // if (i+1 >= NumValues) 01003 // { 01004 // TRACEUSER("Diccon", _T("Adding array element at %d\n"), i+1); 01005 // pPressure->SetAtGrow(i+1, Item); 01006 // } 01007 // else 01008 (*pPressure)[i] = Item; 01009 } 01010 } 01011 01012 01013 01014 /******************************************************************************************** 01015 01016 > void BrushAttrValue::CalculatePressureArrayProportionalDistances(MILLIPOINT PathLength) 01017 01018 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01019 Created: 13/12/99 01020 Inputs: The length of the path to which this attribute applies 01021 Returns: - 01022 Purpose: Only use when we are utilising the path stamping cache. This fn. proceeds 01023 through the list and works out the proportional distance along the path for 01024 each object. 01025 See Also: TimeStampBrushPoint 01026 ********************************************************************************************/ 01027 01028 void BrushAttrValue::CalculatePressureArrayProportions(MILLIPOINT PathLength) 01029 { 01030 if (m_pPressureVals == NULL || PathLength <= 0) 01031 { 01032 ERROR3("Error in calculating proportional distance"); 01033 return; 01034 } 01035 PressureItem Item; 01036 for (size_t i = 0; i < m_pPressureVals->size(); i++) 01037 { 01038 Item = (*m_pPressureVals)[i]; 01039 if (Item.m_Distance > PathLength) 01040 ERROR3("Item distance is greater than path length in BrushAttrValue::CalculatePressureArrayProportions"); 01041 Item.m_Proportion = Item.m_Distance / (double) PathLength; 01042 (*m_pPressureVals)[i] = Item; 01043 } 01044 } 01045 01046 /******************************************************************************************** 01047 01048 > bool BrushAttrValue::DeletePressurePoints(MILLIPOINT Start, MILLIPOINT End, SampleArray* pRemovedPoints) 01049 01050 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01051 Created: 6/10/99 01052 Inputs: Start - distance from which to delete 01053 End - the distance to stop deleting at 01054 pRemovedPoints - an array to put the deleted points in (defaults to null) 01055 Returns: TRUE if successful, FALSE if not 01056 Purpose: removes points from the Pressure Sampler list between the provided distances 01057 SeeAlso: - 01058 01059 ********************************************************************************************/ 01060 01061 BOOL BrushAttrValue::DeletePressurePoints(MILLIPOINT StartDistance, MILLIPOINT EndDistance, 01062 SampleArray* pRemovedPoints) 01063 { 01064 if (StartDistance <0 || EndDistance < 0 || EndDistance <= StartDistance) 01065 { 01066 ERROR3("Invalid inputs to BrushAttrValue::DeletePressureingPoints"); 01067 return FALSE; 01068 } 01069 01070 if (m_pPressureSampler == NULL) 01071 return FALSE; 01072 01073 // find out what indexes correspond to our distances 01074 INT32 StartIndex = m_pPressureSampler->GetInternalIndexFromDistance(StartDistance); 01075 INT32 EndIndex = m_pPressureSampler->GetInternalIndexFromDistance(EndDistance); 01076 01077 if (StartIndex == -1 || EndIndex == -1) 01078 { 01079 ERROR3("Attempting to remove from over the end of the array"); 01080 return FALSE; 01081 } 01082 INT32 NumPoints = EndIndex - StartIndex; 01083 if (NumPoints == 0) 01084 return TRUE; // ours not to reason why... 01085 01086 // set the size of the sample array 01087 if (pRemovedPoints != NULL) 01088 pRemovedPoints->resize( NumPoints ); 01089 01090 // ask the sampler to do its thing 01091 return m_pPressureSampler->RemoveData(StartIndex, EndIndex, pRemovedPoints); 01092 } 01093 01094 01095 /******************************************************************************************** 01096 01097 > bool BrushAttrValue::DeletePressurePoints(MILLIPOINT Start, UINT32 NumPoints, PressureList* pList = NULL) 01098 01099 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01100 Created: 6/10/99 01101 Inputs: StartIndex - the index where we want to start deleting 01102 NumPoints - the number to delete 01103 pRemovedPoints - an array to put the deleted points in (defaults to null) 01104 Returns: TRUE if successful, FALSE if not 01105 Purpose: removes points from the Pressure Sampler between the provided distances 01106 SeeAlso: - 01107 01108 ********************************************************************************************/ 01109 01110 BOOL BrushAttrValue::DeletePressurePoints(UINT32 StartIndex, size_t NumPoints, 01111 SampleArray* pRemovedPoints) 01112 { 01113 if (NumPoints < 1) 01114 { 01115 TRACEUSER( "Diccon", _T("Num points = %d in DeletePressurePoints\n"), NumPoints); 01116 return FALSE; 01117 } 01118 01119 if (m_pPressureSampler == NULL) 01120 return FALSE; 01121 01122 UINT32 EndIndex = StartIndex + NumPoints; 01123 01124 // check that this doesn't overrun the array 01125 if (EndIndex > m_pPressureSampler->GetNumItems()) 01126 { 01127 ERROR3("Attempting to remove over the end of the array"); 01128 return FALSE; 01129 } 01130 01131 // set the size of the sample array 01132 if (pRemovedPoints != NULL) 01133 pRemovedPoints->resize( NumPoints ); 01134 01135 // set the retrieval rate 01136 m_pPressureSampler->SetRetrievalSampleRate(1.0); 01137 01138 // ask the sampler to do its thing 01139 return m_pPressureSampler->RemoveData(StartIndex, EndIndex, pRemovedPoints); 01140 01141 } 01142 01143 01144 /******************************************************************************************** 01145 01146 > bool Bru5shAttrValue::AddPressurePoints(PressureList* pNewPoints, MILLIPOINT Start) 01147 01148 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01149 Created: 6/10/99 01150 Inputs: pNewPoints - the points to add 01151 Start - distance from which to add the points, note that if this is negative then 01152 all the new points will be added to the very start 01153 01154 Returns: TRUE if successful, FALSE if not 01155 Purpose: inserts the list of points after the distance given 01156 SeeAlso: - 01157 01158 ********************************************************************************************/ 01159 01160 BOOL BrushAttrValue::AddPressurePoints(CSampleData* pNewPoints, MILLIPOINT StartDistance) 01161 { 01162 // couple of checks 01163 if (pNewPoints == NULL) 01164 { 01165 ERROR3("Invalid inputs to BrushAttrValue::AddPressurePoints"); 01166 return FALSE; 01167 } 01168 01169 if (m_pPressureSampler == NULL) 01170 return FALSE; 01171 01172 // find out where we're inserting 01173 INT32 StartIndex = m_pPressureSampler->GetInternalIndexFromDistance(StartDistance); 01174 if (StartIndex == -1) 01175 { 01176 ERROR3("Attempting to insert over the end of the array in BrushAttrValue::AddPressurePoints"); 01177 return FALSE; 01178 } 01179 01180 // ask the sampler to insert for us 01181 return m_pPressureSampler->InsertNewData((UINT32)StartIndex, pNewPoints); 01182 } 01183 01184 01185 /******************************************************************************************** 01186 01187 > BOOL BrushAttrValue::AddPressurePoints(PressureList* pNewPoints, UINT32 StartIndex) 01188 01189 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01190 Created: 6/10/99 01191 Inputs: pNewPoints - the points to add 01192 StartIndex - the TimeStampList::iterator in the list where we want to insert the new points 01193 01194 Returns: TRUE if successful, FALSE if not 01195 Purpose: inserts the list of points after the index given 01196 SeeAlso: - 01197 01198 ********************************************************************************************/ 01199 01200 BOOL BrushAttrValue::AddPressurePoints(CSampleData* pNewPoints, UINT32 StartIndex) 01201 { 01202 if (pNewPoints == NULL) 01203 { 01204 ERROR3("Invalid inputs to BrushAttrValue::AddPressurePoints"); 01205 return FALSE; 01206 } 01207 01208 if (m_pPressureSampler == NULL) 01209 return FALSE; 01210 01211 if (StartIndex > m_pPressureSampler->GetNumItems()) 01212 { 01213 ERROR3("Attempting to insert over the end of the array in BrushAttrValue::AddPressurePoints"); 01214 return FALSE; 01215 } 01216 01217 return m_pPressureSampler->InsertNewData(StartIndex, pNewPoints); 01218 } 01219 01220 01221 01222 01223 /******************************************************************************************** 01224 01225 > void BrushAttrValue::SetPressureUpdateType(ListUpdateType Update) 01226 01227 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01228 Created: 6/10/99 01229 Inputs: Update can be: 01230 UPDATE_NONE, 01231 UPDATE_LIST - means that points have been added or removed to the Pressureing list 01232 UPDATE_PROPORTION - means that the underlying path has changed but our list has not 01233 UPDATE_TimeStampList::iterator - means (usually) that the path has been reversed but our points are the same 01234 UPDATE_LISTANDTimeStampList::iterator - take a guess 01235 Returns: - 01236 Purpose: These flags determine what will happen in the NodePathUpdate function which is called 01237 after the freehand/brush or bezier tool is used to edit a brushed nodepath 01238 SeeAlso: - 01239 01240 ********************************************************************************************/ 01241 01242 void BrushAttrValue::SetPressureUpdateType(ListUpdateType Update) 01243 { 01244 m_PressureUpdateType = Update; 01245 } 01246 01247 01248 /******************************************************************************************** 01249 01250 > ListUpdateType GetPressureUpdateType() 01251 01252 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01253 Created: 6/10/99 01254 Inputs: - 01255 Returns: the member, described above 01256 Purpose: As above 01257 SeeAlso: - 01258 01259 ********************************************************************************************/ 01260 01261 ListUpdateType BrushAttrValue::GetPressureUpdateType() 01262 { 01263 return m_PressureUpdateType; 01264 } 01265 01266 01267 01268 /******************************************************************************************** 01269 01270 01271 > BOOL BrushAttrValue::CopyPressureList() 01272 01273 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01274 Created: 22/5/2000 01275 Inputs: - 01276 Returns: pointer to a newly allocated pressure cache, or NULL if it fails 01277 Purpose: To make a carbon copy of our pressure cache and all the items in it. To be used 01278 as part of the operator= sequence. 01279 01280 SeeAlso: BrushAttrValue::operator= 01281 ********************************************************************************************/ 01282 01283 CDistanceSampler* BrushAttrValue::CopyPressureCache() 01284 { 01285 if (m_pPressureSampler == NULL) 01286 return NULL; 01287 01288 return m_pPressureSampler->MakeCopy(); 01289 } 01290 01291 01292 01293 /******************************************************************************************** 01294 01295 > INT32 BrushAttrValue::GetPressureListIndexAtDistance(MILLIPOINT Distance) 01296 01297 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01298 Created: 23/5/2000 01299 Inputs: Distance - the distance along the path that we wish to find the pressure 01300 list index for 01301 01302 Returns: the index into our pressure list, or -1 for an error 01303 Purpose: Finds the pressure list index corresponding to the brush object that would 01304 appear at Distance along the brushed path. Or rather asks the processor to 01305 do it. 01306 SeeAlso: PathProcessorBrush::GetObjectCountToDistance 01307 01308 ********************************************************************************************/ 01309 01310 INT32 BrushAttrValue::GetPressureListIndexAtDistance(MILLIPOINT Distance) 01311 { 01312 // some safety checks 01313 if (m_pPressureSampler == NULL) 01314 return -1; 01315 01316 if (Distance < 0 ) 01317 return -1; 01318 01319 if (m_pProcessor == NULL) 01320 return -1; 01321 01322 INT32 Index = m_pPressureSampler->GetInternalIndexFromDistance(Distance); 01323 01324 return Index; 01325 } 01326 01327 01328 /*------------------------------------------------------------------------------------------ 01329 ------------Time Stamp List functions--------------------------------------------------------- 01330 --------------------------------------------------------------------------------------------*/ 01331 01332 01333 /******************************************************************************************** 01334 01335 > void BrushAttrValue::SetTimeStampList(TimeStampList* pList) 01336 01337 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01338 Created: 13/12/99 01339 01340 Inputs: pointer to list to use as cache 01341 01342 Purpose: sets the timestamp cache member variable 01343 ********************************************************************************************/ 01344 01345 void BrushAttrValue::SetTimeStampList(TimeStampList* pList) 01346 { 01347 m_pTimeStampList = pList; 01348 } 01349 01350 01351 /******************************************************************************************** 01352 01353 > BOOL BrushAttrValue::IsTimeStamping 01354 01355 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01356 Created: 13/12/99 01357 01358 Inputs: - 01359 Returns: TRUE if we are using the timestamp cache, FALSE otherwise (we never use both) 01360 Purpose: as above 01361 ********************************************************************************************/ 01362 01363 BOOL BrushAttrValue::IsTimeStamping() 01364 { 01365 return (m_pTimeStampList != NULL); 01366 } 01367 01368 01369 /******************************************************************************************** 01370 01371 > void BrushAttrValue::CalculateProportionalDistances(MILLIPOINT PathLength) 01372 01373 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01374 Created: 13/12/99 01375 Inputs: The length of the path to which this attribute applies 01376 Returns: - 01377 Purpose: Only use when we are utilising the path stamping cache. This fn. proceeds 01378 through the list and works out the proportional distance along the path for 01379 each object. 01380 See Also: TimeStampBrushPoint 01381 ********************************************************************************************/ 01382 01383 void BrushAttrValue::CalculateProportionalDistances(MILLIPOINT PathLength) 01384 { 01385 if (m_pTimeStampList == NULL || PathLength <= 0) 01386 { 01387 ERROR3("Error in calculating proportional distance"); 01388 return; 01389 } 01390 01391 TimeStampList::iterator ListPos = m_pTimeStampList->begin(); 01392 TimeStampList::iterator LastPos = ListPos; 01393 TimeStampBrushPoint TSBP; 01394 while( ListPos != m_pTimeStampList->end() ) 01395 { 01396 LastPos = ListPos; 01397 TSBP = *ListPos; ++ListPos; 01398 TSBP.WorkOutProportion( PathLength ); 01399 *LastPos = TSBP; 01400 } 01401 } 01402 01403 01404 /******************************************************************************************** 01405 01406 > void BrushAttrValue::FlushTimeStampCache() 01407 01408 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01409 Created: 13/12/99 01410 Inputs: - 01411 Returns: - 01412 Purpose: deletes the timestamp cache if we have one 01413 ********************************************************************************************/ 01414 01415 void BrushAttrValue::FlushTimeStampCache() 01416 { 01417 if (m_pTimeStampList != NULL) 01418 { 01419 m_pTimeStampList->clear(); 01420 delete m_pTimeStampList; 01421 m_pTimeStampList = NULL; 01422 } 01423 } 01424 01425 01426 /******************************************************************************************** 01427 01428 > void BrushAttrValue::TransformTimeStamp(TransformBase& Transform) 01429 01430 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01431 Created: 6/10/99 01432 Inputs: the transformation to perform 01433 Returns: - 01434 Purpose: transforms all the points in the timestamping cache 01435 SeeAlso: - 01436 01437 ********************************************************************************************/ 01438 01439 void BrushAttrValue::TransformTimeStampList(TransformBase& Trans) 01440 { 01441 if (m_pTimeStampList == NULL) 01442 return; 01443 01444 // pretty straightforward, just get the points out of the list and transform them 01445 TimeStampBrushPoint TSBP; 01446 TimeStampList::iterator ListPos = m_pTimeStampList->begin(); 01447 01448 while( ListPos != m_pTimeStampList->end() ) 01449 { 01450 TimeStampList::iterator OldPos = ListPos; 01451 TSBP = *ListPos; ++ListPos; 01452 Trans.Transform(&TSBP.m_Point, 1); 01453 *OldPos = TSBP; 01454 } 01455 01456 01457 01458 } 01459 01460 01461 /******************************************************************************************** 01462 01463 > bool BrushAttrValue::DeleteTimeStampPoints(MILLIPOINT Start, MILLIPOINT End) 01464 01465 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01466 Created: 6/10/99 01467 Inputs: Start - distance from which to delete 01468 End - the distance to stop deleting at 01469 Returns: TRUE if successful, FALSE if not 01470 Purpose: removes points from the timestamping list between the provided distances 01471 SeeAlso: - 01472 01473 ********************************************************************************************/ 01474 01475 BOOL BrushAttrValue::DeleteTimeStampPoints(MILLIPOINT StartDistance, MILLIPOINT EndDistance, 01476 TimeStampList* pRemovedPoints) 01477 { 01478 if (StartDistance <0 || EndDistance < 0 || EndDistance <= StartDistance) 01479 { 01480 ERROR3("Invalid inputs to BrushAttrValue::DeleteTimeStampingPoints"); 01481 return FALSE; 01482 } 01483 01484 if (m_pTimeStampList == NULL) 01485 return FALSE; 01486 01487 TimeStampList::iterator ListPos = m_pTimeStampList->begin(); 01488 TimeStampList::iterator LastPos = ListPos; 01489 TimeStampBrushPoint TSBP; 01490 MILLIPOINT Distance = 0; 01491 INT32 count = 0; 01492 INT32 removecount = 0; 01493 TRACEUSER( "Diccon", _T("Deleting from %d, to %d\n"), StartDistance, EndDistance ); 01494 TRACEUSER( "Diccon", _T("Num points pre-remove = %d\n"), m_pTimeStampList->size() ); 01495 while( ListPos != m_pTimeStampList->end() ) 01496 { 01497 LastPos = ListPos; 01498 TSBP = *ListPos; ++ListPos; 01499 Distance = TSBP.m_Distance; 01500 //TRACEUSER("Diccon", _T("Count %d, Distance = %d\n"), count, Distance); 01501 if (Distance >= StartDistance && Distance <= EndDistance) 01502 { 01503 // if we're sending the removed points back, add this one to the list 01504 if (pRemovedPoints != NULL) 01505 pRemovedPoints->push_back( TSBP ); 01506 01507 // remove it from the main list 01508 m_pTimeStampList->erase( LastPos ); 01509 removecount++; 01510 TRACEUSER("Diccon", _T("Removing point %d\n"), count); 01511 } 01512 count++; 01513 } 01514 TRACEUSER("Diccon", _T("Removed %d points\n"), removecount); 01515 01516 return TRUE; 01517 } 01518 01519 01520 /******************************************************************************************** 01521 01522 > bool BrushAttrValue::DeleteTimeStampPoints(MILLIPOINT Start, UINT32 NumPoints, TimeStampList* pList = NULL) 01523 01524 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01525 Created: 6/10/99 01526 Inputs: Start - distance from which to delete 01527 NumPoints - the number to delete 01528 pList - a list to put the deleted points in (defaults to null) 01529 Returns: TRUE if successful, FALSE if not 01530 Purpose: removes points from the timestamping list between the provided distances 01531 SeeAlso: - 01532 01533 ********************************************************************************************/ 01534 01535 BOOL BrushAttrValue::DeleteTimeStampPoints(MILLIPOINT StartDistance, UINT32 NumPoints, 01536 TimeStampList* pRemovedPoints) 01537 { 01538 if (StartDistance <0 || NumPoints < 1) 01539 { 01540 ERROR3("Invalid inputs to BrushAttrValue::DeleteTimeStampingPoints"); 01541 return FALSE; 01542 } 01543 01544 if (m_pTimeStampList == NULL) 01545 return FALSE; 01546 01547 TimeStampList::iterator ListPos = m_pTimeStampList->begin(); 01548 TimeStampList::iterator LastPos = ListPos; 01549 TimeStampBrushPoint TSBP; 01550 MILLIPOINT Distance = 0; 01551 UINT32 count = 0; 01552 NumPoints --; 01553 while( ListPos != m_pTimeStampList->end() ) 01554 { 01555 LastPos = ListPos; 01556 TSBP = *ListPos; ++ListPos; 01557 Distance = TSBP.m_Distance; 01558 count++; 01559 if (Distance >= StartDistance) 01560 { 01561 01562 TimeStampList::iterator RemPos = LastPos; 01563 while( NumPoints && LastPos != m_pTimeStampList->end() ) 01564 { 01565 TRACEUSER("Diccon", _T("Removing point %d\n"), count); 01566 if (count == m_pTimeStampList->size()) 01567 { 01568 //INT32 i = 1; // why is this here AMB 2006-01-31 01569 } 01570 // if we're sending the removed points back, add this one to the list 01571 if (pRemovedPoints != NULL) 01572 pRemovedPoints->push_back(TSBP); 01573 RemPos = LastPos; 01574 TSBP = *LastPos; ++LastPos; 01575 TimeStampBrushPoint Test = *RemPos; 01576 // TRACEUSER("Diccon", _T("Removing point at %d\n"), Test.m_Distance); 01577 // remove it from the main list 01578 m_pTimeStampList->erase( RemPos ); 01579 NumPoints--; 01580 count++; 01581 } 01582 01583 } 01584 if (NumPoints <= 0 || LastPos == m_pTimeStampList->end()) 01585 break; 01586 } 01587 return TRUE; 01588 } 01589 01590 /******************************************************************************************** 01591 01592 > bool Bru5shAttrValue::AddTimeStampPoints(TimeStampList* pNewPoints, MILLIPOINT Start) 01593 01594 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01595 Created: 6/10/99 01596 Inputs: pNewPoints - the points to add 01597 Start - distance from which to add the points, note that if this is negative then 01598 all the new points will be added to the very start 01599 01600 Returns: TRUE if successful, FALSE if not 01601 Purpose: inserts the list of points after the distance given 01602 SeeAlso: - 01603 01604 ********************************************************************************************/ 01605 01606 BOOL BrushAttrValue::AddTimeStampPoints(TimeStampList* pNewPoints, MILLIPOINT StartDistance) 01607 { 01608 if (pNewPoints == NULL) 01609 { 01610 ERROR3("Invalid inputs to BrushAttrValue::DeleteTimeStampingPoints"); 01611 return FALSE; 01612 } 01613 01614 if (m_pTimeStampList == NULL) 01615 return FALSE; 01616 01617 TimeStampList::iterator ListPos = m_pTimeStampList->begin(); 01618 TimeStampList::iterator LastPos = ListPos; 01619 01620 TimeStampBrushPoint TSBP; 01621 TimeStampBrushPoint NewPoint; 01622 MILLIPOINT Distance; 01623 01624 TRACEUSER("Diccon", _T("Num points pre-add = %d\n"), m_pTimeStampList->size()); 01625 01626 // first find the TimeStampList::iterator at which we want to insert the new points 01627 if (StartDistance > 0) 01628 { 01629 while( ListPos != m_pTimeStampList->end() ) 01630 { 01631 LastPos = ListPos; 01632 TSBP = *ListPos; ++ListPos; 01633 Distance = TSBP.m_Distance; 01634 if (Distance > StartDistance) 01635 break; 01636 01637 } 01638 } 01639 else 01640 LastPos = m_pTimeStampList->begin(); 01641 01642 TimeStampList::iterator NewListPos = pNewPoints->begin(); 01643 01644 while( NewListPos != m_pTimeStampList->end() ) 01645 { 01646 // get the point from the new list 01647 NewPoint = *NewListPos; ++NewListPos; 01648 01649 // insert it into the old list, recall that LastPos stores the element just before 01650 // StartDistance was exceeded 01651 if (StartDistance > 0) 01652 { 01653 m_pTimeStampList->insert( LastPos, NewPoint ); 01654 // increment our list position 01655 ++LastPos; 01656 } 01657 else 01658 m_pTimeStampList->push_front( NewPoint ); 01659 } 01660 01661 TRACEUSER("Diccon", _T("Ended with %d points\n"), m_pTimeStampList->size()); 01662 01663 return TRUE; 01664 } 01665 01666 /******************************************************************************************** 01667 01668 > bool BrushAttrValue::RecalculateTimeStampList(Path* pPath) 01669 01670 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01671 Created: 6/10/99 01672 Inputs: pPath - the path of the nodepath of this timestamped brush 01673 01674 01675 Returns: TRUE if successful, FALSE if not 01676 Purpose: If time stamped lists are edited they can get out of shape, call this function 01677 to make sure the list is all in order. Note that it can be a bit slow 01678 Extra note, depending on exactly how the path was edited our update method differs. 01679 RepositionPointsByProportion is used when the path was edited by no points were 01680 added or removed from the timestamping list. If points were added then the other 01681 method should be used. 01682 SeeAlso: - 01683 01684 ********************************************************************************************/ 01685 01686 BOOL BrushAttrValue::RecalculateTimeStampList(Path* pPath) 01687 { 01688 if (m_pTimeStampList == NULL) 01689 return TRUE; 01690 if (pPath == NULL) 01691 return FALSE; 01692 BOOL Retval = TRUE; 01693 switch (m_TimeStampUpdateType) 01694 { 01695 case UPDATE_NONE: 01696 break; 01697 case UPDATE_PROPORTION: 01698 if (!RepositionPointsByProportion(pPath)) 01699 Retval = FALSE; 01700 break; 01701 case UPDATE_LIST: 01702 if (!RecalculateDistances(pPath)) 01703 { 01704 Retval = FALSE; 01705 break; 01706 } 01707 if (!SortTimeStampingList()) 01708 { 01709 Retval = FALSE; 01710 break; 01711 } 01712 // if (!RecalculateTangents(pPath)) 01713 // { 01714 // Retval = FALSE; 01715 // break; 01716 // } 01717 break; 01718 case UPDATE_POSITION: 01719 if (!RepositionPointsByPosition(pPath)) 01720 Retval = FALSE; 01721 break; 01722 case UPDATE_LISTANDPOSITION: 01723 if (!RepositionPointsByPosition(pPath)) 01724 { 01725 Retval = FALSE; 01726 break; 01727 } 01728 if (!RecalculateDistances(pPath)) 01729 { 01730 Retval = FALSE; 01731 break; 01732 } 01733 if (!SortTimeStampingList()) 01734 { 01735 Retval = FALSE; 01736 break; 01737 } 01738 // if (!RecalculateTangents(pPath)) 01739 // { 01740 // Retval = FALSE; 01741 // break; 01742 // } 01743 break; 01744 } 01745 01746 // if (!GetRidOfCrapFromList(pPath)) 01747 // return FALSE; 01748 return Retval; 01749 } 01750 01751 01752 01753 /******************************************************************************************** 01754 01755 > bool BrushAttrValue::RecalculateDistances(Path* pPath) 01756 01757 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01758 Created: 6/10/99 01759 Inputs: pPath - the path of the nodepath of this timestamped brush 01760 01761 01762 Returns: TRUE if successful, FALSE if not 01763 Purpose: for a timestamped brush, this fn. goes along the path and recalculates 01764 the distances of the coordinates along the line. 01765 SeeAlso: - 01766 01767 ********************************************************************************************/ 01768 01769 BOOL BrushAttrValue::RecalculateDistances(Path* pPath) 01770 { 01771 if (pPath == NULL || m_pTimeStampList == NULL) 01772 { 01773 ERROR3("Input pointers are NULL"); 01774 return FALSE; 01775 } 01776 01777 double PathLength = (MILLIPOINT)pPath->GetPathLength(); 01778 MILLIPOINT Distance; 01779 01780 TimeStampList::iterator ListPos = m_pTimeStampList->begin(); 01781 TimeStampList::iterator LastPos; 01782 TimeStampBrushPoint TSBPoint; 01783 01784 while( ListPos != m_pTimeStampList->end() ) 01785 { 01786 LastPos = ListPos; 01787 TSBPoint = *ListPos; ++ListPos; 01788 // get the distance along the path 01789 if (pPath->GetDistanceToPoint(TSBPoint.m_Point, &Distance)) 01790 { 01791 TSBPoint.m_Distance = Distance; 01792 TSBPoint.m_Proportion = (double)TSBPoint.m_Distance / PathLength; 01793 // TRACEUSER("Diccon", _T("New Prop: %f\n"), TSBPoint.m_Proportion); 01794 *LastPos = TSBPoint; 01795 } 01796 else 01797 TRACEUSER("Diccon", _T("Point %d, %d, not found in line\n"), TSBPoint.m_Point.x, TSBPoint.m_Point.y); 01798 } 01799 01800 return TRUE; 01801 } 01802 01803 /******************************************************************************************** 01804 01805 > bool BrushAttrValue::RecalculateTangents(Path* pPath) 01806 01807 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01808 Created: 6/10/99 01809 Inputs: pPath - the path of the nodepath of this timestamped brush 01810 01811 01812 Returns: TRUE if successful, FALSE if not 01813 Purpose: for a timestamped brush, this fn. goes along the path and recalculates 01814 the tangents of the coordinates along the line. 01815 SeeAlso: - 01816 01817 ********************************************************************************************/ 01818 01819 BOOL BrushAttrValue::RecalculateTangents(Path* pPath) 01820 { 01821 if (pPath == NULL || m_pTimeStampList == NULL) 01822 { 01823 ERROR3("Input pointers are NULL"); 01824 return FALSE; 01825 } 01826 01827 // double PathLength = (MILLIPOINT)pPath->GetPathLength(); 01828 01829 double Tangent; 01830 DocCoord DummyCoord; 01831 01832 TimeStampList::iterator ListPos = m_pTimeStampList->begin(); 01833 TimeStampBrushPoint TSBPoint; 01834 01835 while( ListPos != m_pTimeStampList->end() ) 01836 { 01837 TSBPoint = *ListPos; ++ ListPos; 01838 // we need to use GetPointAtDistance to retrieve the tangent 01839 if (pPath->GetPointAtDistance(TSBPoint.m_Distance, &DummyCoord, &Tangent)) 01840 TSBPoint.m_Tangent = Tangent; 01841 01842 } 01843 return TRUE; 01844 } 01845 01846 01847 /******************************************************************************************** 01848 01849 > bool BrushAttrValue::SortTimeStampingList() 01850 01851 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01852 Created: 6/10/99 01853 Inputs: - 01854 Returns: TRUE if successful, FALSE if not 01855 Purpose: The TimeStamping points lists can become rather disorderly if you edit them a 01856 lot. This function sorts them by order of distance using quicksort. Make sure you call 01857 RecalculateDistances() first. 01858 SeeAlso: - 01859 01860 ********************************************************************************************/ 01861 01862 BOOL BrushAttrValue::SortTimeStampingList() 01863 { 01864 if (m_pTimeStampList == NULL) 01865 return FALSE; 01866 01867 // first we need to copy the elements out of the list into an array 01868 size_t NumElements = m_pTimeStampList->size(); 01869 01870 // make the array 01871 TimeStampBrushPoint* pPointArray = new TimeStampBrushPoint[NumElements]; 01872 if (pPointArray == NULL) 01873 return FALSE; 01874 01875 TimeStampList::iterator ListPos = m_pTimeStampList->begin(); 01876 01877 TimeStampBrushPoint PointInfo; 01878 UINT32 Counter = 0; 01879 01880 // copy the points into the array 01881 while( ListPos != m_pTimeStampList->end() ) 01882 { 01883 PointInfo = *ListPos; ++ListPos; 01884 01885 pPointArray[Counter++] = PointInfo; 01886 } 01887 01888 // quick sort 'em 01889 qsort((void*)pPointArray, NumElements, sizeof(TimeStampBrushPoint), TimeStampBrushPoint::ComparePointInfo); 01890 01891 01892 // now put 'em back in the list 01893 m_pTimeStampList->clear(); 01894 01895 for (unsigned i = 0; i < NumElements; i++) 01896 { 01897 m_pTimeStampList->push_back(pPointArray[i]); 01898 01899 // TRACEUSER("Diccon", _T("Sorted distance = %d\n"), pPointArray[i].m_Distance); 01900 } 01901 01902 delete pPointArray; 01903 return TRUE; 01904 } 01905 01906 01907 /******************************************************************************************** 01908 01909 > bool BrushAttrValue::GetRidOfCrapFromList(Path* pPath) 01910 01911 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01912 Created: 6/10/99 01913 Inputs: pPath = the path that this timestamped brush supposedly follows 01914 Returns: TRUE if successful, FALSE if not 01915 Purpose: The TimeStamping points lists can become rather disorderly if you edit them a 01916 lot. My woefully inadequate undo/redo actions for editing them can still leave 01917 some rogue points hanging around. This function proceeds through the list 01918 removing any points that are not on the path. 01919 SeeAlso: - 01920 01921 ********************************************************************************************/ 01922 01923 BOOL BrushAttrValue::GetRidOfCrapFromList(Path* pPath) 01924 { 01925 if (m_pTimeStampList == NULL || pPath == NULL) 01926 return FALSE; 01927 01928 TimeStampBrushPoint Point; 01929 TimeStampList::iterator ListPos = m_pTimeStampList->begin(); 01930 TimeStampList::iterator LastPos = ListPos; 01931 MILLIPOINT Distance; 01932 01933 while( ListPos != m_pTimeStampList->end() ) 01934 { 01935 LastPos = ListPos; 01936 Point = *ListPos; ++ListPos; 01937 if (!pPath->GetDistanceToPoint(Point.m_Point, &Distance)) 01938 { 01939 m_pTimeStampList->erase( LastPos ); 01940 TRACEUSER("Diccon", _T("Removing point at %d\n"), Point.m_Distance); 01941 } 01942 } 01943 return TRUE; 01944 } 01945 01946 01947 /******************************************************************************************** 01948 01949 > bool BrushAttrValue::RepositionPointsByProportion(Path* pPath) 01950 01951 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01952 Created: 6/10/99 01953 Inputs: pPath = the path that this timestamped brush supposedly follows 01954 Returns: TRUE if successful, FALSE if not 01955 Purpose: This function moves all the points in the timestamping list to their proportional 01956 TimeStampList::iterator along pPath. 01957 01958 SeeAlso: - 01959 01960 ********************************************************************************************/ 01961 01962 BOOL BrushAttrValue::RepositionPointsByProportion(Path* pPath) 01963 { 01964 if (m_pTimeStampList == NULL || pPath == NULL) 01965 return FALSE; 01966 01967 TimeStampBrushPoint Point; 01968 TimeStampList::iterator ListPos = m_pTimeStampList->begin(); 01969 TimeStampList::iterator LastPos = ListPos; 01970 01971 double PathLength = pPath->GetPathLength(); 01972 MILLIPOINT PointDistance = 0; 01973 double Tangent = 0; 01974 DocCoord NewPosition; 01975 UINT32 Counter = 0; 01976 01977 while( ListPos != m_pTimeStampList->end() ) 01978 { 01979 LastPos = ListPos; 01980 Point = *ListPos; ++ListPos; 01981 // work out the new distance along the given path with the existing proportion 01982 PointDistance = (MILLIPOINT)(Point.m_Proportion * PathLength); 01983 if (PointDistance >= 0) 01984 { 01985 // get the coordinate and tangent for this distance 01986 if (pPath->GetPointAtDistance(PointDistance, &NewPosition, &Tangent)) 01987 { 01988 // assign the new data to the point 01989 Point.m_Point = NewPosition; 01990 Point.m_Tangent = Tangent; 01991 Point.m_Distance = PointDistance; 01992 // put the point back in the list 01993 *LastPos = Point; 01994 } 01995 else 01996 { 01997 TRACEUSER("Diccon", _T("Failed to find point on line with distance %d\n"), PointDistance); 01998 } 01999 } 02000 else 02001 { 02002 TRACEUSER("Diccon", _T("Negative path distance at point %d\n"), Counter); 02003 } 02004 Counter++; 02005 } 02006 return TRUE; 02007 } 02008 02009 02010 /******************************************************************************************** 02011 02012 > bool BrushAttrValue::RepositionPointsByPosition(Path* pPath) 02013 02014 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 02015 Created: 6/10/99 02016 Inputs: pPath = the path that this timestamped brush supposedly follows 02017 Returns: TRUE if successful, FALSE if not 02018 Purpose: This function assumes that all the points in the timestamping list are in the 02019 path but that their distance and proportion information is incorrect. Therefore 02020 it runs through the list and finds the correct distance and proportion. 02021 This is useful for those times when the path editing functions conveniently decide to 02022 go and reverse the paths because they feel like it. 02023 02024 SeeAlso: - 02025 02026 ********************************************************************************************/ 02027 02028 BOOL BrushAttrValue::RepositionPointsByPosition(Path* pPath) 02029 { 02030 if (m_pTimeStampList == NULL || pPath == NULL) 02031 return FALSE; 02032 02033 TimeStampBrushPoint Point; 02034 TimeStampList::iterator ListPos = m_pTimeStampList->begin(); 02035 TimeStampList::iterator LastPos = ListPos; 02036 02037 double PathLength = pPath->GetPathLength(); 02038 MILLIPOINT PointDistance = 0; 02039 // double Tangent = 0; 02040 DocCoord NewPosition; 02041 UINT32 Counter = 0; 02042 02043 while( ListPos != m_pTimeStampList->end() ) 02044 { 02045 LastPos = ListPos; 02046 Point = *ListPos; ++ListPos; 02047 02048 if (pPath->GetDistanceToPoint(Point.m_Point, &PointDistance)) 02049 { 02050 Point.m_Distance = PointDistance; 02051 Point.m_Proportion = (double)PointDistance / PathLength; 02052 // put the point back in the list 02053 *LastPos = Point; 02054 } 02055 else 02056 { 02057 TRACEUSER("Diccon", _T("Failed to get distance to point at %d\n"), Counter); 02058 } 02059 Counter++; 02060 } 02061 return TRUE; 02062 } 02063 02064 02065 02066 /******************************************************************************************** 02067 02068 > TimeStampList* BrushAttrValue::CopyTimeStampList() 02069 02070 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 02071 Created: 22/5/2000 02072 02073 Returns: Pointer to the new list, or null if it fails 02074 02075 Purpose: Copy our timestamping list 02076 02077 SeeAlso: operator= 02078 02079 ********************************************************************************************/ 02080 02081 TimeStampList* BrushAttrValue::CopyTimeStampList() 02082 { 02083 if (m_pTimeStampList == NULL) 02084 return NULL; 02085 // allocate a new list of our own 02086 TimeStampList* pCopyList = new TimeStampList; 02087 if (pCopyList != NULL) 02088 { 02089 TimeStampBrushPoint TBSP; 02090 TimeStampList::iterator ListPos = m_pTimeStampList->begin(); 02091 // copy the points 02092 while( ListPos != m_pTimeStampList->end() ) 02093 { 02094 TBSP = *ListPos; ++ListPos; 02095 pCopyList->push_back(TBSP); 02096 } 02097 } 02098 return pCopyList; 02099 } 02100 02101 /******************************************************************************************** 02102 02103 > virtual NodeAttribute *BrushAttrValue::MakeNode() 02104 02105 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 02106 Created: 13/12/99 02107 02108 Returns: Pointer to the new node, or NULL if out of memory. 02109 02110 Purpose: Make a new attribute node for this type of attr value - see base class 02111 02112 SeeAlso: AttributeValue::MakeNode 02113 02114 ********************************************************************************************/ 02115 02116 NodeAttribute *BrushAttrValue::MakeNode() 02117 { 02118 // Create new attribute node 02119 AttrBrushType *pAttr = new AttrBrushType; 02120 if (pAttr == NULL) 02121 return NULL; 02122 02123 // Copy attribute value (if any) into the new node. 02124 if (pAttr->GetAttributeValue() != NULL) 02125 pAttr->GetAttributeValue()->SimpleCopy(this); 02126 02127 02128 return(pAttr); 02129 } 02130 02131 02132 02133 /******************************************************************************************** 02134 02135 > virtual BOOL BrushAttrValue::IsDifferent(AttributeValue *pAttr) 02136 02137 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 02138 Created: 13/12/99 02139 02140 Purpose: Determines if this AttrValue is different from the given one 02141 02142 Errors: ERROR3 if the two attributes are not of the same type 02143 02144 SeeAlso: AttributeValue::IsDifferent 02145 02146 ********************************************************************************************/ 02147 02148 BOOL BrushAttrValue::IsDifferent(AttributeValue *pAttr) 02149 { 02150 ERROR3IF(!pAttr->IsKindOf(CC_RUNTIME_CLASS(BrushAttrValue)), 02151 "Different attribute types in BrushAttrValue::IsDifferent()"); 02152 02153 // Check they are NOT the same using the == operator 02154 return ( !(*((BrushAttrValue *)pAttr) == *this) ); 02155 } 02156 02157 02158 02159 /******************************************************************************************** 02160 02161 > virtual BrushAttrValue &BrushAttrValue::operator=(BrushAttrValue &Attrib) 02162 02163 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 02164 Created: 13/12/99 02165 02166 Inputs: Attrib - the attribute to copy 02167 02168 Purpose: Assignment operator 02169 02170 ********************************************************************************************/ 02171 02172 BrushAttrValue &BrushAttrValue::operator=(BrushAttrValue &Attrib) 02173 { 02174 // Get rid of our old processor (if any) 02175 if (m_pProcessor != NULL) 02176 delete m_pProcessor; 02177 m_pProcessor = NULL; 02178 02179 // Copy the other attr's processor. If this fails, we'll get back a NULL pointer, 02180 // and will simply "convert" into a simple no-stroke attribute. 02181 if (Attrib.m_pProcessor != NULL) 02182 m_pProcessor = Attrib.m_pProcessor->Clone(); 02183 02184 // if we're timestamping then we need to clone the list of points 02185 if (Attrib.IsTimeStamping()) 02186 m_pTimeStampList = CopyTimeStampList(); 02187 02188 // if we have pressure data then we need to copy that also 02189 m_pPressureSampler = Attrib.CopyPressureCache(); 02190 02191 return(*this); 02192 } 02193 02194 02195 02196 /******************************************************************************************** 02197 02198 > virtual INT32 BrushAttrValue::operator==(const BrushAttrValue &Attrib) 02199 02200 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 02201 Created: 13/12/99 02202 02203 Inputs: Attrib - the attribute to compare this attribute with 02204 02205 Returns: TRUE if the attributes are considered equal 02206 02207 Purpose: Comparison operator 02208 02209 ********************************************************************************************/ 02210 02211 INT32 BrushAttrValue::operator==(const BrushAttrValue &Attrib) 02212 { 02213 ERROR3IF(!Attrib.IsKindOf(CC_RUNTIME_CLASS(BrushAttrValue)), 02214 "Other attribute value isn't an BrushAttrValue"); 02215 02216 BrushAttrValue *Other = (BrushAttrValue *) &Attrib; 02217 02218 // two attributes can never have the same timestamp or pressure caches 02219 // If that is the case then why is it checking the points cache and 02220 // not the pressure cache!?? I'm changing this to check the "correct" cache 02221 // Gerry (21/11/05) 02222 02223 // The points cache doesn't get copied in the = operator so don't check it 02224 // if (GetCache() != NULL && GetCache()->GetCount() != 0) 02225 // return(FALSE); 02226 // if (Other->GetCache() != NULL && Other->GetCache()->GetCount != 0) 02227 // return(FALSE); 02228 02229 if (GetPressureCache() != NULL && GetPressureCache()->GetCount() != 0) 02230 return(FALSE); 02231 if (Other->GetPressureCache() != NULL && Other->GetPressureCache()->GetCount() != 0) 02232 return(FALSE); 02233 02234 if (m_pTimeStampList != NULL && m_pTimeStampList->size() != 0) 02235 return FALSE; 02236 if (Other->GetTimeStampList() != NULL && Other->GetTimeStampList()->size() != 0) 02237 return FALSE; 02238 02239 // Equal if they both have same processor (only applies if they are both NULL) 02240 if (m_pProcessor == Other->GetPathProcessor()) 02241 return(TRUE); 02242 02243 // Otherwise, if one of them is NULL, they can't be the same 02244 if (m_pProcessor == NULL || Other->GetPathProcessor() == NULL) 02245 return(FALSE); 02246 02247 // Finally, ask the processors if they are of the same type 02248 return(!m_pProcessor->IsDifferent(Other->GetPathProcessor())); 02249 } 02250 02251 02252 02253 /******************************************************************************************** 02254 02255 > void BrushAttrValue::SetPathProcessor(PathProcessorStroke *pNewProcessor) 02256 02257 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 02258 Created: 13/12/99 02259 02260 Inputs: pNewProcessor - The new PathProcessorStroke to be used by this attr. 02261 May be NULL, in which case it sets "old style lines" stroking mode. 02262 02263 Purpose: To set the path processor used by this object. The processor is now 02264 "owned" by this attribute, and will be auto-deleted upon destruction 02265 02266 ********************************************************************************************/ 02267 02268 void BrushAttrValue::SetPathProcessor(PathProcessorBrush *pNewProcessor) 02269 { 02270 if (m_pProcessor != NULL) 02271 delete m_pProcessor; 02272 m_pProcessor = pNewProcessor; 02273 02274 } 02275 02276 02277 /******************************************************************************************** 02278 02279 > void BrushAttrValue::ScaleToLineWidth(MILLIPOINT Width) 02280 02281 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 02282 Created: 13/12/99 02283 02284 Inputs: Width - the width to set 02285 02286 Purpose: asks the processor to scale to this line width. Note that the relevant flag 02287 must also be set 02288 02289 ********************************************************************************************/ 02290 02291 void BrushAttrValue::ScaleToLineWidth(MILLIPOINT Width) 02292 { 02293 if (m_pProcessor != NULL) 02294 { 02295 BOOL Pressure = m_pPressureSampler != NULL; 02296 m_pProcessor->ScaleToValue(Width, !Pressure); 02297 } 02298 } 02299 02300 /******************************************************************************************** 02301 02302 > BrushDefinition* BrushAttrValue::GetBrushDefintion() 02303 02304 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 02305 Created: 13/12/99 02306 02307 Inputs: - 02308 Outputs: - 02309 Returns: The brush definition used by our path processor, or null if we haven't been 02310 assigned one yet 02311 Purpose: as above 02312 02313 ********************************************************************************************/ 02314 02315 BrushDefinition* BrushAttrValue::GetBrushDefinition() 02316 { 02317 if (m_pProcessor != NULL) 02318 { 02319 return m_pProcessor->GetOurBrushDefinition(); 02320 } 02321 return NULL; 02322 } 02323 02324 02325 /******************************************************************************************** 02326 02327 > BrushHandle BrushAttrValue::GetBrushHandle() 02328 02329 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 02330 Created: 6/10/99 02331 Inputs: - 02332 Returns: handle of the brush definition used by this brush (can be NULL) 02333 Purpose: interface to the pathprocessor 02334 SeeAlso: - 02335 02336 ********************************************************************************************/ 02337 02338 BrushHandle BrushAttrValue::GetBrushHandle() 02339 { 02340 if (m_pProcessor == NULL) 02341 return BrushHandle_NoBrush; 02342 return m_pProcessor->GetBrushDefinitionHandle(); 02343 } 02344 02345 02346 /********************************************************************************************* 02347 02348 > DocRect BrushAttrValue::SetCachedRect(DocRect Rect) 02349 02350 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 02351 Created: 4/4/95 02352 Inputs: Rect - the bounding rect of this attribute 02353 Outputs: - 02354 Returns: 02355 Purpose: This is designed to be called by the path processor, which calculates the 02356 bounding rect of this attribute, arbitrarily setting bounding rects by other 02357 objects is not recommended 02358 **********************************************************************************************/ 02359 02360 void BrushAttrValue::SetCachedRect(DocRect Rect) 02361 { 02362 m_CachedBRect = Rect; 02363 } 02364 02365 02366 /********************************************************************************************* 02367 02368 > void BrushAttrValue::TransformCachedRect(TransformBase& Trans) 02369 02370 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 02371 Created: 4/4/95 02372 Inputs: Trans - the transformation to perform 02373 Outputs: - 02374 Returns: 02375 Purpose: Because it takes such a long time to calculate the bounding rect of a brushed object 02376 we prefer to calculate it once and then simply transform it. 02377 **********************************************************************************************/ 02378 02379 void BrushAttrValue::TransformCachedRect(TransformBase& Trans) 02380 { 02381 02382 02383 // if we have offsets from the path then simply transforming it doesn't work, 02384 // better to recalculate it 02385 if (m_pProcessor != NULL) 02386 { 02387 if (m_pProcessor->GetPathOffsetType() != OFFSET_NONE) 02388 m_CachedBRect.MakeEmpty(); 02389 } 02390 02391 if (!m_CachedBRect.IsEmpty()) 02392 { 02393 DocCoord Coords[4]; 02394 Coords[0].x = m_CachedBRect.lo.x; Coords[0].y = m_CachedBRect.lo.y; 02395 Coords[1].x = m_CachedBRect.hi.x; Coords[1].y = m_CachedBRect.lo.y; 02396 Coords[2].x = m_CachedBRect.hi.x; Coords[2].y = m_CachedBRect.hi.y; 02397 Coords[3].x = m_CachedBRect.lo.x; Coords[3].y = m_CachedBRect.hi.y; 02398 02399 Trans.Transform(Coords,4); 02400 02401 m_CachedBRect.lo.x = min(min(Coords[0].x,Coords[1].x), min(Coords[2].x,Coords[3].x)); 02402 m_CachedBRect.hi.x = max(max(Coords[0].x,Coords[1].x), max(Coords[2].x,Coords[3].x)); 02403 m_CachedBRect.lo.y = min(min(Coords[0].y,Coords[1].y), min(Coords[2].y,Coords[3].y)); 02404 m_CachedBRect.hi.y = max(max(Coords[0].y,Coords[1].y), max(Coords[2].y,Coords[3].y)); 02405 } 02406 02407 } 02408 /********************************************************************************************* 02409 02410 > DocRect NodeAttribute::GetAttrBoundingRect(NodeRenderableInk* pParent) 02411 02412 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 02413 Created: 4/4/95 02414 Inputs: pParent, the parent Ink node that this attribute will effect. 02415 Outputs: - 02416 Returns: The Bounding rect of the attribute (NULL rectangle is it doesn't have any). 02417 Purpose: Virtual function for determining the bounding rect of an attribute. It achieves this 02418 by giving a path to the path processor which tells it the bounding rect. 02419 02420 SeeAlso: NodeAttribute::EffectsParentBounds 02421 02422 **********************************************************************************************/ 02423 02424 DocRect BrushAttrValue::GetAttrBoundingRect(NodeRenderableInk* pParent, CCAttrMap* pAttribMap) 02425 { 02426 BrushDefinition* pBrushDef = GetBrushDefinition(); 02427 if (pBrushDef == NULL) 02428 return DocRect(0, 0, 0, 0); 02429 02430 // get the biggest BBox of the brush objects 02431 DocRect BRect = pBrushDef->GetLargestBoundingBox(); 02432 DocRect ReturnRect(0,0,0,0); 02433 02434 // if (!m_CachedBRect.IsEmpty()) 02435 // return m_CachedBRect; 02436 02437 02438 // get our path processor 02439 PathProcessorBrush* pPPB = GetPathProcessor(); 02440 if (pPPB == NULL) 02441 return DocRect(0,0,0,0); 02442 02443 if (m_pTimeStampList != NULL) 02444 { 02445 ReturnRect = pPPB->TimeStampBoundingBox(); 02446 m_CachedBRect = ReturnRect; 02447 return ReturnRect; 02448 } 02449 02450 if (pParent->IsNodePath()) 02451 { 02452 #ifdef NEWFASTBRUSHES 02453 if (pCachedBitmap) 02454 { 02455 ReturnRect = pCachedBitmap->GetBoundingRect (); 02456 } 02457 else 02458 { 02459 #endif 02460 // we have a special calculation for nodepaths, because we can use their path 02461 ReturnRect = pPPB->CalculateBoundingBox(&((NodePath*)pParent)->InkPath, pParent); 02462 #ifdef NEWFASTBRUSHES 02463 } 02464 #endif 02465 m_CachedBRect = ReturnRect; 02466 return ReturnRect; 02467 } 02468 02469 BecomeA TestBecomeAPath(BECOMEA_TEST, CC_RUNTIME_CLASS(NodePath)); 02470 if (pParent->CanBecomeA(&TestBecomeAPath)) 02471 { 02472 // we must be applied to some arbitrary shape. The thing is that we need to have 02473 // a path to pass to the PPB, so want to get a passback of all the paths in 02474 // the node 02475 02476 // we need to allocate a path 02477 Path* pPath = new Path; 02478 if (pPath != NULL && pPath->Initialise()) 02479 { 02480 PathBecomeA BecomeAPath(BECOMEA_PASSBACK, CC_RUNTIME_CLASS(NodePath), NULL, FALSE, pPath); 02481 if (pParent->DoBecomeA(&BecomeAPath)) 02482 { 02483 ReturnRect = pPPB->CalculateBoundingBox(pPath, pParent); 02484 } 02485 delete pPath; 02486 } 02487 m_CachedBRect = ReturnRect; 02488 return ReturnRect; 02489 } 02490 02491 if (pParent->IsATextChar()) 02492 { 02493 // text always has to be different doesn't it.. 02494 02495 // create a format region to keep an attribute stack 02496 FormatRegion FRegion; 02497 FormatRegion* pFormatRegion=&FRegion; 02498 02499 if (!pFormatRegion->Init(pParent)) 02500 { 02501 ERROR3("Failed to init format region"); 02502 return ReturnRect; 02503 } 02504 02505 pFormatRegion->SaveContext(); 02506 02507 NodePath* pNodePath = NULL; 02508 TextChar* pTextChar = (TextChar*)pParent; 02509 pTextChar->RenderChildAttrs(pFormatRegion); 02510 02511 // create a nodepath that we can use to give the the PPB 02512 if (pTextChar->CreateNodePath(&pNodePath, pFormatRegion)) 02513 { 02514 if (pNodePath != NULL) 02515 { 02516 ReturnRect = pPPB->CalculateBoundingBox(&(pNodePath->InkPath), pParent); 02517 delete pNodePath; 02518 } 02519 } 02520 pFormatRegion->RestoreContext(); 02521 02522 m_CachedBRect = ReturnRect; 02523 return ReturnRect; 02524 } 02525 02526 // Still nothing? Last resort time. 02527 if (ReturnRect.IsEmpty()) 02528 { 02529 ReturnRect = pParent->GetBoundingRect(TRUE); 02530 02531 double Scaling = 1.0; 02532 PathProcessorBrush* pPathProc = GetPathProcessor(); 02533 02534 if (pPathProc != NULL) 02535 Scaling = pPathProc->GetBrushScaling(); 02536 // hack it a bit just to make sure 02537 if (!ReturnRect.IsEmpty()) 02538 ReturnRect.Inflate((MILLIPOINT)((BRect.Width() / 2) * Scaling) , (MILLIPOINT)((BRect.Height() / 2) * Scaling)); 02539 02540 if (pPathProc->GetPathOffsetType() != OFFSET_NONE) 02541 ReturnRect.Inflate(pPathProc->GetPathOffsetValue(), pPathProc->GetPathOffsetValue()); 02542 } 02543 02544 m_CachedBRect = ReturnRect; 02545 return ReturnRect; 02546 } 02547 02548 02549 02550 02551 /******************************************************************************************** 02552 02553 > static void BrushAttrValue::RotateBounds(double Angle, DocRect* pBounds) 02554 02555 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 02556 Created: 8/2/2000 02557 Inputs: Bounds = the bounds to rotate 02558 Angle = the angle in degrees by which to rotate it by 02559 Outputs: Bounds is updated 02560 Returns: TRUE, unless you try to pass in a dud rect 02561 Purpose: The bounds are updated to contain the rotated version 02562 SeeAlso: - 02563 02564 ********************************************************************************************/ 02565 02566 BOOL BrushAttrValue::RotateBounds(double Angle, DocRect* pBounds, DocCoord* pCentre) 02567 { 02568 ERROR2IF(pBounds == NULL, FALSE, "DocRect is NULL"); 02569 // if (Angle != 0.0) 02570 { 02571 02572 DocCoord BBCentre; 02573 if (pCentre == NULL) 02574 BBCentre = pBounds->Centre(); 02575 else 02576 BBCentre = *pCentre; 02577 02578 DocCoord Coords[4]; 02579 Coords[0].x = pBounds->lo.x; Coords[0].y = pBounds->lo.y; 02580 Coords[1].x = pBounds->hi.x; Coords[1].y = pBounds->lo.y; 02581 Coords[2].x = pBounds->hi.x; Coords[2].y = pBounds->hi.y; 02582 Coords[3].x = pBounds->lo.x; Coords[3].y = pBounds->hi.y; 02583 02584 Trans2DMatrix Rotate(BBCentre,Angle); 02585 Rotate.Transform(Coords,4); 02586 02587 pBounds->lo.x = min(min(Coords[0].x,Coords[1].x), min(Coords[2].x,Coords[3].x)); 02588 pBounds->hi.x = max(max(Coords[0].x,Coords[1].x), max(Coords[2].x,Coords[3].x)); 02589 pBounds->lo.y = min(min(Coords[0].y,Coords[1].y), min(Coords[2].y,Coords[3].y)); 02590 pBounds->hi.y = max(max(Coords[0].y,Coords[1].y), max(Coords[2].y,Coords[3].y)); 02591 } 02592 return TRUE; 02593 } 02594 02595 /******************************************************************************************** 02596 02597 > MILLIPOINT BrushAttrValue::GetDefaultLineWidth(BOOL IgnorePressure) 02598 02599 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 02600 Created: 13/12/99 02601 02602 Inputs: - 02603 Outputs: - 02604 Returns: the default line width as defined by the largest bounding box of the brush definition, 02605 or -1 if this attribute has no brush definition 02606 Purpose: as above 02607 02608 ********************************************************************************************/ 02609 02610 MILLIPOINT BrushAttrValue::GetDefaultLineWidth(BOOL IgnorePressure) 02611 { 02612 if (m_pProcessor == NULL) 02613 return - 1; 02614 02615 return m_pProcessor->GetBrushSize(IgnorePressure); 02616 } 02617 02618 /******************************************************************************************** 02619 02620 > void BrushAttrValue::FlushCache() 02621 02622 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 02623 Created: 6/10/99 02624 Inputs: - 02625 Returns: - 02626 Purpose: clears out the cached points 02627 SeeAlso: - 02628 02629 ********************************************************************************************/ 02630 02631 void BrushAttrValue::FlushCache() 02632 { 02633 #ifdef BRUSHPOINTSCACHE 02634 if (m_pCachedPoints != NULL) 02635 { 02636 m_pCachedPoints->clear(); 02637 delete m_pCachedPoints; 02638 m_pCachedPoints = NULL; 02639 } 02640 02641 #endif 02642 02643 } 02644 02645 /******************************************************************************************** 02646 02647 > void BrushAttrValue::TransformCache(TransformBase& Trans) 02648 02649 Author: Chris_Snook (Xara Group Ltd) <camelotdev@xara.com> 02650 Created: 6/11/2000 02651 Inputs: transfromation matrix 02652 Returns: - 02653 Purpose: transforms the cached path. Attempts to optimise straight transform case. 02654 SeeAlso: - 02655 02656 ********************************************************************************************/ 02657 02658 void BrushAttrValue::TransformCache(TransformBase& Trans) 02659 { 02660 if (m_pCachedPoints) 02661 { 02662 BrushPointInfo PointInfo; 02663 PointsMap::iterator pos = m_pCachedPoints->begin(); 02664 02665 TransformBase *pBase = &Trans; 02666 if (pBase->IS_KIND_OF(Trans2DMatrix)) 02667 { 02668 Trans2DMatrix* transMatrix = (Trans2DMatrix*) pBase; 02669 // check for a change in aspect 02670 if (transMatrix->GetMatrix().IsTranslation()) 02671 { 02672 // optimise translate .... 02673 02674 DocCoord trans = transMatrix->GetTranslation (); 02675 02676 while( pos != m_pCachedPoints->end() ) 02677 { 02678 pos->second.m_Point.x += trans.x; 02679 pos->second.m_Point.y += trans.y; 02680 02681 ++pos; 02682 } 02683 } 02684 else 02685 { 02686 while( pos != m_pCachedPoints->end() ) 02687 { 02688 Trans.Transform( &pos->second.m_Point, 1 ); 02689 02690 ++pos; 02691 } 02692 } 02693 } 02694 else 02695 { 02696 while( pos != m_pCachedPoints->end() ) 02697 { 02698 Trans.Transform( &pos->second.m_Point, 1 ); 02699 02700 ++pos; 02701 } 02702 } 02703 } 02704 } 02705 02706 02707 02708 /******************************************************************************************** 02709 02710 > void BrushAttrValue::SetTimeStampUpdateType(ListUpdateType Update) 02711 02712 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 02713 Created: 6/10/99 02714 Inputs: Update can be: 02715 UPDATE_NONE, 02716 UPDATE_LIST - means that points have been added or removed to the timestamping list 02717 UPDATE_PROPORTION - means that the underlying path has changed but our list has not 02718 UPDATE_TimeStampList::iterator - means (usually) that the path has been reversed but our points are the same 02719 UPDATE_LISTANDTimeStampList::iterator - take a guess 02720 Returns: - 02721 Purpose: These flags determine what will happen in the NodePathUpdate function which is called 02722 after the freehand/brush or bezier tool is used to edit a brushed nodepath 02723 SeeAlso: - 02724 02725 ********************************************************************************************/ 02726 02727 void BrushAttrValue::SetTimeStampUpdateType(ListUpdateType Update) 02728 { 02729 m_TimeStampUpdateType = Update; 02730 } 02731 02732 02733 /******************************************************************************************** 02734 02735 > ListUpdateType GetTimeStampUpdateType() 02736 02737 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 02738 Created: 6/10/99 02739 Inputs: - 02740 Returns: the member, described above 02741 Purpose: As above 02742 SeeAlso: - 02743 02744 ********************************************************************************************/ 02745 02746 ListUpdateType BrushAttrValue::GetTimeStampUpdateType() 02747 { 02748 return m_TimeStampUpdateType; 02749 } 02750 02751 02752 /******************************************************************************************** 02753 02754 02755 > BOOL BrushAttrValue::WriteTimeStampList(BaseCamelotFilter *pFilter) 02756 02757 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 02758 Created: 13/12/99 02759 Inputs: pfilter - filter to write to 02760 Returns: TRUE if the list is correctly written 02761 Purpose: If this brush uses timestamping then this function writes the timestamped 02762 list to the filter provided. 02763 02764 SeeAlso: AttrBrushType::WritePreChildrenNative; BrushAttrRecordHandler::HandleRecord 02765 02766 ********************************************************************************************/ 02767 02768 BOOL BrushAttrValue::WriteTimeStampList(BaseCamelotFilter* pFilter) 02769 { 02770 ERROR2IF(pFilter == NULL, FALSE, "Filter is NULL in BrushAttrValue::WriteTimeStampList"); 02771 02772 if (m_pTimeStampList == NULL) 02773 return TRUE; // return TRUE else we'll spring an error 02774 02775 INT32 NumObjects = (INT32)m_pTimeStampList->size(); 02776 // make ourselves a record 02777 CXaraFileRecord Record ( static_cast<INT32> ( TAG_TIMESTAMPBRUSHDATA ), 02778 static_cast<INT32> ( TAG_TIMESTAMPBRUSHDATA_SIZE ) ); 02779 BOOL ok = Record.Init(); 02780 02781 // the first entry in the record is how many objects there are 02782 if (ok) ok = Record.WriteINT32(NumObjects); 02783 02784 // now write the data 02785 TimeStampBrushPoint ListItem; 02786 TimeStampList::iterator ListPos = m_pTimeStampList->begin(); 02787 while( ok && ListPos != m_pTimeStampList->end() ) 02788 { 02789 ListItem = *ListPos; ++ListPos; 02790 ok = ListItem.WriteNative(&Record); 02791 } 02792 02793 if (ok) ok = pFilter->Write(&Record); 02794 02795 return ok; 02796 } 02797 02798 02799 /******************************************************************************************** 02800 02801 02802 > BOOL BrushAttrValue::WritePressureData(BaseCamelotFilter *pFilter) 02803 02804 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 02805 Created: 13/12/99 02806 Inputs: pfilter - filter to write to 02807 Returns: TRUE if the list is correctly written 02808 Purpose: If this attribute contains pressure data then it will write out that data to 02809 the filter provided. 02810 02811 SeeAlso: AttrBrushType::WritePreChildrenNative; BrushAttrRecordHandler::HandleRecord 02812 02813 ********************************************************************************************/ 02814 02815 BOOL BrushAttrValue::WritePressureData(BaseCamelotFilter* pFilter) 02816 { 02817 ERROR2IF(pFilter == NULL, FALSE, "Filter is NULL in BrushAttrValue::WriteTimeStampList"); 02818 02819 if (m_pPressureSampler == NULL) 02820 return TRUE; // return TRUE else we'll spring an error 02821 02822 // make ourselves a record 02823 CXaraFileRecord Record ( static_cast<INT32> ( TAG_BRUSHPRESSURESAMPLEDATA ), 02824 static_cast<INT32> ( TAG_BRUSHSAMPLEDATA_SIZE ) ); 02825 BOOL ok = Record.Init(); 02826 02827 if (ok) ok = m_pPressureSampler->WriteNative(&Record); 02828 02829 if (ok) ok = pFilter->Write(&Record); 02830 02831 return ok; 02832 02833 } 02834 02835 /*-------------------------------------------------------------------------- 02836 ---------------------------------------------------------------------------- 02837 AttrBrushType class 02838 */ 02839 02840 02841 /******************************************************************************************** 02842 02843 > AttrBrushType::AttrBrushType() 02844 02845 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 02846 Created: 7/1/97 02847 02848 Purpose: Default constructor for AttrBrushType 02849 02850 ********************************************************************************************/ 02851 02852 AttrBrushType::AttrBrushType() 02853 { 02854 m_pFreeTool = NULL; 02855 m_pLocalStrokeColour = NULL; 02856 m_pBlendedStrokeColour = NULL; 02857 m_LocalTranspType = 0; 02858 m_LocalTranspValue = 0; 02859 } 02860 02861 02862 02863 /******************************************************************************************** 02864 02865 > AttrBrushType::AttrBrushType(Node *ContextNode, 02866 AttachNodeDirection Direction, 02867 BOOL Locked, 02868 BOOL Mangled, 02869 BOOL Marked, 02870 BOOL Selected) 02871 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 02872 Created: 7/1/97 02873 02874 Purpose: Constructs an AttrBrushType Attribute 02875 02876 ********************************************************************************************/ 02877 02878 AttrBrushType::AttrBrushType(Node *ContextNode, 02879 AttachNodeDirection Direction, 02880 BOOL Locked, 02881 BOOL Mangled, 02882 BOOL Marked, 02883 BOOL Selected) 02884 : NodeAttribute(ContextNode, Direction, Locked, Mangled, Marked, Selected) 02885 { 02886 m_pFreeTool = NULL; 02887 m_pLocalStrokeColour = NULL; 02888 m_pBlendedStrokeColour = NULL; 02889 m_LocalTranspType = 0; 02890 m_LocalTranspValue = 0; 02891 } 02892 02893 02894 /******************************************************************************************** 02895 02896 > AttrBrushType::~AttrBrushType() 02897 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 02898 Created: 7/1/97 02899 02900 Purpose: destructor 02901 02902 ********************************************************************************************/ 02903 02904 AttrBrushType::~AttrBrushType() 02905 { 02906 // if we are a blended attribute then our processor must destroy its blended brushdefinition 02907 /*PathProcessorBrush* pPPB =*/ m_Value.GetPathProcessor(); 02908 02909 // ask our attrval to delete its path processor 02910 m_Value.SetPathProcessor(NULL); 02911 02912 } 02913 02914 02915 /******************************************************************************************** 02916 02917 > virtual void AttrBrushType::Render(RenderRegion *pRender) 02918 02919 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 02920 Created: 7/1/97 02921 02922 Purpose: Renders this attribute (by simply calling the Render function of 02923 its contained AttributeValue) 02924 02925 ********************************************************************************************/ 02926 02927 void AttrBrushType::Render(RenderRegion *pRender) 02928 { 02929 02930 // what it says 02931 FindNearestStrokeTransp(); 02932 02933 // tell the processor who it belongs to 02934 PathProcessorBrush* pPPB = m_Value.GetPathProcessor(); 02935 if (pPPB != NULL) 02936 pPPB->SetParentAttribute(this); 02937 02938 if (m_pFreeTool != NULL) 02939 { 02940 String_32 ProgressString = _T("Processing Brush"); 02941 Progress Hourglass(&ProgressString, -1, FALSE); 02942 TRACEUSER("Diccon", _T("About to do first render\n") ); 02943 02944 GetAttributeValue()->Render(pRender); 02945 02946 // if we have pressure then we must invalidate our parent nodepath 02947 Node* pParent = FindParent(); 02948 if (pParent != NULL && pParent->IsNodePath() && ContainsPressureCache()) 02949 { 02950 ((NodeRenderableInk*)pParent)->InvalidateBoundingRect(); 02951 } 02952 m_pFreeTool = NULL; 02953 } 02954 else 02955 { 02956 #ifdef NEWFASTBRUSHES 02957 BrushAttrValue* pAttr = (BrushAttrValue*) GetAttributeValue(); 02958 pAttr->SetBoundsParent (FindParent ()); 02959 #endif 02960 GetAttributeValue()->Render(pRender); 02961 } 02962 } 02963 02964 /******************************************************************************************** 02965 02966 > SubtreeRenderState AttrBrushType::RenderSubtree(RenderRegion *pRender, Node** ppNextNode, BOOL bClip = TRUE) 02967 02968 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 02969 Created: 07/02/94 02970 Inputs: pRender - A pointer to the current render region 02971 Returns: TRUE => This node should be rendered, 02972 FALSE => This node does not need to be rendered. 02973 Purpose: Basically we want to avoid the situation of recursive path processing for 02974 brushes. Therefore if there is already a path processor of the same type 02975 as this one on the stack then we should not render 02976 02977 SeeAlso: Node::NeedsToRender 02978 02979 ********************************************************************************************/ 02980 02981 SubtreeRenderState AttrBrushType::RenderSubtree(RenderRegion *pRender, Node** ppNextNode, BOOL bClip) 02982 { 02983 // BOOL Retval = TRUE; 02984 PathProcessorBrush* pPPB = GetPathProcessor(); 02985 if (pPPB != NULL) 02986 { 02987 // pRender can legally be null, but we don't want to proliferate passing null pointers around 02988 if (pRender != NULL && pPPB->IsThisPathProcessorOnTheStack(pRender)) 02989 return SUBTREE_NORENDER; 02990 } 02991 02992 return SUBTREE_ROOTONLY; 02993 } 02994 02995 02996 /********************************************************************************************* 02997 02998 > BOOL AttrBrushType::EffectsParentBounds() const 02999 03000 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 03001 Created: 20/12/99 03002 Inputs: - 03003 Outputs: - 03004 Returns: TRUE if the node will effect the bounds of it's parent. 03005 Purpose: Virtual function for determining if the node will effect it's parent bounds. 03006 eg. ArrowHeads. 03007 SeeAlso: NodeAttribute::GetAttrBoundingRect 03008 03009 **********************************************************************************************/ 03010 03011 BOOL AttrBrushType::EffectsParentBounds() 03012 { 03013 return TRUE; 03014 } 03015 03016 03017 /********************************************************************************************* 03018 03019 > DocRect AttrBrushType::GetAttrBoundingRect(NodeRenderableInk* pParent) 03020 03021 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 03022 Created: 20/12/99 03023 Inputs: pParent, the parent Ink node that this attribute will effect. 03024 pAttribMap - not used 03025 Outputs: - 03026 Returns: The Bounding rect of the attribute (NULL rectangle is it doesn't have any). 03027 Purpose: Virtual function for determining the bounding rect of an attribute. 03028 Simply calls the brush value which does the calculation 03029 SeeAlso: NodeAttribute::EffectsParentBounds 03030 03031 **********************************************************************************************/ 03032 03033 DocRect AttrBrushType::GetAttrBoundingRect(NodeRenderableInk* pParent, CCAttrMap* pAttribMap ) 03034 { 03035 ERROR2IF(pParent == NULL, DocRect(0,0,0,0) , "Parent node is NULL in AttrBrushType::GetAttrBoundingRect"); 03036 03037 BrushAttrValue* pVal = (BrushAttrValue*)GetAttributeValue(); 03038 if (pVal == NULL) 03039 return DocRect(0, 0, 0, 0); 03040 else 03041 { 03042 // bit of a hack - the PPB needs to know that we are its parents, and if we have not yet rendered then 03043 // it may not know that yet 03044 PathProcessorBrush* pPPB = pVal->GetPathProcessor(); 03045 if (pPPB != NULL) 03046 { 03047 pPPB->SetParentAttribute(this); 03048 03049 // set the line width 03050 MILLIPOINT Width = GetAppliedLineWidth(); 03051 if (Width > 500) 03052 { 03053 SetValueToScaleTo(Width); 03054 } 03055 else 03056 return DocRect(0, 0, 0, 0); // if its too small then just return as we'll generate infinite objects 03057 } 03058 03059 } 03060 return pVal->GetAttrBoundingRect(pParent); 03061 03062 } 03063 03064 /*********************************************************************************************** 03065 03066 > virtual void AttrBrushType::CopyNodeContents(AttrBrushType *NodeCopy) 03067 03068 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 03069 Created: 13/12/99 03070 03071 Outputs: NodeCopy - returned containing a copy of this node 03072 03073 Purpose: Copies the node's contents to the node pointed to by NodeCopy 03074 03075 ***********************************************************************************************/ 03076 03077 void AttrBrushType::CopyNodeContents(AttrBrushType *NodeCopy) 03078 { 03079 // Let the base class do its bit 03080 NodeAttribute::CopyNodeContents(NodeCopy); 03081 03082 // And then copy our Value 03083 *(NodeCopy->GetAttributeValue()) = *(GetAttributeValue()); 03084 } 03085 03086 03087 03088 /*********************************************************************************************** 03089 > void AttrBrushType::PolyCopyNodeContents(NodeRenderable* pNodeCopy) 03090 03091 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 03092 Created: 18/12/2003 03093 Outputs: - 03094 Purpose: Polymorphically copies the contents of this node to another 03095 Errors: An assertion failure will occur if NodeCopy is NULL 03096 Scope: protected 03097 03098 ***********************************************************************************************/ 03099 03100 void AttrBrushType::PolyCopyNodeContents(NodeRenderable* pNodeCopy) 03101 { 03102 ENSURE(pNodeCopy, "Trying to copy a node's contents into a NULL node"); 03103 ENSURE(IS_A(pNodeCopy, AttrBrushType), "PolyCopyNodeContents given wrong dest node type"); 03104 03105 if (IS_A(pNodeCopy, AttrBrushType)) 03106 CopyNodeContents((AttrBrushType*)pNodeCopy); 03107 } 03108 03109 03110 03111 /*********************************************************************************************** 03112 03113 > virtual INT32 AttrBrushType::operator==(const NodeAttribute &NodeAttrib); 03114 03115 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 03116 Created: 13/12/99 03117 03118 Inputs: NodeAttrib - The node to compare this node to 03119 Returns: TRUE if the nodes are considered equal 03120 03121 Purpose: Comparison operator - determines if the AttributeValues of both objects are == 03122 03123 ***********************************************************************************************/ 03124 03125 INT32 AttrBrushType::operator==(const NodeAttribute &NodeAttrib) 03126 { 03127 // First check they are of the same type 03128 if (((NodeAttribute*)&NodeAttrib)->GetAttributeType() != GetAttributeType()) 03129 return FALSE; 03130 03131 // Make a more sensible pointer 03132 AttrBrushType *Attr = (AttrBrushType *) &NodeAttrib; 03133 03134 // Now let the AttributeValues compare themselves 03135 return( *((BrushAttrValue *) Attr->GetAttributeValue()) == 03136 *((BrushAttrValue *) GetAttributeValue()) ); 03137 } 03138 03139 03140 03141 /******************************************************************************************** 03142 03143 > virtual Node *AttrBrushType::SimpleCopy() 03144 03145 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 03146 Created: 13/12/99 03147 03148 Returns: A copy of the node, or NULL if memory runs out 03149 03150 Purpose: This method returns a shallow copy of the node with all Node pointers NULL. 03151 The function is virtual, and must be defined for all derived classes. 03152 03153 ********************************************************************************************/ 03154 03155 Node *AttrBrushType::SimpleCopy() 03156 { 03157 AttrBrushType* NodeCopy = new AttrBrushType; 03158 if (NodeCopy == NULL) 03159 return(NULL); 03160 03161 // Call the base class 03162 NodeAttribute::CopyNodeContents(NodeCopy); 03163 03164 // And call our AttributeValue to copy itself too 03165 NodeCopy->GetAttributeValue()->SimpleCopy(GetAttributeValue()); 03166 03167 // tell the new path processor who is boss 03168 PathProcessorBrush* pPPB = NodeCopy->GetPathProcessor(); 03169 if (pPPB != NULL) 03170 pPPB->SetParentAttribute(NodeCopy); 03171 03172 return(NodeCopy); 03173 } 03174 03175 03176 03177 /******************************************************************************************** 03178 03179 > virtual UINT32 AttrBrushType::GetAttrNameID(void) 03180 03181 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 03182 Created: 13/12/99 03183 03184 Returns: Attribute description string-resource ID 03185 03186 Purpose: Retrieves a string resource ID describing this attribute 03187 03188 ********************************************************************************************/ 03189 03190 UINT32 AttrBrushType::GetAttrNameID(void) 03191 { 03192 return(_R(IDS_ATTRBRUSH)); 03193 } 03194 03195 /******************************************************************************************** 03196 > virtual BOOL AttrStokeType::NeedsTransparency() const 03197 03198 Author: Richard_Millican (Xara Group Ltd) <camelotdev@xara.com> 03199 Created: 7/2/97 03200 Inputs: - 03201 Outputs: - 03202 Returns: TRUE if this Attribute requires transparency mode to render properly. 03203 Purpose: Strokes like the airbrush require transparency to be turned on to work. 03204 Errors: - 03205 ********************************************************************************************/ 03206 03207 BOOL AttrBrushType::NeedsTransparency() const 03208 { 03209 BOOL SoWeDoReallyNeedTransparencyThenDoWe = FALSE; 03210 03211 PathProcessorBrush *pPathProc = m_Value.GetPathProcessor(); 03212 if(pPathProc != NULL) 03213 { 03214 SoWeDoReallyNeedTransparencyThenDoWe = pPathProc->NeedsTransparency(); 03215 } 03216 03217 return SoWeDoReallyNeedTransparencyThenDoWe; 03218 } 03219 03220 03221 /******************************************************************************************** 03222 03223 > virtual void AttrBrushType::GetDebugDetails(StringBase *Str) 03224 03225 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 03226 Created: 13/12/99 03227 03228 Outputs: On return, Str is filled in with details on this node 03229 03230 Purpose: Produces debug details about this node 03231 03232 ********************************************************************************************/ 03233 03234 void AttrBrushType::GetDebugDetails(StringBase *Str) 03235 { 03236 #ifdef _DEBUG 03237 NodeAttribute::GetDebugDetails(Str); 03238 03239 String_256 TempStr; 03240 TempStr._MakeMsg( _T("\r\nBrush #1%s\r\n"), 03241 (m_Value.GetPathProcessor() == NULL) ? _T("old-style line") : _T("new stroke:") ); 03242 *Str += TempStr; 03243 03244 if (m_Value.GetPathProcessor() != NULL) 03245 { 03246 TempStr._MakeMsg( _T(" #1%s\r\n"), 03247 m_Value.GetPathProcessor()->GetRuntimeClass()->GetClassName() ); 03248 *Str += TempStr; 03249 } 03250 03251 //TempStr._MakeMsg("\r\nNeedsTransparency=#1%s\r\n", NeedsTransparency() ? "TRUE" : "FALSE"); 03252 //*Str += TempStr; 03253 03254 TempStr._MakeMsg( _T("\r\nDefinition Handle=#1%d\r\n"), GetBrushHandle() ); 03255 *Str += TempStr; 03256 #endif 03257 } 03258 03259 /******************************************************************************************** 03260 03261 > BOOL AttrBrushType::Blend(BlendAttrParam* pBlendParam) 03262 03263 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 03264 Created: 17/3/2000 03265 Inputs: pBlendParam - contains the blend info, 03266 Outputs: pBlendParama - containing the blended attributes 03267 Returns: TRUE - Blend went ok, the blended attr val is valid; FALSE if not. 03268 Purpose: Blends between two brush attributes. In fact at the moment it just blends 03269 between the parameters in the two path processors. At some point it should 03270 also blend between the ink objects and attributes. 03271 03272 Errors: Out of memory. 03273 03274 ********************************************************************************************/ 03275 03276 BOOL AttrBrushType::Blend(BlendAttrParam* pBlendParam) 03277 { 03278 // Check entry param isn't NULL 03279 ERROR3IF(pBlendParam == NULL,"NULL entry param"); 03280 if (pBlendParam == NULL) return FALSE; 03281 03282 // Get the Value member to blend to the Value member of the other NodeAttribute. 03283 // If it succeeds, ask the blended Value to make a NodeAttribute out of itself. 03284 03285 if (GetAttributeValue()->Blend(pBlendParam)) 03286 { 03287 // Get the blended attr val. After this call, the ptr is our reponsibility 03288 // so we have to delete it if it's no longer needed 03289 AttributeValue* pBlendedAttrVal = pBlendParam->GetBlendedAttrVal(); 03290 03291 if (pBlendedAttrVal != NULL) 03292 { 03293 // We have a blended attr val, so ask it to make a NodeAttribute out of itself 03294 // and set the pBlendParam's blended NodeAttribute ptr to it 03295 NodeAttribute* pBlendedAttr = pBlendedAttrVal->MakeNode(); 03296 pBlendParam->SetBlendedAttr(pBlendedAttr); 03297 03298 if (pBlendedAttr != NULL) 03299 { 03300 // We were able to make a blended NodeAttribute 03301 // so delete the blended attr val, and return TRUE 03302 ((BrushAttrValue*)pBlendedAttrVal)->SetPathProcessor(NULL); 03303 delete pBlendedAttrVal; 03304 return TRUE; 03305 } 03306 else 03307 { 03308 // Couldn't make a blended NodeAttribute, so give the blended attr val back 03309 // and return FALSE 03310 pBlendParam->SetBlendedAttrVal(pBlendedAttrVal); 03311 return FALSE; 03312 } 03313 } 03314 } 03315 03316 return FALSE; 03317 } 03318 03319 03320 03321 /******************************************************************************************** 03322 03323 > virtual BOOL AttrBrushType::DoBecomeA(BecomeA* pBecomeA, Node* pParent) 03324 03325 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 03326 Created: 17/3/2000 03327 Inputs: pBecomeA - the becomeA object that tells us what to do 03328 pParent - the node that this attribute is applied to 03329 Outputs: 03330 Returns: TRUE if everything went ok, 03331 Purpose: Its a little unusual for attributes to have their own dobecomea function but 03332 the brush requires one because the node that it is applied to will not know 03333 anything about it. It is designed to be called by the node that has this 03334 brush applied to it. 03335 Note that all the real work goes on in the attribute value and path processor. 03336 03337 ********************************************************************************************/ 03338 03339 BOOL AttrBrushType::DoBecomeA(BecomeA* pBecomeA, Node* pParent) 03340 { 03341 ERROR2IF(pBecomeA == NULL, FALSE, "BecomeA pointer is NULL in AttrBrushType::DoBecomeA"); 03342 ERROR2IF(pParent == NULL, FALSE, "Parent node is NULL in AttrBrushType::DoBecomeA"); 03343 PathProcessorBrush* pPPB = m_Value.GetPathProcessor(); 03344 if (pPPB) 03345 pPPB->SetParentAttribute(this); 03346 03347 return m_Value.DoBecomeA(pBecomeA, pParent); 03348 } 03349 03350 /******************************************************************************************** 03351 03352 > virtual UINT32 AttrBrushType::GetNodeSize() const 03353 03354 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 03355 Created: 13/12/99 03356 03357 Returns: The size of this node, in bytes 03358 03359 Purpose: For finding the size of the node, in bytes 03360 03361 ********************************************************************************************/ 03362 03363 UINT32 AttrBrushType::GetNodeSize() const 03364 { 03365 return(sizeof(AttrBrushType)); 03366 } 03367 03368 03369 /******************************************************************************************** 03370 03371 > virtual UINT32 AttrBrushType::GetNodeSize() const 03372 03373 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 03374 Created: 13/12/99 03375 03376 Returns: The size of this node, in bytes 03377 03378 Purpose: For finding the size of the node, in bytes 03379 03380 ********************************************************************************************/ 03381 03382 String_32 AttrBrushType::GetBrushName() 03383 { 03384 String_32 Name = TEXT(" "); 03385 03386 BrushDefinition* pDef = GetBrushDefinition(); 03387 if (pDef != NULL) 03388 { 03389 String_32* pName = pDef->GetLineName(); 03390 if (pName != NULL) 03391 Name = *pName; 03392 } 03393 return Name; 03394 } 03395 03396 /******************************************************************************************** 03397 03398 > void AttrBrushType::FindNearestStrokeColour() 03399 03400 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 03401 Created: 13/12/99 03402 03403 Returns: - 03404 03405 Purpose: Locates the nearest stroke colour attribute, takes the colour and stores 03406 it in our member variable. Note that it also converts the colour if it is 03407 an IndexedColour. 03408 03409 ********************************************************************************************/ 03410 03411 void AttrBrushType::FindNearestStrokeColour() 03412 { 03413 NodeRenderableInk* pParent = (NodeRenderableInk*)FindParent(); 03414 if (pParent == NULL) 03415 { 03416 // ERROR3("Wheres my parent?!"); Might be a default, so don't error 03417 return; 03418 } 03419 // if its a controller we want its ink node 03420 if (pParent->IsCompoundClass()) 03421 { 03422 NodeRenderableInk* pInk = ((NodeCompound*)pParent)->GetInkNodeFromController(); 03423 if (pInk) 03424 pParent = pInk; 03425 } 03426 03427 03428 NodeAttribute* pStrokeColour = NULL; 03429 03430 // get the attribute 03431 pParent->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrStrokeColour), &pStrokeColour); 03432 03433 if (pStrokeColour == NULL) 03434 return; 03435 03436 // get the stroke colour 03437 StrokeColourAttribute* pVal = (StrokeColourAttribute*)pStrokeColour->GetAttributeValue(); 03438 if (pVal != NULL) 03439 { 03440 // we're only interested in the actual colour 03441 m_pLocalStrokeColour = &(pVal->Colour); 03442 } 03443 else 03444 TRACEUSER("Diccon", _T("Unable to find local stroke colour\n") ); 03445 03446 } 03447 03448 03449 /******************************************************************************************** 03450 03451 > void AttrBrushType::FindNearestStrokeTransp() 03452 03453 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 03454 Created: 13/12/99 03455 Returns: - 03456 Purpose: Finds the local stroke transparency and caches the transparency value and type 03457 ********************************************************************************************/ 03458 03459 void AttrBrushType::FindNearestStrokeTransp() 03460 { 03461 m_LocalTranspValue = 0; 03462 m_LocalTranspType = 0; 03463 03464 NodeRenderableInk* pParent = (NodeRenderableInk*)FindParent(); 03465 if (pParent == NULL || !pParent->IsAnObject()) 03466 { 03467 // ERROR3("Wheres my parent?!"); Might be a default, so don't error 03468 return; 03469 } 03470 03471 // if its a controller we want its ink node 03472 if (pParent->IsCompoundClass()) 03473 { 03474 NodeRenderableInk* pInk = ((NodeCompound*)pParent)->GetInkNodeFromController(); 03475 if (pInk) 03476 pParent = pInk; 03477 } 03478 03479 NodeAttribute* pStrokeTransp = NULL; 03480 03481 // get the attribute 03482 pParent->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrStrokeTransp), &pStrokeTransp, FALSE); 03483 03484 if (pStrokeTransp == NULL) 03485 return; 03486 03487 // get the stroke transparency 03488 StrokeTranspAttribute* pVal = (StrokeTranspAttribute*)pStrokeTransp->GetAttributeValue(); 03489 if (pVal != NULL) 03490 { 03491 // we're only interested in the actual colour 03492 m_LocalTranspValue = *pVal->GetStartTransp(); 03493 m_LocalTranspType = pVal->GetTranspType(); 03494 } 03495 } 03496 03497 /******************************************************************************************** 03498 03499 > DocColour AttrBrushType::GetLocalStrokeColour() 03500 03501 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 03502 Created: 13/12/99 03503 03504 Returns: the colour of the stroke that this attribute is applied to, or a default 'blank' 03505 colour if we don't have a stroke 03506 03507 Purpose: Returns either the blended or local stroke colour. Given that the blended colour 03508 is null unless we are in a blend it takes priority when it does exist. 03509 03510 ********************************************************************************************/ 03511 03512 DocColour AttrBrushType::GetLocalStrokeColour() 03513 { 03514 DocColour Col; 03515 if (m_pBlendedStrokeColour != NULL) 03516 Col = * m_pBlendedStrokeColour; 03517 else if (m_pLocalStrokeColour != NULL) 03518 Col = *m_pLocalStrokeColour; 03519 03520 return Col; 03521 } 03522 03523 03524 /******************************************************************************************** 03525 03526 > void AttrBrushType::SetBlendedStrokeColour(DocColour* pCol) 03527 03528 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 03529 Created: 13/12/99 03530 Inputs: pointer to stroke colour in the blend 03531 Returns: - 03532 Purpose: Tells the attribute that pCol is the stroke colour for the current blend step. 03533 ********************************************************************************************/ 03534 03535 void AttrBrushType::SetBlendedStrokeColour(DocColour* pCol) 03536 { 03537 m_pBlendedStrokeColour = pCol; 03538 } 03539 03540 03541 /******************************************************************************************** 03542 03543 > UINT32 AttrBrushType::GetLocalTranspValue() 03544 03545 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 03546 Created: 13/12/99 03547 03548 Returns: the value of the local stroke transparency that we cached 03549 Purpose: - 03550 ********************************************************************************************/ 03551 03552 UINT32 AttrBrushType::GetLocalTranspValue() 03553 { 03554 return m_LocalTranspValue; 03555 } 03556 03557 03558 /******************************************************************************************** 03559 03560 > DocColour AttrBrushType::GetLocalStrokeColour() 03561 03562 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 03563 Created: 13/12/99 03564 03565 Returns: the type of the local stroke transparency that we cached 03566 Purpose: - 03567 ********************************************************************************************/ 03568 03569 UINT32 AttrBrushType::GetLocalTranspType() 03570 { 03571 return m_LocalTranspType; 03572 } 03573 03574 /******************************************************************************************** 03575 03576 > BrushDefinition* AttrBrushType::GetBrushDefinition() 03577 03578 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 03579 Created: 6/10/99 03580 Inputs: - 03581 Returns: the brush definition used by this brush (can be NULL) 03582 Purpose: interface to the BrushAttrValue 03583 SeeAlso: - 03584 03585 ********************************************************************************************/ 03586 03587 BrushDefinition* AttrBrushType::GetBrushDefinition() 03588 { 03589 return m_Value.GetBrushDefinition(); 03590 } 03591 03592 03593 /******************************************************************************************** 03594 03595 > BrushHandle AttrBrushType::GetBrushHandle() 03596 03597 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 03598 Created: 6/10/99 03599 Inputs: - 03600 Returns: handle of the brush definition used by this brush (can be NULL) 03601 Purpose: interface to the BrushAttrValue 03602 SeeAlso: - 03603 03604 ********************************************************************************************/ 03605 03606 BrushHandle AttrBrushType::GetBrushHandle() 03607 { 03608 return m_Value.GetBrushHandle(); 03609 } 03610 03611 03612 /******************************************************************************************** 03613 03614 > virtual BOOL AttrBrushType::IsABrush() const 03615 03616 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 03617 Created: 13/12/99 03618 Returns: TRUE 03619 Purpose: For identifying this as a brush attribute 03620 03621 ********************************************************************************************/ 03622 03623 BOOL AttrBrushType::IsABrush() const 03624 { 03625 return TRUE; 03626 } 03627 03628 03629 /******************************************************************************************** 03630 03631 > MILLIPOINT AttrBrushType::GetDefaultLineWidth(BOOL IgnorePressure) 03632 03633 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 03634 Created: 6/10/99 03635 Inputs: - 03636 Returns: the height of the largest object in this brush 03637 Purpose: convenient interface to the attribute value 03638 SeeAlso: - 03639 03640 ********************************************************************************************/ 03641 03642 MILLIPOINT AttrBrushType::GetDefaultLineWidth(BOOL IgnorePressure) 03643 { 03644 return m_Value.GetDefaultLineWidth(IgnorePressure); 03645 } 03646 03647 /******************************************************************************************** 03648 03649 > BOOL AttrBrushType::SetSpacing(MILLIPOINT NewSpacing) 03650 03651 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 03652 Created: 6/10/99 03653 Inputs: the spacing value to set 03654 Returns: TRUE if successful, FALSE if not 03655 Purpose: To set the spacing between brush objects 03656 SeeAlso: - 03657 03658 ********************************************************************************************/ 03659 03660 BOOL AttrBrushType::SetSpacing(MILLIPOINT NewSpacing) 03661 { 03662 PathProcessorBrush* pPathProc = m_Value.GetPathProcessor(); 03663 if (pPathProc == NULL) 03664 return FALSE; 03665 03666 03667 return pPathProc->SetSpacing(NewSpacing); 03668 } 03669 03670 03671 /******************************************************************************************** 03672 03673 > MILLIPOINT AttrBrushType::GetScaling() 03674 03675 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 03676 Created: 6/10/99 03677 Inputs: - 03678 Returns: the current brush spacing value 03679 Purpose: - 03680 SeeAlso: - 03681 03682 ********************************************************************************************/ 03683 03684 MILLIPOINT AttrBrushType::GetSpacing() 03685 { 03686 PathProcessorBrush* pPathProc = m_Value.GetPathProcessor(); 03687 if (pPathProc == NULL) 03688 return -1; 03689 return (MILLIPOINT)pPathProc->GetSpacing(); 03690 } 03691 03692 03693 03694 /******************************************************************************************** 03695 03696 > BOOL AttrBrushType::SetScaling(double NewScaling) 03697 03698 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 03699 Created: 6/10/99 03700 Inputs: the scaling value to set 03701 Returns: TRUE if successful, FALSE if not 03702 Purpose: To set the brush scaling 03703 SeeAlso: - 03704 03705 ********************************************************************************************/ 03706 03707 BOOL AttrBrushType::SetScaling(double NewScale) 03708 { 03709 PathProcessorBrush* pPPB = m_Value.GetPathProcessor(); 03710 if (pPPB == NULL) 03711 return FALSE; 03712 return pPPB->SetBrushScaling(NewScale); 03713 } 03714 03715 /******************************************************************************************** 03716 03717 > BOOL AttrBrushType::SetPathOffsetType(PathOffset NewOffsetType) 03718 03719 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 03720 Created: 6/10/99 03721 Inputs Offset - the offset type to set 03722 Returns: - 03723 Purpose: to set the offset type for this brush 03724 ********************************************************************************************/ 03725 03726 BOOL AttrBrushType::SetPathOffsetType(PathOffset NewOffsetType) 03727 { 03728 PathProcessorBrush* pPathProc = m_Value.GetPathProcessor(); 03729 if (pPathProc == NULL) 03730 return FALSE; 03731 pPathProc->SetPathOffsetType(NewOffsetType); 03732 return TRUE; 03733 } 03734 03735 /******************************************************************************************** 03736 03737 > BOOL AttrBrushType::SetPathOffsetValue(MILLIPOINT Value) 03738 03739 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 03740 Created: 6/10/99 03741 Inputs Value - the offset value to set 03742 Returns: - 03743 Purpose: to set the offset distance for this brush 03744 ********************************************************************************************/ 03745 03746 BOOL AttrBrushType::SetPathOffsetValue(MILLIPOINT NewValue) 03747 { 03748 PathProcessorBrush* pPathProc = m_Value.GetPathProcessor(); 03749 if (pPathProc == NULL) 03750 return FALSE; 03751 pPathProc->SetPathOffsetValue(NewValue); 03752 return TRUE; 03753 } 03754 03755 03756 /******************************************************************************************** 03757 03758 > BOOL AttrBrushType::SetTiling(BOOL Value) 03759 03760 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 03761 Created: 6/10/99 03762 Inputs: whether or not the brush tiles 03763 Returns: TRUE if successful, FALSE otherwise 03764 Purpose: When a brush tiles it means that the attribute types: 03765 - 3 colour fill 03766 - 4 colour fill 03767 - bitmap fill 03768 are only rendered once per brush, rather than for every brush step 03769 SeeAlso: - 03770 03771 ********************************************************************************************/ 03772 03773 BOOL AttrBrushType::SetTiled(BOOL Tiled) 03774 { 03775 PathProcessorBrush* pPathProc = m_Value.GetPathProcessor(); 03776 if (pPathProc == NULL) 03777 return FALSE; 03778 pPathProc->SetTiling(Tiled); 03779 return TRUE; 03780 } 03781 03782 03783 /******************************************************************************************** 03784 03785 > BOOL AttrBrushType::SetRotateAngle(double Angle) 03786 03787 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 03788 Created: 6/10/99 03789 Inputs: the angle of rotation to set 03790 Returns: TRUE if the angle is within the stated bounds 03791 Purpose: as above 03792 SeeAlso: - 03793 03794 ********************************************************************************************/ 03795 03796 BOOL AttrBrushType::SetRotateAngle(double NewAngle) 03797 { 03798 PathProcessorBrush* pPathProc = m_Value.GetPathProcessor(); 03799 if (pPathProc == NULL) 03800 return FALSE; 03801 return pPathProc->SetRotationAngle(NewAngle); 03802 } 03803 03804 03805 /******************************************************************************************** 03806 03807 > BOOL AttrBrushType::SetRotated(BOOL Value) 03808 03809 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 03810 Created: 6/10/99 03811 Inputs: whether or not the brush rotates 03812 Returns: - 03813 Purpose: as above 03814 SeeAlso: - 03815 03816 ********************************************************************************************/ 03817 03818 BOOL AttrBrushType::SetRotated(BOOL Rotated) 03819 { 03820 PathProcessorBrush* pPathProc = m_Value.GetPathProcessor(); 03821 if (pPathProc == NULL) 03822 return FALSE; 03823 pPathProc->SetRotated(Rotated); 03824 return TRUE; 03825 } 03826 03827 03828 /******************************************************************************************** 03829 03830 > PathProcessorBrush* AttrBrushType::GetPathProcessor() 03831 03832 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 03833 Created: 6/10/99 03834 Inputs: - 03835 Returns: the path processor belonging to the attribute value 03836 Purpose: as above 03837 SeeAlso: - 03838 03839 ********************************************************************************************/ 03840 03841 PathProcessorBrush* AttrBrushType::GetPathProcessor() 03842 { 03843 return m_Value.GetPathProcessor(); 03844 } 03845 03846 03847 03848 /******************************************************************************************** 03849 03850 > void AttrBrushType::InitialiseBrushData() 03851 03852 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 03853 Created: 6/10/99 03854 Inputs: - 03855 Returns: - 03856 Purpose: retrieves data from the path processor and puts it into our brushdata object 03857 SeeAlso: - 03858 03859 ********************************************************************************************/ 03860 03861 void AttrBrushType::InitialiseBrushData() 03862 { 03863 PathProcessorBrush* pPPB = GetPathProcessor(); 03864 if (pPPB != NULL) 03865 pPPB->CopyBrushData(&m_BrushData); 03866 } 03867 03868 03869 03870 /******************************************************************************************** 03871 03872 > BrushData AttrBrushType::GetBrushData() 03873 03874 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 03875 Created: 6/10/99 03876 Inputs: - 03877 Returns: our brush data object 03878 Purpose: gets the latest data from our path processor, copies it into our BrushData object 03879 which is then returned; 03880 SeeAlso: - 03881 03882 ********************************************************************************************/ 03883 03884 BrushData AttrBrushType::GetBrushData() 03885 { 03886 InitialiseBrushData(); 03887 return m_BrushData; 03888 } 03889 03890 03891 03892 /******************************************************************************************** 03893 03894 > void AttrBrushType::SetBrushData(BrushData Data) 03895 03896 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 03897 Created: 6/10/99 03898 Inputs: Data object to set 03899 Returns: - 03900 Purpose: Not quite sure why you would use this, as there is no link from the brush data object 03901 to the path processor at the moment. hmm 03902 SeeAlso: - 03903 03904 ********************************************************************************************/ 03905 03906 void AttrBrushType::SetBrushData(BrushData Data) 03907 { 03908 m_BrushData = Data; 03909 } 03910 03911 03912 /******************************************************************************************** 03913 03914 > void AttrBrushType::GetMaxScalingFromDefinition() 03915 03916 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 03917 Created: 6/10/99 03918 Inputs: - 03919 Returns: - 03920 Purpose: Obtains the max scaling value from the brush definition and sets it to the 03921 path processor. This is not needed upon brush creation however it is required 03922 if you are importing a brush. 03923 SeeAlso: - 03924 03925 ********************************************************************************************/ 03926 03927 void AttrBrushType::GetMaxScalingFromDefinition() 03928 { 03929 BrushDefinition* pBrushDef = GetBrushDefinition(); 03930 if (pBrushDef != NULL) 03931 { 03932 double Max = pBrushDef->GetMaxScaling(); 03933 PathProcessorBrush* pPPB = GetPathProcessor(); 03934 if (pPPB != NULL) 03935 pPPB->SetMaxScaling(Max); 03936 } 03937 } 03938 03939 03940 /******************************************************************************************** 03941 03942 > BOOL AttrBrushType::CanUsePointsCache() 03943 03944 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 03945 Created: 6/10/99 03946 Inputs: - 03947 Returns: TRUE if the we are allowed to use the points cache in the brushattrvalue, 03948 FALSE if not. 03949 Purpose: We are not allowed to use the points cache if this attribute is applied to multiple 03950 ink nodes as a part of a group. The reason for this is that the paths of the ink 03951 nodes are passed in to the path processor one by one, this means that the points 03952 along the first path are cached, and because the cache exists these points are 03953 re-used for all subsequent ink objects, meaning that only the first object gets 03954 drawn. 03955 Further conditions may be added to this at a later date. 03956 See also: PathProcessorBrush::GetPointAtDistance 03957 03958 ********************************************************************************************/ 03959 03960 BOOL AttrBrushType::CanUsePointsCache() 03961 { 03962 Node* pParent = FindParent(); 03963 if (pParent != NULL) 03964 { 03965 if (pParent->IsCompound() 03966 || pParent->IsABaseTextClass() 03967 || pParent->IsAContour() 03968 ) 03969 return FALSE; 03970 } 03971 03972 return TRUE; 03973 } 03974 03975 /******************************************************************************************** 03976 03977 > void AttrBrushType::GetCurrentLineWidth() 03978 03979 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 03980 Created: 6/10/99 03981 Inputs: - 03982 Returns: the width of the nearest linewidth attribute, or -1 if there isn't one (unlikely) 03983 Purpose: as above 03984 SeeAlso: - 03985 03986 ********************************************************************************************/ 03987 03988 MILLIPOINT AttrBrushType::GetAppliedLineWidth() 03989 { 03990 MILLIPOINT ReturnVal = 0; 03991 //first get the parent 03992 NodeRenderableInk* pInk = (NodeRenderableInk*)FindParent(); 03993 03994 // if we're under a nodeshadow controller then we need to ask it for the right ink node 03995 if (pInk != NULL && pInk->IsCompoundClass()) 03996 { 03997 NodeRenderableInk* pInkNode = ((NodeCompound*)pInk)->GetInkNodeFromController(); 03998 if (pInkNode) 03999 pInk = pInkNode; 04000 } 04001 04002 if (pInk != NULL) 04003 { 04004 // find the applied AttrLineWidth 04005 NodeAttribute* pAttr = NULL; 04006 BOOL Found = pInk->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrLineWidth), &pAttr); 04007 if (Found && (pAttr != NULL)) 04008 { 04009 LineWidthAttribute* pVal = (LineWidthAttribute*)((AttrLineWidth*)pAttr)->GetAttributeValue(); 04010 if (pVal != NULL) 04011 ReturnVal = pVal->LineWidth; 04012 } 04013 04014 // double check that we don't have a transparent stroke colour 04015 AttrStrokeColour* pStrokeCol = NULL; 04016 pInk->FindAppliedAttribute(CC_RUNTIME_CLASS(AttrStrokeColour), (NodeAttribute**)&pStrokeCol, FALSE); 04017 if (pStrokeCol) 04018 { 04019 if (pStrokeCol->Value.Colour.IsTransparent()) 04020 ReturnVal = 0; 04021 } 04022 } 04023 04024 return ReturnVal; 04025 } 04026 04027 /******************************************************************************************** 04028 04029 > void AttrBrushType::SetValueToScaleTo(MILLIPOINT Value) 04030 04031 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 04032 Created: 6/10/99 04033 Inputs: linewidth to scale to 04034 Returns: - 04035 Purpose: as above 04036 SeeAlso: - 04037 04038 ********************************************************************************************/ 04039 04040 void AttrBrushType::SetValueToScaleTo(MILLIPOINT Value) 04041 { 04042 m_Value.ScaleToLineWidth(Value); 04043 } 04044 04045 04046 /******************************************************************************************** 04047 04048 > void AttrBrushType::SetUseLocalTransp(BOOL UseTransp) 04049 04050 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 04051 Created: 6/10/99 04052 Inputs: whether or not to use local transparency 04053 Returns: - 04054 Purpose: interface to the PPB, sets a member 04055 SeeAlso: PathProcessorBrush::RenderAttributes 04056 04057 ********************************************************************************************/ 04058 04059 void AttrBrushType::SetUseLocalTransp(BOOL UseTransp) 04060 { 04061 PathProcessorBrush* pPPB = m_Value.GetPathProcessor(); 04062 if (pPPB) 04063 pPPB->SetUseLocalTransp(UseTransp); 04064 } 04065 04066 /******************************************************************************************** 04067 04068 > void AttrBrushType::Transform(TransformBase& Transform) 04069 04070 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 04071 Created: 6/10/99 04072 Inputs: the transformation to perform 04073 Returns: - 04074 Purpose: Currently this simply flushes the cached points map. 04075 SeeAlso: - 04076 04077 ********************************************************************************************/ 04078 04079 void AttrBrushType::Transform(TransformBase &Trans) 04080 { 04081 #ifdef NEWFASTBRUSHES 04082 if (m_Value.GetCachedBitmap ()) 04083 { 04084 m_Value.GetCachedBitmap ()->Transform (Trans); 04085 } 04086 // else 04087 // { 04088 #endif 04089 04090 if (!Trans.bSolidDrag) 04091 { 04092 // CGS: my new TransformCache function is three 04093 // times faster than doing it this way! 04094 m_Value.TransformCache(Trans); 04095 m_Value.TransformTimeStampList(Trans); 04096 m_Value.TransformCachedRect(Trans); 04097 } 04098 else 04099 { 04100 // Phil, 10/03/2004 04101 // It may be faster but it doesn't do the job properly during solid dragging. 04102 // The following version works better for solid dragging and ought to be 04103 // reasonably fast because it still uses the cached bounding rect 04104 FlushCache(); 04105 m_Value.TransformCachedRect(Trans); 04106 } 04107 04108 //#ifdef NEWFASTBRUSHES 04109 //} 04110 //#endif 04111 04112 } 04113 04114 /******************************************************************************************** 04115 04116 > void AttrBrushType::FlushCache() 04117 04118 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 04119 Created: 6/10/99 04120 Inputs: - 04121 Returns: - 04122 Purpose: interface to the BrushAttrValue, tells it to flush the cache of its path processor 04123 SeeAlso: - 04124 04125 ********************************************************************************************/ 04126 04127 void AttrBrushType::FlushCache() 04128 { 04129 m_Value.FlushCache(); 04130 } 04131 04132 04133 /******************************************************************************************** 04134 04135 > BOOL AttrBrushType::OnReplaceAttribute(AttrBrushType* pOther) 04136 04137 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 04138 Created: 6/10/99 04139 Inputs: pOther - the attribute we are about to replace 04140 Returns: TRUE if successful, FALSE otherwise 04141 Purpose: If we are applying this attribute to a node that already has a brush attribute then 04142 we wish to retain certain information,so copy it over before we do the replacing. 04143 SeeAlso: - 04144 04145 ********************************************************************************************/ 04146 04147 BOOL AttrBrushType::OnReplaceAttribute(AttrBrushType* pOther) 04148 { 04149 ERROR2IF(pOther == NULL, FALSE, "Null input pointer to AttrBrushType::OnReplaceAttribute"); 04150 04151 PathProcessorBrush* pOldPPB = pOther->GetPathProcessor(); 04152 PathProcessorBrush* pNewPPB = GetPathProcessor(); 04153 if (pOldPPB != NULL && pNewPPB != NULL) 04154 { 04155 pNewPPB->SetUseLocalFillColour(pOldPPB->GetUseLocalFillColour()); 04156 pNewPPB->SetUseNamedColours(pOldPPB->GetUseNamedColours()); 04157 } 04158 04159 // if we have a pressure cache then we want to copy that, also use local colour flags 04160 CDistanceSampler* pPressure = pOther->GetPressureCache(); 04161 if (pPressure) 04162 { 04163 CDistanceSampler* pCopyPressure = pPressure->MakeCopy(); 04164 if (pCopyPressure) 04165 SetPressureCache(pCopyPressure); 04166 } 04167 04168 return TRUE; 04169 } 04170 04171 /******************************************************************************************** 04172 04173 > void AttrBrushType::NodePathUpdated(Path* pPAth) 04174 04175 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 04176 Created: 6/10/99 04177 Inputs: InkPath of the nodepath 04178 Returns: - 04179 Purpose: interface to the BrushAttrValue, called when a nodepath is updated, either flushes 04180 the cache or recalculates the timestamping points distances 04181 SeeAlso: - 04182 04183 ********************************************************************************************/ 04184 04185 void AttrBrushType::NodePathUpdated(Path* pPath) 04186 { 04187 // so far as coordinates go, if we are not timestamping then we just flush our cache 04188 if (!IsTimeStamping()) 04189 m_Value.FlushCache(); 04190 else 04191 m_Value.RecalculateTimeStampList(pPath); 04192 04193 04194 // clear our cached bounding rect 04195 m_Value.SetCachedRect(DocRect(0,0,0,0)); 04196 } 04197 04198 04199 /******************************************************************************************** 04200 04201 > BOOL AttrBrushType::IsParentSelected(); 04202 04203 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 04204 Created: 6/10/99 04205 Inputs: - 04206 Returns: TRUE if any ancestor of the brush attribute is selected, FALSE otherwise 04207 Purpose: To find out if this brush belongs to an ink node that is selected. We simpy 04208 scan up the tree until we find a selected node or hit the layer. 04209 SeeAlso: - 04210 04211 ********************************************************************************************/ 04212 04213 BOOL AttrBrushType::IsParentSelected() 04214 { 04215 BOOL Retval = FALSE; 04216 Node* pParent = FindParent(); 04217 while (pParent != NULL && !pParent->IsLayer()) 04218 { 04219 if (pParent->IsSelected()) 04220 { 04221 Retval = TRUE; 04222 break; 04223 } 04224 pParent = pParent->FindParent(); 04225 } 04226 return Retval; 04227 } 04228 04229 /******************************************************************************************** 04230 04231 > void AttrBrushType::SetCache(PointsMap* pMap) 04232 04233 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 04234 Created: 6/10/99 04235 Inputs: - 04236 Returns: - 04237 Purpose: interface to the BrushAttrValue, sets the cache 04238 SeeAlso: - 04239 04240 ********************************************************************************************/ 04241 04242 void AttrBrushType::SetCache(PointsMap* pMap) 04243 { 04244 m_Value.SetCache(pMap); 04245 } 04246 04247 /******************************************************************************************** 04248 04249 > PointsMap* AttrBrushType::GetCache() 04250 04251 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 04252 Created: 6/10/99 04253 Inputs: - 04254 Returns: pointer to the points map of the brushattrvalue 04255 Purpose: interface to the BrushAttrValue, gets the cache 04256 SeeAlso: - 04257 04258 ********************************************************************************************/ 04259 04260 PointsMap* AttrBrushType::GetCache() 04261 { 04262 return m_Value.GetCache(); 04263 } 04264 04265 04266 /******************************************************************************************** 04267 04268 > PressureArray* AttrBrushType::GetPressureCache() 04269 04270 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 04271 Created: 6/10/99 04272 Inputs: - 04273 Returns: pointer to the points map of the brushattrvalue 04274 Purpose: interface to the BrushAttrValue, gets the pressure cache 04275 SeeAlso: - 04276 04277 ********************************************************************************************/ 04278 04279 BOOL AttrBrushType::ContainsPressureCache() 04280 { 04281 return (m_Value.GetPressureCache() != NULL); 04282 } 04283 04284 /******************************************************************************************** 04285 04286 > PressureArray* AttrBrushType::GetPressureCache() 04287 04288 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 04289 Created: 6/10/99 04290 Inputs: - 04291 Returns: pointer to the points map of the brushattrvalue 04292 Purpose: interface to the BrushAttrValue, gets the pressure cache 04293 SeeAlso: - 04294 04295 ********************************************************************************************/ 04296 04297 CDistanceSampler* AttrBrushType::GetPressureCache() 04298 { 04299 return m_Value.GetPressureCache(); 04300 } 04301 04302 04303 /******************************************************************************************** 04304 04305 > void AttrBrushType::SetPressureCache(PressureArray* pArray) 04306 04307 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 04308 Created: 6/10/99 04309 Inputs: array holding pressure values 04310 Returns: - 04311 Purpose: interface to the BrushAttrValue, sets the cache 04312 SeeAlso: - 04313 04314 ********************************************************************************************/ 04315 04316 void AttrBrushType::SetPressureCache(CDistanceSampler* pCache) 04317 { 04318 m_Value.SetPresssureCache(pCache); 04319 } 04320 04321 /******************************************************************************************** 04322 04323 > BOOL AttrBrushType::ReversePressureCache() 04324 04325 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 04326 Created: 23/5/2000 04327 Inputs: - 04328 Outputs: - 04329 Returns: TRUE if all went well, otherwise false 04330 Purpose: Asks the attribute value to reverse its pressure list 04331 See Also: BrushAttrValue::ReversePressureList 04332 ********************************************************************************************/ 04333 04334 BOOL AttrBrushType::ReversePressureCache() 04335 { 04336 CDistanceSampler* pCache = GetPressureCache(); 04337 return pCache->ReverseData(); 04338 } 04339 04340 /******************************************************************************************** 04341 04342 > TimeStampList* AttrBrushType::GetTimeStampList() 04343 04344 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 04345 Created: 6/10/99 04346 Inputs: - 04347 Returns: pointer to the timestamp points list of the brushattrvalue 04348 Purpose: interface to the BrushAttrValue, gets the cache 04349 SeeAlso: - 04350 04351 ********************************************************************************************/ 04352 04353 TimeStampList* AttrBrushType::GetTimeStampList() 04354 { 04355 return m_Value.GetTimeStampList(); 04356 } 04357 04358 /******************************************************************************************** 04359 04360 > BOOL AttrBrushType::IsTimeStamping() 04361 04362 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 04363 Created: 6/10/99 04364 Inputs: - 04365 Returns: TRUE if we are timestamping, or FALSE if not 04366 Purpose: interface to the BrushAttrValue 04367 SeeAlso: - 04368 04369 ********************************************************************************************/ 04370 04371 BOOL AttrBrushType::IsTimeStamping() 04372 { 04373 return m_Value.IsTimeStamping(); 04374 } 04375 04376 04377 /******************************************************************************************** 04378 04379 > void AttrBrushType::ClearCachedRect() 04380 04381 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 04382 Created: 6/10/99 04383 Inputs: - 04384 Returns: - 04385 Purpose: interface to the BrushAttrValue, wipes the cached bounding rect 04386 SeeAlso: - 04387 04388 ********************************************************************************************/ 04389 04390 void AttrBrushType::ClearCachedRect() 04391 { 04392 m_Value.SetCachedRect(DocRect(0,0,0,0)); 04393 } 04394 04395 04396 void AttrBrushType::SetFreeHandTool(FreeHandTool* pTool) 04397 { 04398 m_pFreeTool = pTool; 04399 } 04400 04401 /******************************************************************************************** 04402 04403 > static void AttrBrushType::RotateBounds(double Angle, DocRect* pBounds) 04404 04405 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 04406 Created: 8/2/2000 04407 Inputs: Bounds = the bounds to rotate 04408 Angle = the angle in degrees by which to rotate it by 04409 Outputs: Bounds is updated 04410 Returns: TRUE, unless you try to pass in a dud rect 04411 Purpose: The bounds are updated to contain the rotated version 04412 SeeAlso: - 04413 04414 ********************************************************************************************/ 04415 04416 BOOL AttrBrushType::RotateBounds(double Angle, DocRect* pBounds) 04417 { 04418 ERROR2IF(pBounds == NULL, FALSE, "DocRect is NULL"); 04419 if (Angle != 0.0) 04420 { 04421 DocCoord BBCentre = pBounds->Centre(); 04422 04423 DocCoord Coords[4]; 04424 Coords[0].x = pBounds->lo.x; Coords[0].y = pBounds->lo.y; 04425 Coords[1].x = pBounds->hi.x; Coords[1].y = pBounds->lo.y; 04426 Coords[2].x = pBounds->hi.x; Coords[2].y = pBounds->hi.y; 04427 Coords[3].x = pBounds->lo.x; Coords[3].y = pBounds->hi.y; 04428 04429 Trans2DMatrix Rotate(BBCentre,Angle); 04430 Rotate.Transform(Coords,4); 04431 04432 pBounds->lo.x = min(min(Coords[0].x,Coords[1].x), min(Coords[2].x,Coords[3].x)); 04433 pBounds->hi.x = max(max(Coords[0].x,Coords[1].x), max(Coords[2].x,Coords[3].x)); 04434 pBounds->lo.y = min(min(Coords[0].y,Coords[1].y), min(Coords[2].y,Coords[3].y)); 04435 pBounds->hi.y = max(max(Coords[0].y,Coords[1].y), max(Coords[2].y,Coords[3].y)); 04436 } 04437 return TRUE; 04438 } 04439 04440 /******************************************************************************************** 04441 04442 > virtual BOOL AttrBrushType::WritePreChildrenWeb(BaseCamelotFilter *pFilter) 04443 > virtual BOOL AttrBrushType::WritePreChildrenNative(BaseCamelotFilter *pFilter) 04444 04445 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 04446 Created: 13/12/99 04447 04448 Inputs: pFilter - filter to write to 04449 04450 Returns: TRUE if the Node has written out a record to the filter 04451 04452 Purpose: Writes out a record that represents the node, to either Native or Web 04453 file format. 04454 04455 This function is called before any of the AttrBrushType's children 04456 are written to the filter. 04457 04458 If the AttrBrushType writes out a record successfully to the file, 04459 it will return TRUE. 04460 04461 If the AttrBrushType chooses not to write itself to the filter 04462 (e.g. because it is not appropriate for this filter), then this 04463 function will return FALSE. 04464 04465 Notes: Simple Brushs (not using fancy bitmap/vector brushes) just 04466 write out a 4-byte (UINT32) record containing the stroke type. 04467 Defined stroke types at this time are: 04468 0 - Simple variable width stroke 04469 04470 SeeAlso: Node::WritePreChildrenNative; Node::WritePreChildrenWeb; 04471 StrokeAttrRecordHandler::HandleRecord 04472 04473 ********************************************************************************************/ 04474 04475 BOOL AttrBrushType::WritePreChildrenWeb(BaseCamelotFilter *pFilter) 04476 { 04477 return(WritePreChildrenNative(pFilter)); 04478 } 04479 04480 BOOL AttrBrushType::WritePreChildrenNative(BaseCamelotFilter *pFilter) 04481 { 04482 //return TRUE; 04483 04484 ERROR2IF(pFilter == NULL, FALSE, "Illegal NULL param"); 04485 04486 BOOL ok = TRUE; 04487 PathProcessorBrush *pProcessor = m_Value.GetPathProcessor(); 04488 04489 if (pProcessor != NULL) 04490 { 04491 // first try and get the definition stored in the brush component 04492 BrushHandle Handle = pProcessor->GetBrushDefinitionHandle(); 04493 04494 // also check that the definition exists, as we do not want to save out deactivated brushes 04495 BrushDefinition* pDef = BrushComponent::FindBrushDefinition(Handle); 04496 04497 if (Handle != BrushHandle_NoBrush && pDef != NULL) 04498 { 04499 // now get the brush component from the document (bit longwinded this but it 04500 // ensures that each brush only gets written once) 04501 Document* pDoc = Document::GetCurrent(); 04502 ERROR2IF(pDoc == NULL, FALSE, "Er, wheres the document gone?"); 04503 BrushComponent* pBrushComp = (BrushComponent*)pDoc->GetDocComponent(CC_RUNTIME_CLASS(BrushComponent)); 04504 ERROR2IF(pBrushComp == NULL, FALSE, "Couldn't find brush component"); 04505 04506 // finally lets write the definition 04507 ok = pBrushComp->ExportLine(pFilter, Handle); 04508 04509 if (ok) ok = pProcessor->WriteNative(pFilter); 04510 04511 // now write our timestamping and pressure data 04512 if (IsTimeStamping()) 04513 if (ok) ok = m_Value.WriteTimeStampList(pFilter); 04514 04515 if (ContainsPressureCache()) 04516 if (ok) ok = m_Value.WritePressureData(pFilter); 04517 04518 } 04519 } 04520 else 04521 { 04522 //ERROR3("Trying to write empty attribute"); 04523 // return FALSE; 04524 } 04525 04526 return ok; 04527 } 04528 04529 04530 04531 04532 04533 04534 /*------------------------------------------------------------------------------------------ 04535 -----------------BRUSH ATTRIBUTE RECORD HANDLER -------------------------------------------- 04536 --------------------------------------------------------------------------------------------*/ 04537 04538 04539 // initialise our static 04540 AttrBrushType* BrushAttrRecordHandler::m_pLastAttribute = NULL; 04541 04542 04543 /******************************************************************************************** 04544 04545 > virtual UINT32 *BrushAttrRecordHandler::GetTagList() 04546 04547 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 04548 Created: 7/1/97 04549 04550 Returns: A list of tag values, terminated by CXFRH_TAG_LIST_END 04551 04552 Purpose: Provides the record handler system with a list of records handled by this 04553 handler - all StrokeType attributes: 04554 04555 SeeAlso: BrushTypeAttrRecordHandler::HandleRecord 04556 04557 ********************************************************************************************/ 04558 04559 UINT32 *BrushAttrRecordHandler::GetTagList() 04560 { 04561 static UINT32 TagList[] = 04562 { 04563 TAG_BRUSHDEFINITION, 04564 TAG_BRUSHATTR, 04565 TAG_BRUSHDATA, 04566 TAG_MOREBRUSHDATA, 04567 TAG_MOREBRUSHATTR, 04568 TAG_EVENMOREBRUSHDATA, 04569 TAG_EVENMOREBRUSHATTR, 04570 TAG_TIMESTAMPBRUSHDATA, 04571 TAG_BRUSHPRESSUREINFO, 04572 TAG_BRUSHATTRPRESSUREINFO, 04573 TAG_BRUSHPRESSUREDATA, 04574 TAG_BRUSHPRESSURESAMPLEDATA, 04575 TAG_BRUSHATTRFILLFLAGS, 04576 TAG_BRUSHTRANSPINFO, 04577 TAG_BRUSHATTRTRANSPINFO, 04578 CXFRH_TAG_LIST_END 04579 }; 04580 04581 return(TagList); 04582 } 04583 04584 04585 04586 /******************************************************************************************** 04587 04588 > virtual BOOL BrushAttrRecordHandler::HandleRecord(CXaraFileRecord *pCXaraFileRecord) 04589 04590 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 04591 Created: 21/12/99 04592 04593 Inputs: pCXaraFileRecord - The record to handle - may not be NULL 04594 Returns: TRUE if handled successfuly 04595 04596 Purpose: Handles loading of the given AttrBrushType attribute record 04597 04598 04599 04600 ********************************************************************************************/ 04601 04602 BOOL BrushAttrRecordHandler::HandleRecord(CXaraFileRecord *pCXaraFileRecord) 04603 { 04604 ERROR3IF(pCXaraFileRecord == NULL, "pCXaraFileRecord is NULL"); 04605 04606 // NodeAttribute* pNewNode = NULL; 04607 BOOL RetVal = TRUE; 04608 switch (pCXaraFileRecord->GetTag()) 04609 { 04610 case TAG_BRUSHDEFINITION: 04611 { 04612 // get the brush component from the document 04613 Document* pDoc = Document::GetCurrent(); 04614 ERROR2IF(pDoc == NULL, FALSE, "Wheres the document?"); 04615 BrushComponent* pBrushComp = (BrushComponent*)pDoc->GetDocComponent(CC_RUNTIME_CLASS(BrushComponent)); 04616 ERROR2IF(pBrushComp == NULL, FALSE, "No brush component"); 04617 UINT32 ImportHandle = 0; 04618 BOOL ok = pCXaraFileRecord->ReadUINT32(&ImportHandle); 04619 04620 if (ok) 04621 RetVal = pBrushComp->StartImportBrush(this, pCXaraFileRecord, ImportHandle); 04622 } 04623 break; 04624 case TAG_BRUSHDATA: 04625 RetVal = HandleBrushDataRecord(pCXaraFileRecord); 04626 break; 04627 case TAG_BRUSHATTR: 04628 RetVal = HandleBrushAttributeRecord(pCXaraFileRecord); 04629 break; 04630 case TAG_MOREBRUSHDATA: 04631 RetVal = HandleMoreBrushDataRecord(pCXaraFileRecord); 04632 break; 04633 case TAG_MOREBRUSHATTR: 04634 RetVal = HandleMoreBrushAttrRecord(pCXaraFileRecord); 04635 break; 04636 case TAG_EVENMOREBRUSHDATA: 04637 RetVal = HandleEvenMoreBrushData(pCXaraFileRecord); 04638 break; 04639 case TAG_EVENMOREBRUSHATTR: 04640 RetVal = HandleEvenMoreBrushAttr(pCXaraFileRecord); 04641 break; 04642 case TAG_TIMESTAMPBRUSHDATA: 04643 RetVal = HandleTimeStampData(pCXaraFileRecord); 04644 break; 04645 case TAG_BRUSHPRESSUREINFO: 04646 RetVal = HandlePressureInfo(pCXaraFileRecord); 04647 break; 04648 case TAG_BRUSHATTRPRESSUREINFO: 04649 RetVal = HandleAttrPressureInfo(pCXaraFileRecord); 04650 break; 04651 case TAG_BRUSHPRESSUREDATA: 04652 RetVal = HandlePressureData(pCXaraFileRecord); 04653 break; 04654 case TAG_BRUSHPRESSURESAMPLEDATA: 04655 RetVal = HandlePressureSampleData(pCXaraFileRecord); 04656 break; 04657 case TAG_BRUSHATTRFILLFLAGS: 04658 RetVal = HandleAttrFillFlags(pCXaraFileRecord); 04659 break; 04660 case TAG_BRUSHTRANSPINFO: 04661 RetVal = HandleTranspInfo(pCXaraFileRecord); 04662 break; 04663 case TAG_BRUSHATTRTRANSPINFO: 04664 RetVal = HandleAttrTranspInfo(pCXaraFileRecord); 04665 break; 04666 default: 04667 ERROR3_PF(("I don't handle records with the tag (%d)\n", pCXaraFileRecord->GetTag())); 04668 break; 04669 } 04670 04671 return(RetVal); 04672 } 04673 04674 04675 /******************************************************************************************** 04676 04677 > BOOL BrushAttrRecordHandler::HandleBrushAttributeRecord(CXaraFileRecord* pRecord) 04678 04679 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 04680 Created: 21/12/99 04681 04682 Inputs: pRecord - the file record holding the data 04683 Returns: TRUE if brush attribute was successfully read and created, otherwise FALSE 04684 Purpose: Reads in data which it uses to create a new AttrBrushType node 04685 04686 ********************************************************************************************/ 04687 04688 BOOL BrushAttrRecordHandler::HandleBrushAttributeRecord(CXaraFileRecord* pRecord) 04689 { 04690 ERROR2IF(pRecord == NULL, FALSE, "Record is NULL"); 04691 04692 // first read in all the data 04693 UINT32 Handle = 0x01000000; 04694 INT32 TempOffsetType = 0; 04695 INT32 TempOffsetValue = 0; 04696 INT32 TempSpacing = 10000; 04697 BYTE Flags; 04698 double TempRotateAngle = 0.0; 04699 double TempScaling = 1.0; 04700 // Import the data from the record 04701 if (!pRecord->ReadUINT32(&Handle) || !pRecord->ReadINT32(&TempSpacing) || 04702 !pRecord->ReadBYTE(&Flags) || !pRecord->ReadDOUBLE(&TempRotateAngle) 04703 || !pRecord->ReadINT32(&TempOffsetType) || !pRecord->ReadINT32(&TempOffsetValue) 04704 || !pRecord->ReadDOUBLE(&TempScaling)) 04705 { 04706 return(FALSE); 04707 } 04708 04709 // allocate tge new node 04710 NodeAttribute* pNewNode = new AttrBrushType; 04711 ERROR2IF(pNewNode == NULL, FALSE, "Unable to allocate node attribute"); 04712 04713 // get the brush component from the document 04714 Document* pDoc = Document::GetCurrent(); 04715 ERROR2IF(pDoc == NULL, FALSE, "Wheres the document?"); 04716 BrushComponent* pBrushComp = (BrushComponent*)pDoc->GetDocComponent(CC_RUNTIME_CLASS(BrushComponent)); 04717 ERROR2IF(pBrushComp == NULL, FALSE, "No brush component"); 04718 04719 // find the brush definition that this brush uses 04720 BrushHandle NewHandle = pBrushComp->FindImportedBrush(Handle); 04721 04722 // allocate a new path processor 04723 PathProcessorBrush* pNewPathProc = new PathProcessorBrush; 04724 ERROR2IF(pNewPathProc == NULL, FALSE, "Unable to allocate path processor"); 04725 // tell it which brush definition to use 04726 pNewPathProc->SetBrushDefinition(NewHandle); 04727 04728 // transfer all the data 04729 pNewPathProc->SetSpacing(TempSpacing); 04730 PathOffset Offset = (PathOffset)TempOffsetType; 04731 pNewPathProc->SetPathOffsetType(Offset); 04732 pNewPathProc->SetPathOffsetValue(TempOffsetValue); 04733 pNewPathProc->SetRotationAngle(TempRotateAngle); 04734 pNewPathProc->SetBrushScaling(TempScaling); 04735 04736 BOOL bTile = Flags & TAG_BRUSHTILE_FLAG; 04737 BOOL bRotate = Flags & TAG_BRUSHROTATE_FLAG; 04738 pNewPathProc->SetRotated(bRotate); 04739 pNewPathProc->SetTiling(bTile); 04740 04741 // now allocate the processor to the AttributeValue 04742 BrushAttrValue* pBrushAttrValue = (BrushAttrValue*)pNewNode->GetAttributeValue(); 04743 ERROR2IF(pBrushAttrValue == NULL, FALSE, "Brush attribute value is NULL"); 04744 pBrushAttrValue->SetPathProcessor(pNewPathProc); 04745 04746 // tell the processor who's the boss 04747 pNewPathProc->SetParentAttribute((AttrBrushType*)pNewNode); 04748 04749 InsertNode(pNewNode); 04750 04751 04752 // set the static member, as there may be more data to come 04753 m_pLastAttribute = (AttrBrushType*)pNewNode; 04754 04755 m_pLastAttribute->GetMaxScalingFromDefinition(); 04756 04757 return TRUE; 04758 04759 } 04760 04761 04762 /******************************************************************************************** 04763 04764 > BOOL BrushAttrRecordHandler::HandleBrushAttributeRecord(CXaraFileRecord* pRecord) 04765 04766 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 04767 Created: 21/12/99 04768 04769 Inputs: pRecord - the file record holding the data 04770 Returns: TRUE if all went well, otherwise FALSE 04771 Purpose: Reads in data and assigns it to the previously created BrushDefinition. 04772 04773 ********************************************************************************************/ 04774 04775 BOOL BrushAttrRecordHandler::HandleBrushDataRecord(CXaraFileRecord* pRecord) 04776 { 04777 ERROR2IF(pRecord == NULL, FALSE, "Record is NULL"); 04778 04779 // first read in all the data 04780 UINT32 Handle = 0x01000000; 04781 INT32 TempOffsetType = 0; 04782 INT32 TempOffsetValue = 0; 04783 INT32 TempSpacing = 10000; 04784 BYTE Flags; 04785 String_32 TempName; 04786 double TempScaling = 1.0; 04787 double TempRotateAngle = 0.0; 04788 // Import the data from the record 04789 if (!pRecord->ReadUINT32(&Handle) || !pRecord->ReadINT32(&TempSpacing) || 04790 !pRecord->ReadBYTE(&Flags) || !pRecord->ReadDOUBLE(&TempRotateAngle) 04791 || !pRecord->ReadINT32(&TempOffsetType) || !pRecord->ReadINT32(&TempOffsetValue) 04792 || !pRecord->ReadUnicode(&TempName) || !pRecord->ReadDOUBLE(&TempScaling)) 04793 { 04794 return(FALSE); 04795 } 04796 04797 // convert the variables that were not stored as their original type 04798 PathOffset Offset = (PathOffset)TempOffsetType; 04799 BOOL bTile = Flags & TAG_BRUSHTILE_FLAG; 04800 BOOL bRotate = Flags & TAG_BRUSHROTATE_FLAG; 04801 04802 // If there is a name to be imported, read it as well 04803 //if (!pRecord->ReadUnicode(&TempName)) 04804 // return(FALSE); 04805 04806 // We remember the imported flags and suchlike, which we will use in EndImportLine. 04807 // TempName.Left((StringBase *)&m_ImportedName, 31); 04808 04809 // Now we need to retrieve the previously generated brush definition and assign all 04810 // this lovely data to it. Note that for this to be successful it is vital that 04811 // BrushComponent::StartImportBrush be called prior to this in the import 04812 04813 // get the brush component from the document 04814 Document* pDoc = Document::GetCurrent(); 04815 ERROR2IF(pDoc == NULL, FALSE, "Wheres the document?"); 04816 BrushComponent* pBrushComp = (BrushComponent*)pDoc->GetDocComponent(CC_RUNTIME_CLASS(BrushComponent)); 04817 ERROR2IF(pBrushComp == NULL, FALSE, "No brush component"); 04818 04819 // find the brush definition that is currently being imported 04820 BrushDefinition* pBrushDef = pBrushComp->GetImportBrushDefinition(); 04821 04822 if (pBrushDef != NULL) 04823 { 04824 // assign the new data to it 04825 pBrushDef->SetSpacing(TempSpacing); 04826 pBrushDef->SetTiling(bTile); 04827 pBrushDef->SetRotated(bRotate); 04828 pBrushDef->SetRotationAngle(TempRotateAngle); 04829 pBrushDef->SetPathOffsetType(Offset); 04830 pBrushDef->SetPathOffsetValue(TempOffsetValue); 04831 pBrushDef->SetLineName(&TempName); 04832 pBrushDef->SetBrushScaling(1.0); 04833 } 04834 // else 04835 // return FALSE; 04836 04837 04838 return TRUE; 04839 } 04840 04841 04842 /******************************************************************************************** 04843 04844 > BOOL BrushAttrRecordHandler::HandleMoreBrushDataRecord(CXaraFileRecord* pRecord) 04845 04846 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 04847 Created: 21/12/99 04848 04849 Inputs: pRecord - the file record holding the data 04850 Returns: TRUE if all went well, otherwise FALSE 04851 Purpose: Reads in data and assigns it to the previously created BrushDefinition. 04852 04853 ********************************************************************************************/ 04854 04855 BOOL BrushAttrRecordHandler::HandleMoreBrushDataRecord(CXaraFileRecord* pRecord) 04856 { 04857 ERROR2IF(pRecord == NULL, FALSE, "Record is NULL"); 04858 04859 // get the variables to read into 04860 double SpacingIncrProp = 1.0; 04861 INT32 SpacingIncrConst = 0; 04862 INT32 SpacingMaxRand = 0; 04863 INT32 SpacingRandSeed = 0; 04864 double ScalingIncr = 1.0; 04865 INT32 ScalingMaxRand = 0; 04866 INT32 ScalingRandSeed = 0; 04867 INT32 Sequence = SEQ_FORWARD; 04868 INT32 SequenceRandSeed = 0; 04869 double OffsetIncrProp = 1.0; 04870 INT32 OffsetIncrConst = 0; 04871 INT32 OffsetTypeRandSeed = 0; 04872 INT32 OffsetValMaxRand = 0; 04873 INT32 OffsetValRandSeed = 0; 04874 04875 if (!pRecord->ReadDOUBLE(&SpacingIncrProp) || !pRecord->ReadINT32(&SpacingIncrConst) || 04876 !pRecord->ReadINT32(&SpacingMaxRand) || !pRecord->ReadINT32(&SpacingRandSeed) || 04877 !pRecord->ReadDOUBLE(&ScalingIncr) || !pRecord->ReadINT32(&ScalingMaxRand) || 04878 !pRecord->ReadINT32(&ScalingRandSeed) || !pRecord->ReadINT32(&Sequence) || 04879 !pRecord->ReadINT32(&SequenceRandSeed) || !pRecord->ReadDOUBLE(&OffsetIncrProp) || 04880 !pRecord->ReadINT32(&OffsetIncrConst) || !pRecord->ReadINT32(&OffsetTypeRandSeed) || 04881 !pRecord->ReadINT32(&OffsetValMaxRand) || !pRecord->ReadINT32(&OffsetValRandSeed) 04882 ) 04883 return FALSE; 04884 04885 // get the brush component from the document 04886 Document* pDoc = Document::GetCurrent(); 04887 ERROR2IF(pDoc == NULL, FALSE, "Wheres the document?"); 04888 BrushComponent* pBrushComp = (BrushComponent*)pDoc->GetDocComponent(CC_RUNTIME_CLASS(BrushComponent)); 04889 ERROR2IF(pBrushComp == NULL, FALSE, "No brush component"); 04890 04891 // find the brush definition that is currently being imported 04892 BrushDefinition* pBrushDef = pBrushComp->GetImportBrushDefinition(); 04893 04894 if (pBrushDef != NULL) 04895 { 04896 pBrushDef->SetSpacingIncrProp(SpacingIncrProp); 04897 pBrushDef->SetSpacingIncrConst((UINT32)SpacingIncrConst); 04898 pBrushDef->SetSpacingMaxRand((UINT32)SpacingMaxRand); 04899 pBrushDef->SetSpacingRandSeed((UINT32)SpacingRandSeed); 04900 pBrushDef->SetBrushScalingIncr(ScalingIncr); 04901 pBrushDef->SetScalingMaxRand((UINT32)ScalingMaxRand); 04902 pBrushDef->SetScalingRandSeed((UINT32)ScalingRandSeed); 04903 pBrushDef->SetSequenceType((SequenceType)Sequence); 04904 pBrushDef->SetSequenceSeed(SequenceRandSeed); 04905 pBrushDef->SetPathOffsetIncrProp(OffsetIncrProp); 04906 pBrushDef->SetPathOffsetIncrConst((UINT32)OffsetIncrConst); 04907 pBrushDef->SetOffsetTypeRandSeed((UINT32)OffsetTypeRandSeed); 04908 pBrushDef->SetOffsetValueMaxRand((UINT32)OffsetValMaxRand); 04909 pBrushDef->SetOffsetValueRandSeed((UINT32)OffsetValRandSeed); 04910 } 04911 04912 return TRUE; 04913 04914 } 04915 04916 04917 /******************************************************************************************** 04918 04919 > BOOL BrushAttrRecordHandler::HandleMoreBrushAttrRecord(CXaraFileRecord* pRecord) 04920 04921 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 04922 Created: 21/12/99 04923 04924 Inputs: pRecord - the file record holding the data 04925 Returns: TRUE if all went well, otherwise FALSE 04926 Purpose: reads in the same data as previous fn. but assigns it to the path processor 04927 of 04928 04929 ********************************************************************************************/ 04930 04931 BOOL BrushAttrRecordHandler::HandleMoreBrushAttrRecord(CXaraFileRecord* pRecord) 04932 { 04933 ERROR2IF(pRecord == NULL, FALSE, "Record is NULL"); 04934 // we must have a node to import to 04935 ERROR2IF(m_pLastAttribute == NULL, FALSE, "No last attribute to import to"); 04936 04937 // get some variables to read into 04938 double SpacingIncrProp = 1.0; 04939 INT32 SpacingIncrConst = 0; 04940 INT32 SpacingMaxRand = 0; 04941 INT32 SpacingRandSeed = 0; 04942 double ScalingIncr = 1.0; 04943 INT32 ScalingMaxRand = 0; 04944 INT32 ScalingRandSeed = 0; 04945 INT32 Sequence = SEQ_FORWARD; 04946 INT32 SequenceRandSeed = 0; 04947 double OffsetIncrProp = 1.0; 04948 INT32 OffsetIncrConst = 0; 04949 INT32 OffsetTypeRandSeed = 0; 04950 INT32 OffsetValMaxRand = 0; 04951 INT32 OffsetValRandSeed = 0; 04952 INT32 UseLocalFill = -1; 04953 04954 if (!pRecord->ReadDOUBLE(&SpacingIncrProp) || !pRecord->ReadINT32(&SpacingIncrConst) || 04955 !pRecord->ReadINT32(&SpacingMaxRand) || !pRecord->ReadINT32(&SpacingRandSeed) || 04956 !pRecord->ReadDOUBLE(&ScalingIncr) || !pRecord->ReadINT32(&ScalingMaxRand) || 04957 !pRecord->ReadINT32(&ScalingRandSeed) || !pRecord->ReadINT32(&Sequence) || 04958 !pRecord->ReadINT32(&SequenceRandSeed) || !pRecord->ReadDOUBLE(&OffsetIncrProp) || !pRecord->ReadINT32(&OffsetIncrConst) || 04959 !pRecord->ReadINT32(&OffsetTypeRandSeed) || !pRecord->ReadINT32(&OffsetValMaxRand) || 04960 !pRecord->ReadINT32(&OffsetValRandSeed) || !pRecord->ReadINT32(&UseLocalFill) 04961 ) 04962 return FALSE; 04963 04964 // now get the path processor belonging to the last attribute 04965 PathProcessorBrush* pPathProc = m_pLastAttribute->GetPathProcessor(); 04966 04967 // if there isn't a path processor thats ok, as it may be default 04968 if (pPathProc == NULL) 04969 return TRUE; 04970 else 04971 { 04972 pPathProc->SetSpacingIncrProp(SpacingIncrProp); 04973 pPathProc->SetSpacingIncrConst((UINT32)SpacingIncrConst); 04974 pPathProc->SetSpacingMaxRand((UINT32)SpacingMaxRand); 04975 pPathProc->SetSpacingRandSeed((UINT32)SpacingRandSeed); 04976 pPathProc->SetBrushScalingIncr(ScalingIncr); 04977 pPathProc->SetScalingMaxRand((UINT32)ScalingMaxRand); 04978 pPathProc->SetScalingRandSeed((UINT32)ScalingRandSeed); 04979 pPathProc->SetSequenceType((SequenceType)Sequence); 04980 pPathProc->SetSequenceSeed(SequenceRandSeed); 04981 pPathProc->SetPathOffsetIncrProp(OffsetIncrProp); 04982 pPathProc->SetPathOffsetIncrConst((UINT32)OffsetIncrConst); 04983 pPathProc->SetOffsetTypeRandSeed((UINT32)OffsetTypeRandSeed); 04984 pPathProc->SetOffsetValueMaxRand((UINT32)OffsetValMaxRand); 04985 pPathProc->SetOffsetValueRandSeed((UINT32)OffsetValRandSeed); 04986 BOOL UseFill = UseLocalFill > 0 ? TRUE : FALSE; 04987 pPathProc->SetUseLocalFillColour(UseFill); 04988 04989 // gotta set these for the time being 04990 pPathProc->SetRotationMaxRand(0); 04991 pPathProc->SetRotationRandSeed(0); 04992 } 04993 04994 return TRUE; 04995 } 04996 04997 04998 04999 /******************************************************************************************** 05000 05001 > BOOL BrushAttrRecordHandler::HandleEvenMoreBrushData(CXaraFileRecord* pRecord) 05002 05003 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 05004 Created: 21/12/99 05005 05006 Inputs: pRecord - the file record holding the data 05007 Returns: TRUE if all went well, otherwise FALSE 05008 Purpose: Reads in data and assigns it to the previously created BrushDefinition. 05009 05010 ********************************************************************************************/ 05011 05012 BOOL BrushAttrRecordHandler::HandleEvenMoreBrushData(CXaraFileRecord* pRecord) 05013 { 05014 ERROR2IF(pRecord == NULL, FALSE, "Record is NULL"); 05015 05016 INT32 RotationMaxRand = 0; 05017 INT32 RotationRandSeed = 0; 05018 05019 if (!pRecord->ReadINT32(&RotationMaxRand) || !pRecord->ReadINT32(&RotationRandSeed)) 05020 return FALSE; 05021 05022 // get the brush component from the document 05023 Document* pDoc = Document::GetCurrent(); 05024 ERROR2IF(pDoc == NULL, FALSE, "Wheres the document?"); 05025 BrushComponent* pBrushComp = (BrushComponent*)pDoc->GetDocComponent(CC_RUNTIME_CLASS(BrushComponent)); 05026 ERROR2IF(pBrushComp == NULL, FALSE, "No brush component"); 05027 05028 // find the brush definition that is currently being imported 05029 BrushDefinition* pBrushDef = pBrushComp->GetImportBrushDefinition(); 05030 05031 if (pBrushDef != NULL) 05032 { 05033 pBrushDef->SetRotationMaxRand((UINT32)RotationMaxRand); 05034 pBrushDef->SetRotationRandSeed((UINT32)RotationRandSeed); 05035 } 05036 05037 // tell the component we've finished importing 05038 return TRUE; 05039 } 05040 05041 05042 /******************************************************************************************** 05043 05044 > BOOL BrushAttrRecordHandler::HandleEvenMoreBrushAttr(CXaraFileRecord* pRecord) 05045 05046 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 05047 Created: 21/12/99 05048 05049 Inputs: pRecord - the file record holding the data 05050 Returns: TRUE if all went well, otherwise FALSE 05051 Purpose: Reads in data and assigns it to the previously created node 05052 05053 ********************************************************************************************/ 05054 05055 BOOL BrushAttrRecordHandler::HandleEvenMoreBrushAttr(CXaraFileRecord* pRecord) 05056 { 05057 ERROR2IF(pRecord == NULL, FALSE, "Record is NULL"); 05058 05059 // we must have a node to import to 05060 ERROR2IF(m_pLastAttribute == NULL, FALSE, "No last attribute to import to"); 05061 05062 INT32 RotationMaxRand = 0; 05063 INT32 RotationRandSeed = 0; 05064 BYTE ScaleFlag = 0; 05065 if (!pRecord->ReadINT32(&RotationMaxRand) || !pRecord->ReadINT32(&RotationRandSeed) 05066 || !pRecord->ReadBYTE(&ScaleFlag)) 05067 return FALSE; 05068 05069 05070 // now get the path processor belonging to the last attribute 05071 PathProcessorBrush* pPathProc = m_pLastAttribute->GetPathProcessor(); 05072 05073 // if there isn't a path processor thats ok, as it may be default 05074 if (pPathProc == NULL) 05075 return TRUE; 05076 05077 pPathProc->SetRotationMaxRand((UINT32)RotationMaxRand); 05078 pPathProc->SetRotationRandSeed((UINT32)RotationRandSeed); 05079 05080 BOOL ScaleToLineWidth = ScaleFlag & TAG_SCALETOWIDTH_FLAG; 05081 pPathProc->SetScaleToLineWidth(ScaleToLineWidth); 05082 05083 05084 // set the random hue & sat to zero until we do a tag 05085 /*pPathProc->SetHueMaxRand(0); 05086 pPathProc->SetHueRandSeed(0); 05087 pPathProc->SetSatMaxRand(0); 05088 pPathProc->SetSatRandSeed(0); 05089 pPathProc->SetHueIncrement(1.0); 05090 pPathProc->SetSatIncrement(1.0); 05091 */ 05092 return TRUE; 05093 } 05094 05095 05096 /******************************************************************************************** 05097 05098 > BOOL BrushAttrRecordHandler::HandlePressureInfo(CXaraFileRecord* pRecord) 05099 05100 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 05101 Created: 21/12/99 05102 05103 Inputs: pRecord - the file record holding the data 05104 Returns: TRUE if all went well, otherwise FALSE 05105 Purpose: Reads in data and assigns it to the previously created BrushDefinition. 05106 05107 ********************************************************************************************/ 05108 05109 BOOL BrushAttrRecordHandler::HandlePressureInfo(CXaraFileRecord* pRecord) 05110 { 05111 ERROR2IF(pRecord == NULL, FALSE, "Record is NULL"); 05112 05113 INT32 ScalingPressure = 0; 05114 INT32 SpacingPressure = 0; 05115 INT32 OffsetPressure = 0; 05116 INT32 RotationPressure = 0; 05117 INT32 HuePressure = 0; 05118 INT32 SatPressure = 0; 05119 INT32 TimePressure = 0; 05120 05121 if (!pRecord->ReadINT32(&ScalingPressure) || !pRecord->ReadINT32(&SpacingPressure) || 05122 !pRecord->ReadINT32(&OffsetPressure) || !pRecord->ReadINT32(&RotationPressure) || 05123 !pRecord->ReadINT32(&HuePressure) || !pRecord->ReadINT32(&SatPressure) || 05124 !pRecord->ReadINT32(&TimePressure)) 05125 return FALSE; 05126 05127 // get the brush component from the document 05128 Document* pDoc = Document::GetCurrent(); 05129 ERROR2IF(pDoc == NULL, FALSE, "Wheres the document?"); 05130 BrushComponent* pBrushComp = (BrushComponent*)pDoc->GetDocComponent(CC_RUNTIME_CLASS(BrushComponent)); 05131 ERROR2IF(pBrushComp == NULL, FALSE, "No brush component"); 05132 05133 // find the brush definition that is currently being imported 05134 BrushDefinition* pBrushDef = pBrushComp->GetImportBrushDefinition(); 05135 05136 // currently we only make use of the scaling pressure value, others to follow when I have 05137 // time to implement them 05138 if (pBrushDef != NULL) 05139 { 05140 pBrushDef->SetScalingMaxPressure((UINT32)ScalingPressure); 05141 pBrushDef->SetRotationMaxPressure((UINT32)RotationPressure); 05142 } 05143 05144 return TRUE; 05145 } 05146 05147 05148 /******************************************************************************************** 05149 05150 > BOOL BrushAttrRecordHandler::HandleAttrPressureInfo(CXaraFileRecord* pRecord) 05151 05152 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 05153 Created: 21/12/99 05154 05155 Inputs: pRecord - the file record holding the data 05156 Returns: TRUE if all went well, otherwise FALSE 05157 Purpose: Reads in data and assigns it to the previously created node 05158 05159 ********************************************************************************************/ 05160 05161 BOOL BrushAttrRecordHandler::HandleAttrPressureInfo(CXaraFileRecord* pRecord) 05162 { 05163 ERROR2IF(pRecord == NULL, FALSE, "Record is NULL"); 05164 05165 // we must have a node to import to 05166 ERROR2IF(m_pLastAttribute == NULL, FALSE, "No last attribute to import to"); 05167 05168 INT32 ScalingPressure = 0; 05169 INT32 SpacingPressure = 0; 05170 INT32 OffsetPressure = 0; 05171 INT32 RotationPressure = 0; 05172 INT32 HuePressure = 0; 05173 INT32 SatPressure = 0; 05174 INT32 TimePressure = 0; 05175 05176 if (!pRecord->ReadINT32(&ScalingPressure) || !pRecord->ReadINT32(&SpacingPressure) || 05177 !pRecord->ReadINT32(&OffsetPressure) || !pRecord->ReadINT32(&RotationPressure) || 05178 !pRecord->ReadINT32(&HuePressure) || !pRecord->ReadINT32(&SatPressure) || 05179 !pRecord->ReadINT32(&TimePressure)) 05180 return FALSE; 05181 05182 // now get the path processor belonging to the last attribute 05183 PathProcessorBrush* pPathProc = m_pLastAttribute->GetPathProcessor(); 05184 05185 // if there isn't a path processor thats ok, as it may be default 05186 if (pPathProc == NULL) 05187 return TRUE; 05188 else 05189 { 05190 pPathProc->SetScalingMaxPressure((UINT32)ScalingPressure); 05191 pPathProc->SetRotationMaxPressure((UINT32)RotationPressure); 05192 } 05193 05194 return TRUE; 05195 } 05196 05197 05198 /******************************************************************************************** 05199 05200 > BOOL BrushAttrRecordHandler::HandleTimeStampData(CXaraFileRecord* pRecord) 05201 05202 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 05203 Created: 21/12/99 05204 05205 Inputs: pRecord - the file record holding the data 05206 Returns: TRUE if all went well, otherwise FALSE 05207 Purpose: Reads in timestamp data and assigns it to the last attribute we created 05208 05209 ********************************************************************************************/ 05210 05211 BOOL BrushAttrRecordHandler::HandlePressureData(CXaraFileRecord* pRecord) 05212 { 05213 ERROR2IF(pRecord == NULL, FALSE, "Record is NULL"); 05214 05215 // we must have a node to import to 05216 ERROR2IF(m_pLastAttribute == NULL, FALSE, "No last attribute to import to"); 05217 05218 INT32 NumObjects = 0; 05219 05220 if (!pRecord->ReadINT32(&NumObjects)) 05221 return FALSE; 05222 05223 // must be some mistake, but ours not to reason why 05224 if (NumObjects <= 0) 05225 return TRUE; 05226 05227 /* 05228 // otherwise we must make ourselves a list 05229 PressureList* pNewList = new PressureList; 05230 05231 PressureItem TheItem; 05232 INT32 Pressure; 05233 double Proportion; 05234 INT32 Distance; 05235 05236 BOOL ok = TRUE; 05237 while ((NumObjects-- > 0) && ok) 05238 { 05239 if (ok) ok = pRecord->ReadINT32(&Pressure); 05240 if (ok) ok = pRecord->ReadDOUBLE(&Proportion); 05241 if (ok) ok = pRecord->ReadINT32(&Distance); 05242 if (ok) 05243 { 05244 TheItem.m_Pressure = Pressure; 05245 TheItem.m_Proportion = Proportion; 05246 TheItem.m_Distance = Distance; 05247 pNewList->push_back(TheItem); 05248 } 05249 } 05250 05251 if (pNewList && ok) 05252 { 05253 BrushAttrValue* pVal = (BrushAttrValue*)m_pLastAttribute->GetAttributeValue(); 05254 if (pVal) 05255 pVal->SetPressureList(pNewList); 05256 else 05257 { 05258 pNewList->RemoveAll(); 05259 delete pNewList; 05260 } 05261 pNewList = NULL; 05262 } 05263 */ 05264 return TRUE; 05265 } 05266 05267 05268 /******************************************************************************************** 05269 05270 > BOOL BrushAttrRecordHandler::HandleTimeStampData(CXaraFileRecord* pRecord) 05271 05272 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 05273 Created: 21/12/99 05274 05275 Inputs: pRecord - the file record holding the data 05276 Returns: TRUE if all went well, otherwise FALSE 05277 Purpose: Reads in timestamp data and assigns it to the last attribute we created 05278 05279 ********************************************************************************************/ 05280 05281 BOOL BrushAttrRecordHandler::HandleTimeStampData(CXaraFileRecord* pRecord) 05282 { 05283 ERROR2IF(pRecord == NULL, FALSE, "Record is NULL"); 05284 05285 // we must have a node to import to 05286 ERROR2IF(m_pLastAttribute == NULL, FALSE, "No last attribute to import to"); 05287 05288 // first find out how many objects we have 05289 INT32 NumObjects = 0; 05290 05291 if (!pRecord->ReadINT32(&NumObjects)) 05292 return FALSE; 05293 05294 // must be some mistake, but ours not to reason why 05295 if (NumObjects <= 0) 05296 return TRUE; 05297 05298 // otherwise we must make ourselves a list 05299 TimeStampList* pNewList = new TimeStampList; 05300 05301 // we may fail to get the list, however we must still read in the data or the next 05302 // record will be really screwed 05303 05304 DocCoord Point; 05305 double Tangent; 05306 double Proportion; 05307 MILLIPOINT Distance; 05308 05309 TimeStampBrushPoint TSBP; 05310 BOOL ok = TRUE; 05311 while ((NumObjects-- > 0) && ok) 05312 { 05313 if (ok) ok = pRecord->ReadCoord(&Point); 05314 if (ok) ok = pRecord->ReadDOUBLE(&Tangent); 05315 if (ok) ok = pRecord->ReadDOUBLE(&Proportion); 05316 if (ok) ok = pRecord->ReadINT32(&Distance); 05317 TRACEUSER("Diccon", _T("Read Point %d, %d\n"), Point.x, Point.y); 05318 if (pNewList != NULL && ok) 05319 { 05320 TSBP.m_Distance = Distance; 05321 TSBP.m_Point = Point; 05322 // not quite sure why I have to make this atrocious hack. It seems that 05323 // somewhere between being written and being read the millipoint values 05324 // had 576000 added to them. 05325 TSBP.m_Point.x -= 576000; 05326 TSBP.m_Point.y -= 576000; 05327 TSBP.m_Proportion = Proportion; 05328 TSBP.m_Tangent = Tangent; 05329 TSBP.m_Pressure = MAXPRESSURE / 2; //?? 05330 pNewList->push_back(TSBP); 05331 } 05332 } 05333 05334 if (pNewList) 05335 { 05336 BrushAttrValue* pVal = (BrushAttrValue*)m_pLastAttribute->GetAttributeValue(); 05337 if (pVal) 05338 pVal->SetTimeStampList(pNewList); 05339 else 05340 { 05341 pNewList->clear(); 05342 delete pNewList; 05343 } 05344 pNewList = NULL; 05345 } 05346 return ok; 05347 05348 } 05349 05350 05351 /******************************************************************************************** 05352 05353 > BOOL BrushAttrRecordHandler::HandleAttrFillFlags(CXaraFileRecord* pRecord) 05354 05355 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 05356 Created: 17/6/2000 05357 05358 Inputs: pRecord - the file record holding the data 05359 Returns: TRUE if all went well, otherwise FALSE 05360 Purpose: Reads in data, and assigns it to the attribute that we just created 05361 05362 ********************************************************************************************/ 05363 05364 BOOL BrushAttrRecordHandler::HandleAttrFillFlags(CXaraFileRecord* pRecord) 05365 { 05366 ERROR2IF(pRecord == NULL, FALSE, "Record is NULL"); 05367 05368 // we must have a node to import to 05369 ERROR2IF(m_pLastAttribute == NULL, FALSE, "No last attribute to import to"); 05370 05371 BYTE Flags = 0; 05372 05373 if (!pRecord->ReadBYTE(&Flags)) 05374 return FALSE; 05375 05376 BOOL bUseLocalFill = Flags & BRUSHFILLFLAG_LOCALFILL; 05377 BOOL bUseLocalTransp = Flags & BRUSHFILLFLAG_LOCALTRANSP; 05378 BOOL bUseNamed = Flags & BRUSHFILLFLAG_NAMEDCOL; 05379 05380 // we need to get the path processor 05381 PathProcessorBrush* pPPB = m_pLastAttribute->GetPathProcessor(); 05382 if (pPPB == NULL) 05383 return FALSE; 05384 05385 pPPB->SetUseLocalFillColour(bUseLocalFill); 05386 pPPB->SetUseLocalTransp(bUseLocalTransp); 05387 pPPB->SetUseNamedColours(bUseNamed); 05388 05389 return TRUE; 05390 05391 } 05392 05393 05394 /******************************************************************************************** 05395 05396 > BOOL BrushAttrRecordHandler::HandleTranspInfo(CXaraFileRecord* pRecord) 05397 05398 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 05399 Created: 21/12/99 05400 05401 Inputs: pRecord - the file record holding the data 05402 Returns: TRUE if all went well, otherwise FALSE 05403 Purpose: Reads in data pertaining to transparency, and other assorted things 05404 05405 ********************************************************************************************/ 05406 05407 BOOL BrushAttrRecordHandler::HandleTranspInfo(CXaraFileRecord* pRecord) 05408 { 05409 ERROR2IF(pRecord == NULL, FALSE, "Record is NULL"); 05410 05411 INT32 Transp = 0; 05412 INT32 TranspPressure = 0; 05413 double RotIncr = 0.0; 05414 double ScaleIncr = 0.0; 05415 INT32 HueMaxRand = 0; 05416 INT32 HueRandSeed = 0; 05417 INT32 SatMaxRand = 0; 05418 INT32 SatRandSeed = 0; 05419 05420 if (!pRecord->ReadINT32(&Transp) || !pRecord->ReadINT32(&TranspPressure) || 05421 !pRecord->ReadDOUBLE(&RotIncr) || !pRecord->ReadDOUBLE(&ScaleIncr) || 05422 !pRecord->ReadINT32(&HueMaxRand) || !pRecord->ReadINT32(&HueRandSeed) || 05423 !pRecord->ReadINT32(&SatMaxRand) || !pRecord->ReadINT32(&SatRandSeed)) 05424 return FALSE; 05425 05426 // get the brush component from the document 05427 Document* pDoc = Document::GetCurrent(); 05428 ERROR2IF(pDoc == NULL, FALSE, "Wheres the document?"); 05429 BrushComponent* pBrushComp = (BrushComponent*)pDoc->GetDocComponent(CC_RUNTIME_CLASS(BrushComponent)); 05430 ERROR2IF(pBrushComp == NULL, FALSE, "No brush component"); 05431 05432 // find the brush definition that is currently being imported 05433 BrushDefinition* pBrushDef = pBrushComp->GetImportBrushDefinition(); 05434 05435 // give the data to the definition 05436 if (pBrushDef != NULL) 05437 { 05438 pBrushDef->SetBrushTransparency(Transp); 05439 pBrushDef->SetTransparencyPressure(UINT32(TranspPressure)); 05440 pBrushDef->SetRotationIncrConst(RotIncr); 05441 pBrushDef->SetBrushScalingIncrConst(ScaleIncr); 05442 pBrushDef->SetHueMaxRand(UINT32(HueMaxRand)); 05443 pBrushDef->SetHueRandSeed(UINT32(HueRandSeed)); 05444 pBrushDef->SetSatMaxRand(UINT32(SatMaxRand)); 05445 pBrushDef->SetSatRandSeed(UINT32(SatRandSeed)); 05446 } 05447 else 05448 ERROR3("Unable to find brush definition in BrushAttrRecordHandler::HandleTranspInfo"); 05449 05450 // this is the end of this brush import 05451 m_pLastAttribute = NULL; 05452 05453 return pBrushComp->EndImportBrush(this); 05454 05455 } 05456 05457 05458 /******************************************************************************************** 05459 05460 > BOOL BrushAttrRecordHandler::HandleAttrTranspInfo(CXaraFileRecord* pRecord) 05461 05462 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 05463 Created: 21/12/99 05464 05465 Inputs: pRecord - the file record holding the data 05466 Returns: TRUE if all went well, otherwise FALSE 05467 Purpose: Reads in data pertaining to transparency, and other assorted things 05468 05469 ********************************************************************************************/ 05470 05471 BOOL BrushAttrRecordHandler::HandleAttrTranspInfo(CXaraFileRecord* pRecord) 05472 { 05473 ERROR2IF(pRecord == NULL, FALSE, "Record is NULL"); 05474 05475 // we must have a node to import to 05476 ERROR2IF(m_pLastAttribute == NULL, FALSE, "No last attribute to import to"); 05477 05478 // read in the data 05479 INT32 Transp = 0; 05480 INT32 TranspPressure = 0; 05481 double RotIncr = 0.0; 05482 double ScaleIncr = 0.0; 05483 INT32 HueMaxRand = 0; 05484 INT32 HueRandSeed = 0; 05485 INT32 SatMaxRand = 0; 05486 INT32 SatRandSeed = 0; 05487 05488 if (!pRecord->ReadINT32(&Transp) || !pRecord->ReadINT32(&TranspPressure) || 05489 !pRecord->ReadDOUBLE(&RotIncr) || !pRecord->ReadDOUBLE(&ScaleIncr) || 05490 !pRecord->ReadINT32(&HueMaxRand) || !pRecord->ReadINT32(&HueRandSeed) || 05491 !pRecord->ReadINT32(&SatMaxRand) || !pRecord->ReadINT32(&SatRandSeed)) 05492 return FALSE; 05493 05494 // we need to get the path processor 05495 PathProcessorBrush* pPPB = m_pLastAttribute->GetPathProcessor(); 05496 05497 if (pPPB != NULL) 05498 { 05499 pPPB->SetBrushTransparency(Transp); 05500 pPPB->SetTransparencyPressure(UINT32(TranspPressure)); 05501 pPPB->SetRotationIncrConst(RotIncr); 05502 pPPB->SetBrushScalingIncrConst(ScaleIncr); 05503 pPPB->SetHueMaxRand(UINT32(HueMaxRand)); 05504 pPPB->SetHueRandSeed(UINT32(HueRandSeed)); 05505 pPPB->SetSatMaxRand(UINT32(SatMaxRand)); 05506 pPPB->SetSatRandSeed(UINT32(SatRandSeed)); 05507 } 05508 else 05509 ERROR3("Unable to find path processor in BrushAttrRecordHandler::HandleAttrTranspInfo"); 05510 05511 return TRUE; 05512 } 05513 05514 05515 /******************************************************************************************** 05516 05517 > BOOL BrushAttrRecordHandler::HandleTimeStampData(CXaraFileRecord* pRecord) 05518 05519 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 05520 Created: 21/12/99 05521 05522 Inputs: pRecord - the file record holding the data 05523 Returns: TRUE if all went well, otherwise FALSE 05524 Purpose: Reads in timestamp data and assigns it to the last attribute we created 05525 05526 ********************************************************************************************/ 05527 05528 BOOL BrushAttrRecordHandler::HandlePressureSampleData(CXaraFileRecord* pRecord) 05529 { 05530 ERROR2IF(pRecord == NULL, FALSE, "Record is NULL"); 05531 05532 // we must have a node to import to 05533 ERROR2IF(m_pLastAttribute == NULL, FALSE, "No last attribute to import to"); 05534 05535 // first find out how many objects we have 05536 INT32 NumObjects = 0; 05537 05538 if (!pRecord->ReadINT32(&NumObjects)) 05539 return FALSE; 05540 05541 // must be some mistake, but ours not to reason why 05542 if (NumObjects <= 0) 05543 return TRUE; 05544 05545 // make a new pressure sampler 05546 CDistanceSampler* pSampler = new CDistanceSampler; 05547 05548 if (pSampler == NULL) 05549 return FALSE; 05550 05551 if (!pSampler->InitialiseData(NumObjects)) 05552 { 05553 delete pSampler; 05554 return FALSE; 05555 } 05556 pSampler->SetCollectionSampleRate(1); 05557 05558 CSampleItem TheItem; 05559 DocCoord TheCoord; 05560 MILLIPOINT TheDistance = 0; 05561 INT32 ThePressure = 0; 05562 BOOL ok = TRUE; 05563 BOOL KeepAdding = TRUE; 05564 UINT32 Count = 0; 05565 while (ok && KeepAdding) 05566 { 05567 if (ok) ok = pRecord->ReadINT32(&ThePressure); 05568 if (ok) ok = pRecord->ReadCoord(&TheCoord); 05569 if (ok) ok = pRecord->ReadINT32(&TheDistance); 05570 05571 TheItem.m_Pressure = (UINT32)ThePressure; 05572 TheItem.m_Coord = TheCoord; 05573 TheItem.m_Distance = TheDistance; 05574 05575 if (ok) KeepAdding = pSampler->SetNext(TheItem); 05576 Count++; 05577 } 05578 05579 pSampler->SetDistanceSoFar (TheItem.m_Distance); 05580 05581 if (ok) 05582 m_pLastAttribute->SetPressureCache(pSampler); 05583 else 05584 delete pSampler; 05585 05586 return ok; 05587 } 05588 05589 05590 05591 /******************************************************************************************** 05592 05593 > virtual BOOL BrushAttrRecordHandler::BeginSubtree(UINT32 Tag) 05594 05595 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 05596 Created: 21/12/99 05597 05598 Inputs: Tag = tag value of the tag this handler last handled 05599 Returns: TRUE if this func wants exclusive handling of the tag 05600 FALSE otherwise 05601 Purpose: Informs the record handler that a subtree is following a tag of type 'Tag' 05602 05603 If you override this func and you do not wish other parts of the system to be informed of the 05604 subtree start, you should return TRUE 05605 05606 ********************************************************************************************/ 05607 05608 BOOL BrushAttrRecordHandler::BeginSubtree(UINT32 Tag) 05609 { 05610 // We only want to know about following subtrees when doing stroke definition records. 05611 // If we are doing one, then we grab the subtree so nobody else can faff about with it 05612 if (Tag != TAG_BRUSHDEFINITION) 05613 return(FALSE); 05614 05615 return(TRUE); 05616 } 05617 05618 05619 05620 /******************************************************************************************** 05621 05622 > virtual BOOL BrushAttrRecordHandler::EndSubtree(UINT32 Tag) 05623 05624 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 05625 Created: 21/12/99 05626 05627 Inputs: Tag = tag value of the tag this handler last handled 05628 Returns: TRUE if this func wants exclusive handling of the tag 05629 FALSE otherwise 05630 05631 Purpose: Informs the record handler that a subtree that followed a tag of type 'Tag' has ended 05632 05633 If you override this func and you do not wish other parts of the system to be 05634 informed of the subtree end, you should return TRUE 05635 05636 ********************************************************************************************/ 05637 05638 BOOL BrushAttrRecordHandler::EndSubtree(UINT32 Tag) 05639 { 05640 // We only want to know about following subtrees when doing custom print mark records. 05641 // If we are doing one, then we grab the subtree so nobody else can faff about with it 05642 if (Tag != TAG_BRUSHDEFINITION) 05643 return(FALSE); 05644 05645 // get the brush component from the document 05646 Document* pDoc = Document::GetCurrent(); 05647 ERROR2IF(pDoc == NULL, FALSE, "Wheres the document?"); 05648 BrushComponent* pBrushComp = (BrushComponent*)pDoc->GetDocComponent(CC_RUNTIME_CLASS(BrushComponent)); 05649 ERROR2IF(pBrushComp == NULL, FALSE, "No brush component"); 05650 05651 return TRUE; //pBrushComp->EndImportBrush(this); 05652 05653 } 05654 05655 05656 05657 /******************************************************************************************** 05658 05659 > virtual void BrushAttrRecordHandler::GetRecordDescriptionText(CXaraFileRecord* pRecord,StringBase* pStr) 05660 05661 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 05662 Created: 21/12/99 05663 05664 Inputs: pRecord = ptr to a record 05665 pStr = ptr to string to update 05666 05667 Returns: - 05668 Purpose: Provides descriptions for the brush attribute records. 05669 05670 Notes: This function is only present in _DEBUG builds 05671 05672 ********************************************************************************************/ 05673 05674 #ifdef XAR_TREE_DIALOG 05675 05676 void BrushAttrRecordHandler::GetRecordDescriptionText(CXaraFileRecord* pRecord, StringBase* pStr) 05677 { 05678 if (pStr == NULL || pRecord == NULL) 05679 return; 05680 05681 // Call base class first to output the tag and size 05682 CamelotRecordHandler::GetRecordDescriptionText(pRecord, pStr); 05683 05684 // UINT32 Tag = pRecord->GetTag(); 05685 // INT32 RecordNumber = pRecord->GetRecordNumber(); 05686 05687 05688 } 05689 05690 05691 05692 #endif