00001 // $Id: nodebmp.cpp 1771 2007-06-17 20:14:43Z alex $ 00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE 00003 ================================XARAHEADERSTART=========================== 00004 00005 Xara LX, a vector drawing and manipulation program. 00006 Copyright (C) 1993-2006 Xara Group Ltd. 00007 Copyright on certain contributions may be held in joint with their 00008 respective authors. See AUTHORS file for details. 00009 00010 LICENSE TO USE AND MODIFY SOFTWARE 00011 ---------------------------------- 00012 00013 This file is part of Xara LX. 00014 00015 Xara LX is free software; you can redistribute it and/or modify it 00016 under the terms of the GNU General Public License version 2 as published 00017 by the Free Software Foundation. 00018 00019 Xara LX and its component source files are distributed in the hope 00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the 00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00022 See the GNU General Public License for more details. 00023 00024 You should have received a copy of the GNU General Public License along 00025 with Xara LX (see the file GPL in the root directory of the 00026 distribution); if not, write to the Free Software Foundation, Inc., 51 00027 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00028 00029 00030 ADDITIONAL RIGHTS 00031 ----------------- 00032 00033 Conditional upon your continuing compliance with the GNU General Public 00034 License described above, Xara Group Ltd grants to you certain additional 00035 rights. 00036 00037 The additional rights are to use, modify, and distribute the software 00038 together with the wxWidgets library, the wxXtra library, and the "CDraw" 00039 library and any other such library that any version of Xara LX relased 00040 by Xara Group Ltd requires in order to compile and execute, including 00041 the static linking of that library to XaraLX. In the case of the 00042 "CDraw" library, you may satisfy obligation under the GNU General Public 00043 License to provide source code by providing a binary copy of the library 00044 concerned and a copy of the license accompanying it. 00045 00046 Nothing in this section restricts any of the rights you have under 00047 the GNU General Public License. 00048 00049 00050 SCOPE OF LICENSE 00051 ---------------- 00052 00053 This license applies to this program (XaraLX) and its constituent source 00054 files only, and does not necessarily apply to other Xara products which may 00055 in part share the same code base, and are subject to their own licensing 00056 terms. 00057 00058 This license does not apply to files in the wxXtra directory, which 00059 are built into a separate library, and are subject to the wxWindows 00060 license contained within that directory in the file "WXXTRA-LICENSE". 00061 00062 This license does not apply to the binary libraries (if any) within 00063 the "libs" directory, which are subject to a separate license contained 00064 within that directory in the file "LIBS-LICENSE". 00065 00066 00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS 00068 ---------------------------------------------- 00069 00070 Subject to the terms of the GNU Public License (see above), you are 00071 free to do whatever you like with your modifications. However, you may 00072 (at your option) wish contribute them to Xara's source tree. You can 00073 find details of how to do this at: 00074 http://www.xaraxtreme.org/developers/ 00075 00076 Prior to contributing your modifications, you will need to complete our 00077 contributor agreement. This can be found at: 00078 http://www.xaraxtreme.org/developers/contribute/ 00079 00080 Please note that Xara will not accept modifications which modify any of 00081 the text between the start and end of this header (marked 00082 XARAHEADERSTART and XARAHEADEREND). 00083 00084 00085 MARKS 00086 ----- 00087 00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara 00089 designs are registered or unregistered trademarks, design-marks, and/or 00090 service marks of Xara Group Ltd. All rights in these marks are reserved. 00091 00092 00093 Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK. 00094 http://www.xara.com/ 00095 00096 =================================XARAHEADEREND============================ 00097 */ 00098 00099 // Node representing a bitmap object. 00100 00101 /* 00102 */ 00103 00104 #include "camtypes.h" 00105 #include "nodebmp.h" 00106 //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00107 //#include "tim.h" 00108 //#include "rndrgn.h" 00109 //#include "doccolor.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00110 //#include "fillattr.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00111 #include "lineattr.h" 00112 //#include "progress.h" 00113 #include "cameleps.h" 00114 #include "ai_epsrr.h" 00115 #include "bitmpinf.h" 00116 #include "nodepath.h" 00117 //#include "becomea.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00118 #include "draginfo.h" 00119 //#include "scrcamvw.h" 00120 #include "cliptype.h" 00121 #include "attrmap.h" 00122 #include "spread.h" 00123 #include "zoomops.h" 00124 #include "bitfilt.h" 00125 00126 #include "colormgr.h" 00127 //#include "attrmgr.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00128 //#include "jason.h" 00129 //#include "justin2.h" 00130 //#include "sglfills.h" 00131 //#include "xpehost.h" 00132 #include "grndrgn.h" 00133 //#include "matrix.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00134 #include "nodeliveeffect.h" 00135 00136 // These are for CheckGreyscaleBitmap 00137 #ifndef WEBSTER 00138 //these should probably be #ifndef EXCLUDE_BFX rather than WEBSTER Martin-17/03/97 00139 //they aren't used any more anyway 10/04/97 00140 //#include "bfxalu.h" 00141 //#include "bitmapfx.h" 00142 #endif //WEBSTER 00143 //#include "resource.h" 00144 //#include "bmplist.h" 00145 #include "bmpcomp.h" 00146 //#include "app.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00147 //#include "will.h" 00148 #include "qualattr.h" 00149 //#include "view.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00150 //#include "will2.h" 00151 //#include "capturemanager.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00152 #include "fthrattr.h" 00153 #include "ophist.h" 00154 #include "objchge.h" 00155 00156 // headers for the new file format 00157 //#include "camfiltr.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00158 #include "cxfnbmp.h" 00159 00160 // stuff for CMX rubbish 00161 //#include "cmxrendr.h" 00162 //#include "cmxexdc.h" 00163 00164 // for popup menu 00165 #include "contmenu.h" 00166 //#include "bfxdlg.h" 00167 #include "tracedlg.h" 00168 00169 //This includes the Hot Link class 00170 #include "userattr.h" 00171 //#include "webattr.h" 00172 #include "camview.h" 00173 00174 #ifdef PHOTOSHOPPLUGINS 00175 // Only add in if required - general plug-in removal at present 00176 #include "plugmngr.h" // OPTOKEN_PLUGINS_MENU 00177 #include "plugop.h" // PlugInsContextMenu 00178 #endif 00179 00180 DECLARE_SOURCE("$Revision: 1771 $"); 00181 00182 CC_IMPLEMENT_DYNCREATE(NodeBitmap, NodeRect); 00183 #if !defined(EXCLUDE_FROM_RALPH) 00184 CC_IMPLEMENT_DYNCREATE(OpCreateNodeBitmap, UndoableOperation); 00185 #endif 00186 CC_IMPLEMENT_DYNCREATE(ChangeBitmapPtrAction, Action); 00187 00188 // Declare smart memory handling in Debug builds 00189 #define new CAM_DEBUG_NEW 00190 00191 00192 /******************************************************************************************** 00193 00194 > NodeBitmap::NodeBitmap(Node* ContextNode, 00195 AttachNodeDirection Direction, 00196 BOOL Locked, 00197 BOOL Mangled, 00198 BOOL Marked, 00199 BOOL Selected) 00200 00201 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00202 Created: 30/08/94 00203 00204 Inputs: ContextNode: Pointer to a node which this node is to be attached to. 00205 00206 Direction: 00207 00208 Specifies the direction in which the node is to be attached to the 00209 ContextNode. The values this variable can take are as follows: 00210 00211 PREV : Attach node as a previous sibling of the context node 00212 NEXT : Attach node as a next sibling of the context node 00213 FIRSTCHILD: Attach node as the first child of the context node 00214 LASTCHILD : Attach node as a last child of the context node 00215 00216 The remaining inputs specify the status of the node: 00217 00218 Locked: Is node locked ? 00219 Mangled: Is node mangled ? 00220 Marked: Is node marked ? 00221 Selected: Is node selected ? 00222 00223 Purpose: This constructor initialises the nodes flags and links it to ContextNode in 00224 the direction specified by Direction. All neccesary tree links are updated. 00225 00226 Note: SetUpPath() must be called before the NodeBitmap is in a state in which it 00227 can be used. 00228 00229 SeeAlso: SetUpPath 00230 00231 Errors: An assertion error will occur if ContextNode is NULL 00232 00233 ********************************************************************************************/ 00234 00235 NodeBitmap::NodeBitmap(Node* ContextNode, 00236 AttachNodeDirection Direction, 00237 BOOL Locked, 00238 BOOL Mangled, 00239 BOOL Marked, 00240 BOOL Selected 00241 ):NodeRect(ContextNode, Direction, Locked, Mangled, Marked, Selected ) 00242 { 00243 Colour = COLOUR_NONE; 00244 EndColour = COLOUR_NONE; 00245 00246 ApplyContoneColour = FALSE; 00247 } 00248 00249 00250 /******************************************************************************************** 00251 00252 > NodeBitmap::NodeBitmap() 00253 00254 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00255 Created: 30/08/94 00256 Purpose: This constructor creates a NodeBitmap linked to no other with all status 00257 flags false and an uninitialized bounding rectangle. 00258 00259 NB. SetUpPath() must be called before the NodeBitmap is in a state in which 00260 it can be used. 00261 00262 SeeAlso: SetUpPath 00263 00264 ********************************************************************************************/ 00265 00266 NodeBitmap::NodeBitmap(): NodeRect() 00267 { 00268 Colour = COLOUR_NONE; 00269 EndColour = COLOUR_NONE; 00270 00271 ApplyContoneColour = FALSE; 00272 } 00273 00274 00275 00276 /*********************************************************************************************** 00277 00278 > virtual Node* NodeBitmap::SimpleCopy() 00279 00280 Author: Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com> 00281 Created: 26/5/93 00282 Returns: Pointer to a Node 00283 Purpose: Makes a copy of all the data in the node 00284 00285 ***********************************************************************************************/ 00286 00287 Node* NodeBitmap::SimpleCopy() 00288 { 00289 // Make a new NodeBitmap and then copy things into it 00290 NodeBitmap* NodeCopy = new NodeBitmap(); 00291 if (NodeCopy) 00292 CopyNodeContents(NodeCopy); 00293 00294 return NodeCopy; 00295 } 00296 00297 00298 /*********************************************************************************************** 00299 00300 > void NodeBitmap::CopyNodeContents(NodeBitmap* NodeCopy) 00301 00302 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00303 Created: 26/5/93 00304 Inputs: NodeCopy - The node to copy 00305 Purpose: Copies the data in the node by first calling the base class to get it to 00306 copy its stuff, and then copying its own stuff 00307 Scope: protected 00308 SeeAlso: NodeRect::CopyNodeContents 00309 00310 ***********************************************************************************************/ 00311 00312 void NodeBitmap::CopyNodeContents(NodeBitmap* NodeCopy) 00313 { 00314 NodeRect::CopyNodeContents(NodeCopy); 00315 00316 // Copy contents specific to derived class here 00317 00318 // Copy KernelBitmap reference 00319 NodeCopy->BitmapRef = BitmapRef; 00320 00321 // We need to copy the cached bitmaps into the new node 00322 // But since this cached (option 2) bitmap is only ever used as an intermediate stage 00323 // in producing another cached bitmap, we probably don't need to copy it 00324 //CopyCached(pCopyOfNode, GetPixelWidth(), 2); // Copy cached bitmaps, options 0, 1 and 2 (original and processed) 00325 } 00326 00327 00328 00329 00330 /*********************************************************************************************** 00331 > void NodeBitmap::PolyCopyNodeContents(NodeRenderable* pNodeCopy) 00332 00333 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 00334 Created: 18/12/2003 00335 Outputs: - 00336 Purpose: Polymorphically copies the contents of this node to another 00337 Errors: An assertion failure will occur if NodeCopy is NULL 00338 Scope: protected 00339 00340 ***********************************************************************************************/ 00341 00342 void NodeBitmap::PolyCopyNodeContents(NodeRenderable* pNodeCopy) 00343 { 00344 ENSURE(pNodeCopy, "Trying to copy a node's contents into a NULL node"); 00345 ENSURE(IS_A(pNodeCopy, NodeBitmap), "PolyCopyNodeContents given wrong dest node type"); 00346 00347 if (IS_A(pNodeCopy, NodeBitmap)) 00348 CopyNodeContents((NodeBitmap*)pNodeCopy); 00349 } 00350 00351 00352 00353 /******************************************************************************************** 00354 00355 > virtual String NodeBitmap::Describe(BOOL Plural, BOOL Verbose = TRUE) 00356 00357 Author: Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com> 00358 Created: 25/6/93 00359 Inputs: Plural: Flag indicating if the string description should be plural or 00360 singular. 00361 Returns: Description of the object 00362 Purpose: To return a description of the NodeBitmap object in either the singular or the 00363 plural. This method is called by the DescribeRange method. 00364 The description will always begin with a lower case letter. 00365 Errors: A resource exception will be thrown if a problem occurs when loading the 00366 string resource. 00367 00368 ********************************************************************************************/ 00369 00370 String NodeBitmap::Describe(BOOL Plural, BOOL Verbose) 00371 { 00372 #if !defined(EXCLUDE_FROM_RALPH) 00373 if (Plural) 00374 { 00375 return(String(_R(IDS_BITMAP_DESCRP))); 00376 } 00377 else 00378 { 00379 if (GetBitmap() == NULL || GetBitmap()->ActualBitmap == NULL) 00380 return(String(_R(IDS_BITMAP_DESCRS))); 00381 00382 // If we have a bitmap, then include it's name and actual dpi 00383 // in the desciption 00384 00385 String_256 BmpName = GetBitmap()->ActualBitmap->GetName(); 00386 String_64 TrunkName; 00387 if (BmpName.Length() > 12) 00388 { 00389 BmpName.Left(&TrunkName, 9); 00390 TrunkName += _T("..."); 00391 } 00392 else 00393 { 00394 BmpName.Left(&TrunkName, 12); 00395 } 00396 00397 String_256 DpiText; 00398 UINT32 dpi = GetBitmapDPI(); 00399 00400 if (dpi > 0) 00401 { 00402 String_256 jcf(_R(IDS_NODEBMP_DPI_FORMAT)); 00403 camSnprintf(DpiText, 256, jcf, dpi); 00404 } 00405 00406 String_64 TrunkDpi; 00407 DpiText.Left(&TrunkDpi, 11); 00408 00409 String_256 Desc(_R(IDS_BITMAP_DESCRS)); 00410 String_64 TrunkDesc; 00411 Desc.Left(&TrunkDesc, 6); 00412 00413 if (Verbose) 00414 { 00415 String_32 ret = TrunkDesc; 00416 ret += TEXT(" '"); 00417 ret += TrunkName; 00418 ret += TEXT("'"); 00419 ret += TrunkDpi; 00420 return ret; 00421 // return(String(TrunkDesc+TEXT(" '")+TrunkName+TEXT("'")+TrunkDpi)); 00422 } 00423 else 00424 { 00425 String_32 ret = TrunkDesc; 00426 ret += TEXT(" "); 00427 ret += TrunkName; 00428 return ret; 00429 // return(String(TrunkDesc+TEXT(" ")+TrunkName)); 00430 } 00431 } 00432 #else 00433 return(String(_R(IDS_BITMAP_DESCRP))); 00434 #endif 00435 } 00436 00437 /******************************************************************************************** 00438 00439 > UINT32 NodeBitmap::GetBitmapDPI() 00440 00441 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 00442 Created: 16/2/95 00443 Returns: The actual DPI of the bitmap. 00444 Purpose: Caculates the actual DPI of the bitmap on the page. 00445 00446 ********************************************************************************************/ 00447 00448 UINT32 NodeBitmap::GetBitmapDPI() 00449 { 00450 UINT32 Dpi = 0; 00451 00452 if (GetBitmap() == NULL) 00453 return 0; 00454 00455 // Do we have a valid bitmap ? 00456 OILBitmap *OilBM = GetBitmap()->ActualBitmap; 00457 00458 if (OilBM != NULL) 00459 { 00460 BitmapInfo Info; 00461 OilBM->GetInfo(&Info); 00462 00463 // Get the Width of the Bitmap in Pixels 00464 INT32 PixWidth = Info.PixelWidth; 00465 INT32 PixHeight = Info.PixelHeight; 00466 00467 // Get the Width of the Bitmap in Millipoints 00468 INT32 Width = INT32(Parallel[0].Distance(Parallel[1])); 00469 INT32 Height = INT32(Parallel[1].Distance(Parallel[2])); 00470 00471 // Use doubles so that we can round up as well as down. This improves 00472 // the dpi calculated. 00473 double HDpi = 0; 00474 double VDpi = 0; 00475 00476 if (Width > 0) 00477 HDpi = ((double)PixWidth * 72000.0)/(double)Width; 00478 00479 if (Height > 0) 00480 VDpi = ((double)PixHeight * 72000.0)/(double)Height; 00481 00482 // Use the smaller of the two dpi values 00483 Dpi = (UINT32)(HDpi + 0.5); 00484 if (VDpi < Dpi) 00485 Dpi = (UINT32)(VDpi + 0.5); 00486 } 00487 00488 return Dpi; 00489 } 00490 00491 /******************************************************************************************** 00492 00493 > virtual UINT32 NodeBitmap::GetNodeSize() const 00494 00495 Author: Simon_Maneggio (Xara Group Ltd) <camelotdev@xara.com> 00496 Created: 6/10/93 00497 Returns: The size of the node in bytes 00498 Purpose: For finding the size of the node 00499 SeeAlso: Node::GetSubtreeSize 00500 00501 ********************************************************************************************/ 00502 00503 UINT32 NodeBitmap::GetNodeSize() const 00504 { 00505 return (sizeof(NodeBitmap)); 00506 } 00507 00508 00509 00510 /******************************************************************************************** 00511 00512 > virtual BOOL NodeBitmap::OnNodePopUp(Spread* pSpread, DocCoord PointerPos, ContextMenu* pMenu) 00513 00514 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 00515 Created: 20/08/96 00516 Inputs: pSpread The spread in which things are happening 00517 PointerPos The Location of the mouse pointer at the time of the click 00518 pMenu The menu to which items should be added 00519 Returns: BOOL - TRUE if the node claims the click as its own and FALSE if it is 00520 not interested in the click 00521 Purpose: Allows the Node to respond to pop up menu clicks on it (rather than its blobs). 00522 00523 ********************************************************************************************/ 00524 BOOL NodeBitmap::OnNodePopUp(Spread* pSpread, DocCoord PointerPos, ContextMenu* pMenu) 00525 { 00526 #if !defined(EXCLUDE_FROM_RALPH) 00527 00528 BOOL ok = TRUE; 00529 00530 PORTNOTE("liveeffects", "XPE menu option disabled") 00531 #ifndef EXCLUDE_FROM_XARALX 00532 ok = ok && pMenu->BuildCommand(OPTOKEN_XPE_EDIT, FALSE); 00533 #endif 00534 00535 //ok = ok && pMenu->BuildCommand(OPTOKEN_BFXDLG, FALSE); 00536 00537 #ifdef PHOTOSHOPPLUGINS 00538 // Only add in if required - general plug-in removal at present 00539 // Add a sub-menu tacked onto this which is the main PhotoShopContextMenu 00540 // we have real OpTokens and so can do it properly 00541 // Well, in fact we will ask the PhotoShopContextMenu to do it for us! 00542 // ok = ok && pMenu->BuildCommand(OPTOKEN_PLUGINS_UNDO_MENU, FALSE); 00543 // MenuItem* pMainRoot = pMenu->GetLastItem(); 00544 MenuItem* pMainRoot = NULL; 00545 // Add a submenu which is the list of bitmap based plug-ins. 00546 // We have no need for specifying a document and a bitmap as this will be read 00547 // by the undoable op. 00548 // There should not be a separator and we should use the undoable versions 00549 // of the operations (hence FALSE, TRUE). 00550 ok = ok && PlugInsContextMenu::BuildMenu(NULL, NULL, pMenu, pMainRoot, FALSE, TRUE); 00551 #endif // PHOTOSHOPPLUGINS 00552 00553 ok = ok && pMenu->BuildCommand(OPTOKEN_TRACEDLG, TRUE); 00554 00555 return ok; 00556 00557 #else // !defined(EXCLUDE_FROM_RALPH) 00558 00559 return FALSE; 00560 00561 #endif // !defined(EXCLUDE_FROM_RALPH) 00562 } 00563 00564 00565 00566 /******************************************************************************************** 00567 00568 > void NodeBitmap::Render(RenderRegion* pRender) 00569 00570 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00571 Created: 30/8/94 00572 Inputs: Pointer to a render region 00573 Purpose: Will render the bitmap contained within the object to the given render 00574 region. 00575 00576 ********************************************************************************************/ 00577 00578 void NodeBitmap::Render(RenderRegion* pRender) 00579 { 00580 // No need to render if we are going to supply directly to a capture 00581 Capture* pCapture = pRender->GetTopCapture(); 00582 if (!(pCapture && pCapture->ConsumeDirectBitmap(this))) 00583 { 00584 // Render the transformed bitmap 00585 pRender->DrawTransformedBitmap(this); 00586 } 00587 } 00588 00589 00590 /******************************************************************************************** 00591 00592 > void NodeBitmap::PreExportRender(RenderRegion*) 00593 00594 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00595 Created: 12/10/94 00596 Inputs: Ignored 00597 Purpose: Prevent the base class NodeRect::PreExportRender() function from exporting 00598 anything to mark this as a rectangle object - because it's not; it's a 00599 bitmap object. 00600 00601 ********************************************************************************************/ 00602 00603 void NodeBitmap::PreExportRender(RenderRegion*) 00604 { 00605 // No action, and we want to stop the base class from exporting any 'rectangly' 00606 // information that might confuse us. 00607 } 00608 00609 00610 /******************************************************************************************** 00611 00612 > BOOL NodeBitmap::ExportRender(RenderRegion* pRegion) 00613 00614 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00615 Created: 01/09/94 00616 Inputs: pRegion - the export render region to export to. 00617 Returns: TRUE if the bitmap was exported ok; 00618 FALSE if not. 00619 Purpose: Export a bitmap object to a file. 00620 Errors: Usual disk/file errors. 00621 SeeAlso: Filter::ExportBitmap 00622 00623 ********************************************************************************************/ 00624 00625 BOOL NodeBitmap::ExportRender(RenderRegion* pRegion) 00626 { 00627 #ifdef DO_EXPORT 00628 if (pRegion->IsKindOf(CC_RUNTIME_CLASS(CamelotEPSRenderRegion))) 00629 { 00630 // Get valid transparency fill for this object 00631 CamelotEPSRenderRegion *pCamelotRegion = (CamelotEPSRenderRegion *) pRegion; 00632 pCamelotRegion->GetValidPathAttributes(); 00633 00634 // Output bitmap object position and keyword... 00635 EPSExportDC *pDC = (EPSExportDC *) pRegion->GetRenderDC(); 00636 00637 DocCoord *Coords = InkPath.GetCoordArray(); 00638 00639 // Bodge Code 00640 00641 // So this is some Bodge code to make Bitmaps in moulds, save themselves 00642 // correctly if a Line colour is applied to the Mould. 00643 00644 // This line colour makes the Bitmap think it has been contoned, so we save out 00645 // a contoned version, which is looks incorrect when re-loaded. 00646 00647 // To get around this problem, this code checks specifically for the situation, 00648 // and forces the bitmap to be saved as a non-contoned version. 00649 00650 BOOL CanSaveAsContoned = TRUE; 00651 BOOL LineColourIsAppliedToMould = FALSE; 00652 00653 if (GetBitmap() && GetBitmap()->GetBPP() <= 8) 00654 { 00655 // We only need to worry about this for < 8BPP 00656 NodeAttribute* pLineAttr; 00657 00658 // So we find the applied Stroke Colour ... 00659 if (FindAppliedAttribute(CC_RUNTIME_CLASS(AttrStrokeColour), &pLineAttr)) 00660 { 00661 Node* pParent = pLineAttr->FindParent(); 00662 00663 // And if it has been applied to a Mould ... 00664 if (pParent && IS_A(pParent, NodeMould)) 00665 { 00666 LineColourIsAppliedToMould = TRUE; 00667 00668 // and there is no Flat Colour Applied to the Bitmap, 00669 // then this flag will be FALSE, stopping the bitmap 00670 // from being saved as contone. 00671 CanSaveAsContoned = (GetEndColour() != NULL); 00672 } 00673 } 00674 } 00675 00676 if (CanSaveAsContoned && (GetStartColour() || GetEndColour())) 00677 { 00678 // Must be a contone bitmap 00679 00680 // If either the start or end colour is NULL, we need 00681 // to output a dummy colour, because 'No_Colour' doesn't 00682 // get saved 00683 if (LineColourIsAppliedToMould || GetStartColour() == NULL) 00684 { 00685 DocColour StartCol; 00686 AttributeManager::FindDefaultColour(ColourManager::GetCurrentColourList(), 00687 _R(IDS_BLACKNAME), &StartCol); 00688 00689 if (*GetEndColour() == StartCol) 00690 { 00691 AttributeManager::FindDefaultColour(ColourManager::GetCurrentColourList(), 00692 _R(IDS_WHITENAME), &StartCol); 00693 } 00694 00695 // Output dummy start colour here 00696 if (StartCol.FindParentIndexedColour() == NULL) 00697 { 00698 // Unnamed colour 00699 PColourCMYK CMYK; 00700 StartCol.GetCMYKValue(&CMYK); 00701 pDC->OutputColour(&CMYK); 00702 pDC->OutputToken(_T("K")); 00703 } 00704 else 00705 { 00706 // Named colour 00707 pDC->OutputNamedColour(&StartCol); 00708 pDC->OutputToken(_T("X")); 00709 } 00710 00711 pDC->OutputNewLine(); 00712 } 00713 else if (GetEndColour() == NULL) 00714 { 00715 DocColour EndCol; 00716 AttributeManager::FindDefaultColour(ColourManager::GetCurrentColourList(), 00717 _R(IDS_WHITENAME), &EndCol); 00718 00719 if (*GetStartColour() == EndCol) 00720 { 00721 AttributeManager::FindDefaultColour(ColourManager::GetCurrentColourList(), 00722 _R(IDS_BLACKNAME), &EndCol); 00723 } 00724 00725 // Output dummy end colour here 00726 if (EndCol.FindParentIndexedColour() == NULL) 00727 { 00728 // Unnamed colour 00729 PColourCMYK CMYK; 00730 EndCol.GetCMYKValue(&CMYK); 00731 pDC->OutputColour(&CMYK); 00732 pDC->OutputToken(_T("k")); 00733 } 00734 else 00735 { 00736 // Named colour 00737 pDC->OutputNamedColour(&EndCol); 00738 pDC->OutputToken(_T("x")); 00739 } 00740 00741 pDC->OutputNewLine(); 00742 } 00743 00744 // Co-ords first, 00745 for (INT32 i = 0; i <= 3; i++) 00746 pDC->OutputCoord(Coords[i]); 00747 00748 // ...then the bitmap object token. 00749 pDC->OutputToken(_T("cbm")); 00750 pDC->OutputNewLine(); 00751 00752 // ...and then the bitmap data itself. 00753 pDC->GetParentFilter()->ExportBitmap(*GetBitmap()); 00754 } 00755 else 00756 { 00757 // It's not a contone bitmap. 00758 // Oh bum. We've made a bit of a bo-bo with these. 00759 // Since we don't save 'no-colour' we don't know that 00760 // the bitmap has no-colour when re-loaded, and so it 00761 // uses the 'current' fill colour, so sometimes the bitmaps 00762 // come out coloured, when they shouldn't be. 00763 00764 // Solution .... We'll save this bitmap as a bitmap fill 00765 // (which already has a non-contone format), and save out 00766 // some extra stuff to tell the import routines that it's 00767 // not a bitmap fill, but really a bitmap object. 00768 // This means it will look correct in the Viewer (they'll 00769 // be loaded as bitmap filled paths), but will appear as 00770 // bitmaps when loaded into the main program. 00771 00772 // So first we'll output a new eps object (which will be Ignored by 00773 // the viewer), telling the main program that the following 00774 // object is really a bitmap object 00775 00776 pDC->OutputValue((INT32) EOTAG_BITMAPFLAGS); 00777 pDC->OutputToken(_T("cso")); // Start of new object type 00778 00779 pDC->OutputToken(_T("cbot")); // Flag the next bitmap fill as an object 00780 00781 pDC->OutputToken(_T("ceo")); // End of new object type 00782 pDC->OutputNewLine(); 00783 00784 // Now output the Bitmap fill 00785 pDC->OutputCoord(Coords[3]); 00786 pDC->OutputCoord(Coords[2]); 00787 pDC->OutputCoord(Coords[0]); 00788 00789 pDC->OutputValue((INT32) CAMEPS_FILL_BITMAP); 00790 pDC->OutputToken(_T("cax")); 00791 pDC->OutputNewLine(); 00792 00793 // ...and then the bitmap data itself. 00794 pDC->GetParentFilter()->ExportBitmap(*GetBitmap()); 00795 00796 // Now output a filled path for the Viewer to render 00797 // This will be skipped over by the new import code 00798 pDC->OutputCoord(Coords[0]); 00799 pDC->OutputToken(_T("m")); 00800 pDC->OutputNewLine(); 00801 pDC->OutputCoord(Coords[1]); 00802 pDC->OutputToken(_T("l")); 00803 pDC->OutputNewLine(); 00804 pDC->OutputCoord(Coords[2]); 00805 pDC->OutputToken(_T("l")); 00806 pDC->OutputNewLine(); 00807 pDC->OutputCoord(Coords[3]); 00808 pDC->OutputToken(_T("l")); 00809 pDC->OutputNewLine(); 00810 pDC->OutputCoord(Coords[0]); 00811 pDC->OutputToken(_T("l")); 00812 pDC->OutputNewLine(); 00813 pDC->OutputToken(_T("F")); // Filled path 00814 pDC->OutputNewLine(); 00815 } 00816 00817 // Now force the Fill Colour, Line Colour, and Line Width 00818 // attribute to output themselves again, 'cus old versions 00819 // (including the Viewer) will corrupt these attributes for 00820 // any subsequent objects 00821 00822 // Get rid of the current copies of the last output attrs 00823 delete pCamelotRegion->LastOutputAttrs[ATTR_FILLGEOMETRY].pAttr; 00824 delete pCamelotRegion->LastOutputAttrs[ATTR_STROKECOLOUR].pAttr; 00825 delete pCamelotRegion->LastOutputAttrs[ATTR_LINEWIDTH].pAttr; 00826 00827 // NULL the pointers 00828 pCamelotRegion->LastOutputAttrs[ATTR_FILLGEOMETRY].pAttr = NULL; 00829 pCamelotRegion->LastOutputAttrs[ATTR_STROKECOLOUR].pAttr = NULL; 00830 pCamelotRegion->LastOutputAttrs[ATTR_LINEWIDTH].pAttr = NULL; 00831 00832 // and clear the Temp flags so we don't try and delete them on exit 00833 pCamelotRegion->LastOutputAttrs[ATTR_FILLGEOMETRY].Temp = FALSE; 00834 pCamelotRegion->LastOutputAttrs[ATTR_STROKECOLOUR].Temp = FALSE; 00835 pCamelotRegion->LastOutputAttrs[ATTR_LINEWIDTH].Temp = FALSE; 00836 00837 // Re-output the attributes we've just reset 00838 pCamelotRegion->GetValidPathAttributes(); 00839 00840 // Tell caller we rendered ourselves ok 00841 return TRUE; 00842 } 00843 PORTNOTE("cmx", "Disabled CMXRenderRegion") 00844 #ifndef EXCLUDE_FROM_XARALX 00845 else if (pRegion->IsKindOf(CC_RUNTIME_CLASS(CMXRenderRegion))) 00846 { 00847 // mark start of a group... 00848 CMXExportDC *pDC = (CMXExportDC *)pRegion->GetRenderDC(); 00849 ERROR2IF(pDC == NULL, FALSE, "no dc in CMXRenderRegion"); 00850 KernelBitmap *pBittyThingy = BitmapRef.GetBitmap(); 00851 ERROR2IF(pBittyThingy == NULL, FALSE, "no bitmap in the node"); 00852 00853 pDC->WriteBitmap ( pBittyThingy, ( DocCoord * ) ( &Parallel ), 00854 CMXExportDC::CMXBITMAPCOLOURSOURCE_LINEANDFILL ); 00855 00856 return TRUE; 00857 } 00858 #endif 00859 else if ( pRegion->IsKindOf ( CC_RUNTIME_CLASS ( AIEPSRenderRegion ) ) ) 00860 { 00861 // Grab a pointer to the AIEPS_RenderRegion. 00862 AIEPSRenderRegion *pAIEPSRR = static_cast<AIEPSRenderRegion*> ( pRegion ); 00863 00864 // Write the bitmap using the render region's custom code. 00865 return pAIEPSRR->ExportBitmap ( this ); 00866 } 00867 00868 #endif 00869 // Render this node in the normal way 00870 return FALSE; 00871 } 00872 00873 00874 /******************************************************************************************** 00875 00876 > INT32 NodeBitmap::GetSizeOfExport(Filter *pFilter) 00877 00878 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 00879 Created: 27/01/95 00880 Inputs: pFilter - the filter that will be used to export this node. 00881 Returns: The number of 'nodes' this bitmap is equivalent to (in size). 00882 Purpose: Determine how many 'nodes' this bitmap is equivalent to. We use the 00883 rough approximation that each scanline taks the same amount of space as 00884 a typical node. This gives us enough granularity for a reasonably 00885 accurate and smooth progress display update. 00886 SeeAlso: - 00887 00888 ********************************************************************************************/ 00889 00890 INT32 NodeBitmap::GetSizeOfExport(Filter *pFilter) 00891 { 00892 #ifdef DO_EXPORT 00893 // Are we going to save the bitmap out as part of this object? 00894 if (pFilter->GetBitmapSupportLevel() != SimpleBitmapSupport) 00895 // No - just one node 00896 return 1; 00897 00898 // Find out how many scanlines there are, and return as the result. 00899 KernelBitmap *pBitmap = GetBitmap(); 00900 BitmapInfo Info; 00901 if (!pBitmap->ActualBitmap->GetInfo(&Info)) 00902 // something has gone wrong! 00903 return 1; 00904 00905 // Return number of scanlines. 00906 return Info.PixelHeight; 00907 #else 00908 return 0; 00909 #endif 00910 } 00911 00912 /******************************************************************************************** 00913 00914 > BOOL NodeBitmap::RequiresAttrib(NodeAttribute* pAttrib, 00915 BOOL Search = FALSE) 00916 00917 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 00918 Created: 14/4/95 00919 Inputs: pAttrib - specifies the attribute being enquired about. 00920 Search - See NodeRenderableInk::RequiresAttrib (Has no effect in this fn) 00921 Returns: TRUE => object supports this kind of attribute. 00922 FALSE => object does not support this kind of attribute, and so it 00923 should not be applied. 00924 Purpose: Determine which attributes a bitmap object supports a particular type of 00925 attribute. A bitmap only supports transparent fill geometries, 00926 mappings, and effects - all other attributes are rejected. 00927 SeeAlso: NodeRenderableInk::RequiresAttrib 00928 00929 ********************************************************************************************/ 00930 00931 BOOL NodeBitmap::RequiresAttrib(NodeAttribute* pAttrib, BOOL Search /*= FALSE*/) 00932 { 00933 // Sanity checks 00934 ERROR2IF(pAttrib == NULL, FALSE, "Pointer is null in NodeBitmap::RequiresAttrib"); 00935 00936 if ((pAttrib->IS_KIND_OF(AttrColourChange) || 00937 pAttrib->IS_KIND_OF(AttrStrokeColourChange))) 00938 { 00939 // Someone's trying to apply a contone colour 00940 // Remember this, so we can do a conversion in the 00941 // AllowOp routine. 00942 ApplyContoneColour = TRUE; 00943 00944 // Just say yes 00945 return TRUE; 00946 } 00947 00948 ApplyContoneColour = FALSE; 00949 00950 // Is it one we want? 00951 return ((pAttrib->IsAColourFill() && pAttrib->IsAFlatFill()) || 00952 pAttrib->IsAStrokeColour() || 00953 pAttrib->IsATranspFill() || 00954 pAttrib->IS_KIND_OF(AttrValueChange) || 00955 pAttrib->IS_KIND_OF(AttrColourDrop) || 00956 pAttrib->IS_KIND_OF(AttrTranspFillMapping) || 00957 pAttrib->IS_KIND_OF(AttrFillEffect) || 00958 pAttrib->IS_KIND_OF(AttrFillMapping) || 00959 PORTNOTE("other","Removed AttrWebAddress") 00960 #ifndef EXCLUDE_FROM_XARALX 00961 pAttrib->IS_KIND_OF(AttrWebAddress) || //Added by Graham 1/9/96, so bitmaps can have HotLinks 00962 #endif 00963 pAttrib->IS_KIND_OF(AttrUser) 00964 ); 00965 } 00966 00967 /******************************************************************************************** 00968 00969 > BOOL NodeBitmap::ApplyDefaultBitmapAttrs(UndoableOperation* pOp, 00970 AttrBitmapTranspFill* pTranspBitmap = NULL) 00971 00972 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 00973 Created: 19/4/95 00974 Inputs: pOp - the undoable operation in which this Node has been created. 00975 pTranspBitmap - optional bitmap to apply as transparency. (Default = NULL) 00976 Returns: TRUE => Default attribute where applied ok. 00977 FALSE => Apply failed. 00978 Purpose: Apply the default attributes that a NodeBitmap needs. 00979 This is specific to Bitmap Nodes, which need the Start and End colours 00980 to be NONE initially, and also need to ensure the line width is 0. 00981 There is now an optional pointer to a transparent bitmap fill to be applied 00982 over the current bitmap node. This is used by the transparent GIF import code. 00983 00984 00985 ********************************************************************************************/ 00986 00987 /* Note by Will 12/1/96 00988 00989 Removed Line transparency attr (AttrStrokeTransp), because this is no longer needed, 00990 and caused a bug where outlines disappeared when transparency is turned on (eg. after 00991 slicing a bitmap and applying a line colour). It is no longer required because the 00992 rendering code now looks at the line colour, rather than relying on the Line 00993 transparency attr being present. 00994 00995 */ 00996 00997 BOOL NodeBitmap::ApplyDefaultBitmapAttrs(UndoableOperation* pOp, 00998 AttrBitmapTranspFill* pTranspBitmap) 00999 { 01000 if (pTranspBitmap != NULL) 01001 { 01002 pTranspBitmap->AttachNode(this, FIRSTCHILD); 01003 01004 // Apply it as a single tiled fill. Otherwise in the GIF transparency case 01005 // the repeating can give ghost pixels along the edges. 01006 AttrTranspFillMappingLinear *pNoRepeatAttr = new AttrTranspFillMappingLinear; 01007 if (pNoRepeatAttr == NULL) 01008 return FALSE; 01009 01010 pNoRepeatAttr->Value.Repeat = 1; 01011 01012 pNoRepeatAttr->AttachNode(this, FIRSTCHILD); 01013 } 01014 01015 Node* pLineColAttr = new AttrStrokeColour(); 01016 if (pLineColAttr == NULL) 01017 return FALSE; 01018 01019 /* 01020 Node* pLineTranspAttr = new AttrStrokeTransp(); 01021 if (pLineTranspAttr == NULL) 01022 { 01023 delete pLineColAttr; 01024 return FALSE; 01025 } 01026 */ 01027 01028 Node* pFillColAttr = new AttrFlatColourFill(); 01029 if (pFillColAttr == NULL) 01030 { 01031 delete pLineColAttr; 01032 // delete pLineTranspAttr; 01033 return FALSE; 01034 } 01035 01036 Node* pLineWidthAttr = new AttrLineWidth(); 01037 if (pFillColAttr == NULL) 01038 { 01039 delete pLineColAttr; 01040 // delete pLineTranspAttr; 01041 delete pFillColAttr; 01042 return FALSE; 01043 } 01044 01045 DocColour colorNull(COLOUR_NONE); 01046 ((AttrFillGeometry*)pLineColAttr)->SetStartColour( &colorNull ); 01047 ((AttrFillGeometry*)pFillColAttr)->SetStartColour( &colorNull ); 01048 ((AttrLineWidth*)pLineWidthAttr)->Value.LineWidth = 0; 01049 01050 // UINT32 LineTransp = 255; 01051 // ((AttrFillGeometry*)pLineTranspAttr)->SetStartTransp(&LineTransp); 01052 // ((AttrFillGeometry*)pLineTranspAttr)->SetTranspType(1); 01053 01054 pLineColAttr->AttachNode(this, FIRSTCHILD); 01055 // pLineTranspAttr->AttachNode(this, FIRSTCHILD); 01056 pFillColAttr->AttachNode(this, FIRSTCHILD); 01057 pLineWidthAttr->AttachNode(this, FIRSTCHILD); 01058 01059 return TRUE; 01060 } 01061 01062 /******************************************************************************************** 01063 01064 > virtual BOOL NodeBitmap::CanBecomeA(BecomeA* pBecomeA) 01065 01066 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01067 Created: 13/1/95 01068 Inputs: pClass: The class of object 01069 pNumObjects = ptr to place number of objects of type pClass that will be created (Note: can be NULL). 01070 *pNumObects in undefined on entry 01071 Returns: TRUE if the node, or any of its children can transmogrify themselves to become 01072 an InkClass object 01073 Purpose: This function is used by the convert to shapes operation. It determines if 01074 the node or any of its children can convert themselves into an InkClass object. 01075 In the case of a node bitmap we must stop it from it having the make shapes 01076 applied as otherwise we will loose the bitmap from view. 01077 NodeSimpleShape overrides the baseclass function to return True. 01078 01079 The number you put into pNumObjects (if it's not NULL) should exactly equal the total number 01080 of pClass objects you create. It should NOT contain any additional objects you may produce 01081 such as group objects for containing the pClass object, or attributes. 01082 01083 Also, the entry value of *pNumObjects cannot be assumed to be 0. 01084 01085 ********************************************************************************************/ 01086 01087 BOOL NodeBitmap::CanBecomeA(BecomeA* pBecomeA) 01088 { 01089 // The NodeBitmap can become a NodePath (with a bitmap fill) 01090 if (pBecomeA->BAPath()) 01091 { 01092 pBecomeA->AddCount(1); 01093 return TRUE; 01094 } 01095 01096 return FALSE; 01097 } 01098 01099 /******************************************************************************************** 01100 01101 > virtual BOOL NodeBitmap::DoBecomeA(CCRuntimeClass* InkClass, UndoableOperation* pOp) 01102 01103 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 01104 Created: 16/2/95 01105 Inputs: pBecomeA = ptr to a class that contains all the info needed to become a new 01106 type of node. 01107 Outputs: - 01108 Returns: TRUE if the object has been transformed, FALSE if we run out of memory 01109 01110 Purpose: Transforms the object into another type of object. 01111 Note: changed 7/10/94 by MarkN to take the pBecomeA param, so that more data 01112 could be passed to these functions in the future without causing massive 01113 rebuilds due to the editing of node.h 01114 SeeAlso: NodeSimpleShape::CanBecomeA 01115 01116 ********************************************************************************************/ 01117 01118 BOOL NodeBitmap::DoBecomeA(BecomeA* pBecomeA) 01119 { 01120 // Check for a NULL entry param 01121 ERROR2IF_PF(pBecomeA == NULL,FALSE,("pBecomeA is NULL")); 01122 01123 // This lump checks that the Reason is one that we understand 01124 // It also makes sure that we don't have a NULL UndoOp ptr 01125 BOOL ValidReason = (pBecomeA->GetReason() == BECOMEA_REPLACE || pBecomeA->GetReason() == BECOMEA_PASSBACK); 01126 ERROR2IF_PF(!ValidReason,FALSE,("Unkown BecomeA reason %d",pBecomeA->GetReason())); 01127 01128 // pBecomeA->Reason is one that we understand. 01129 01130 UndoableOperation* pUndoOp = pBecomeA->GetUndoOp(); 01131 BOOL Success = TRUE; // Our success flag (Important that this defaults to TRUE) 01132 NodePath* pNewNodePath = NULL; // Ptr to a new NodePath, if we get to make one. 01133 01134 if (pBecomeA->BAPath()) 01135 { 01136 // We need to create a new NodePath, no matter what the reason. 01137 01138 // Allocate a new NodePath node 01139 ALLOC_WITH_FAIL(pNewNodePath, (new NodePath), pBecomeA->GetUndoOp()); 01140 Success = (pNewNodePath != NULL); 01141 01142 // Initialise the path 01143 if (Success) CALL_WITH_FAIL(pNewNodePath->InkPath.Initialise(InkPath.GetNumCoords(),12), pBecomeA->GetUndoOp(), Success); 01144 if (Success) CALL_WITH_FAIL(pNewNodePath->InkPath.CopyPathDataFrom(&InkPath), pBecomeA->GetUndoOp(), Success); 01145 01146 if (Success) pNewNodePath->InkPath.IsFilled = TRUE; 01147 01148 // If Success is TRUE, then we now have a new NodePath object that contains this shape's path 01149 01150 if (Success) 01151 { 01152 // Remember the contone colours before we go and hide the applied attributes 01153 DocColour* ContoneStart = GetStartColour(); 01154 DocColour* ContoneEnd = GetEndColour(); 01155 01156 switch (pBecomeA->GetReason()) 01157 { 01158 case BECOMEA_REPLACE : 01159 { 01160 // It's a BECOMEA_REPLACE, so replace this node with the new NodePath in an undoable way 01161 01162 // Can't do it in an undoable way without an Undo Op 01163 // ERROR2IF_PF(pBecomeA->GetUndoOp() == NULL,FALSE,("GetUndoOp() returned NULL")); 01164 01165 // The NodeBitmap uses the Fill and line colours to set it's 01166 // contone colours. 01167 // But the bitmap fill doesn't need them, so we will Hide 01168 // any of these attributes that we find applied 01169 Node* pChild = FindFirstChild(); 01170 while (pChild != NULL) 01171 { 01172 Node* pThisChild = pChild; 01173 pChild = pChild->FindNext(); // Find next before we hide this child 01174 01175 if (pThisChild->IsAnAttribute()) 01176 { 01177 NodeAttribute* pAttr = (NodeAttribute*)pThisChild; 01178 01179 if (pAttr->IsAColourFill() || 01180 pAttr->IsAStrokeColour() ) 01181 { 01182 if (pUndoOp) 01183 { 01184 // Hide and Fill or Line colour attributes 01185 NodeHidden* pNodeHidden; 01186 Success = pBecomeA->GetUndoOp()->DoHideNode(pAttr, TRUE, &pNodeHidden); 01187 } 01188 else 01189 { 01190 pAttr->CascadeDelete(); 01191 delete pAttr; 01192 } 01193 } 01194 } 01195 } 01196 01197 // Now make a Bitmap Fill that is equivalent to this NodeBitmap 01198 AttrFillGeometry* pBitmapFill; 01199 ALLOC_WITH_FAIL(pBitmapFill , new AttrBitmapColourFill(), pBecomeA->GetUndoOp()); 01200 01201 if (pBitmapFill) 01202 { 01203 pBitmapFill->AttachBitmap(GetBitmap()); 01204 01205 // Set any contone colours that we have 01206 pBitmapFill->SetStartColour(ContoneStart); 01207 pBitmapFill->SetEndColour(ContoneEnd); 01208 01209 // Set the control points from the NodeBitmap Parallelogram 01210 pBitmapFill->SetStartPoint(&Parallel[3]); 01211 pBitmapFill->SetEndPoint(&Parallel[2]); 01212 pBitmapFill->SetEndPoint2(&Parallel[0]); 01213 01214 pBitmapFill->AttachNode(this, FIRSTCHILD); 01215 01216 if (pUndoOp) 01217 { 01218 // Create a hide node action to hide the node when we undo 01219 HideNodeAction* UndoHideNodeAction; 01220 Success = (HideNodeAction::Init(pBecomeA->GetUndoOp(), 01221 pBecomeA->GetUndoOp()->GetUndoActionList(), 01222 pBitmapFill, 01223 TRUE, // Include subtree size 01224 ( Action**)(&UndoHideNodeAction)) 01225 != AC_FAIL); 01226 } 01227 } 01228 01229 // We also need to make sure it has no line colour 01230 AttrFillGeometry* pStrokeColour; 01231 ALLOC_WITH_FAIL(pStrokeColour , new AttrStrokeColour(), pBecomeA->GetUndoOp()); 01232 01233 if (pStrokeColour) 01234 { 01235 // Ensure the line colour is set to NONE 01236 DocColour NoCol = COLOUR_NONE; 01237 pStrokeColour->SetStartColour(&NoCol); 01238 01239 pStrokeColour->AttachNode(this, FIRSTCHILD); 01240 01241 if (pUndoOp) 01242 { 01243 // Create a hide node action to hide the node when we undo 01244 HideNodeAction* UndoHideNodeAction; 01245 Success = (HideNodeAction::Init(pBecomeA->GetUndoOp(), 01246 pBecomeA->GetUndoOp()->GetUndoActionList(), 01247 pStrokeColour, 01248 TRUE, // Include subtree size 01249 ( Action**)(&UndoHideNodeAction)) 01250 != AC_FAIL); 01251 } 01252 } 01253 01254 // Copy the node's attributes 01255 CALL_WITH_FAIL(CopyChildrenTo(pNewNodePath), pBecomeA->GetUndoOp(), Success); 01256 01257 // Insert the new NodePath into the tree, next to this node 01258 pNewNodePath->AttachNode(this,NEXT); 01259 01260 if (Success) 01261 { 01262 // Set the bounds 01263 pNewNodePath->InvalidateBoundingRect(); 01264 pNewNodePath->SetSelected(IsSelected()); 01265 01266 if (pUndoOp) 01267 { 01268 // Create a hide node action to hide the node when we undo 01269 HideNodeAction* UndoHideNodeAction; 01270 Success = (HideNodeAction::Init(pBecomeA->GetUndoOp(), 01271 pBecomeA->GetUndoOp()->GetUndoActionList(), 01272 pNewNodePath, 01273 TRUE, // Include subtree size 01274 ( Action**)(&UndoHideNodeAction)) 01275 != AC_FAIL); 01276 } 01277 } 01278 01279 if (Success) 01280 { 01281 CCAttrMap AttrMap; 01282 CCAttrMap* pAttrMap = NULL; 01283 BOOL bFoundAttrs = pNewNodePath->FindAppliedAttributes(&AttrMap); 01284 if (bFoundAttrs) 01285 pAttrMap = AttrMap.Copy(); 01286 pBecomeA->PassBack(pNewNodePath, this, pAttrMap); 01287 } 01288 01289 // Now hide this NodeBitmap 01290 if (pUndoOp) 01291 { 01292 NodeHidden* pNodeHidden; 01293 Success = pBecomeA->GetUndoOp()->DoHideNode(this, TRUE, &pNodeHidden); 01294 } 01295 else 01296 { 01297 CascadeDelete(); 01298 delete this; // Scary! 01299 } 01300 } 01301 break; 01302 01303 case BECOMEA_PASSBACK : 01304 { 01305 // First find all attributes applied to this node... 01306 // 30 is a default value - this will grow if it needs more space 01307 CCAttrMap* pAttribMap = new CCAttrMap(30); 01308 CCAttrMap* pCopyOfAttrMap = NULL; 01309 01310 // Now find any attributes that are applied to this node. 01311 /*BOOL FoundAttrs =*/ FindAppliedAttributes(pAttribMap); 01312 01313 // size_t AttrCount = FoundAttrs ? pAttribMap->GetCount() : 30; 01314 01315 // Now make a copy of the applied attributes map 01316 pCopyOfAttrMap = pAttribMap->Copy ();//new CCAttrMap(AttrCount); 01317 if (pCopyOfAttrMap != NULL) 01318 { 01319 // We've made a copy of the Attr map now, so we don't need 01320 // the old one anymore 01321 delete pAttribMap; 01322 01323 // Replace the Fill and Line Colour attributes 01324 // in the Attr Map copy 01325 01326 AttrFillGeometry* pBitmapFill = new AttrBitmapColourFill(); 01327 if (pBitmapFill) 01328 { 01329 // Make a Bitmap Fill that is equivalent to this 01330 // node bitmap 01331 pBitmapFill->AttachBitmap(GetBitmap()); 01332 01333 // Set any contone colours that we have 01334 pBitmapFill->SetStartColour(ContoneStart); 01335 pBitmapFill->SetEndColour(ContoneEnd); 01336 01337 // Set the control points from the NodeBitmap Parallelogram 01338 pBitmapFill->SetStartPoint(&Parallel[3]); 01339 pBitmapFill->SetEndPoint(&Parallel[2]); 01340 pBitmapFill->SetEndPoint2(&Parallel[0]); 01341 01342 void* pOldFill; 01343 if( pCopyOfAttrMap->Lookup( CC_RUNTIME_CLASS(AttrFillGeometry), pOldFill ) ) 01344 { 01345 // We need to Remove and Delete the existing Fill Attr 01346 pCopyOfAttrMap->RemoveKey( CC_RUNTIME_CLASS(AttrFillGeometry) ); 01347 delete (AttrFillGeometry*)pOldFill; 01348 } 01349 01350 // Add the Bitmap fill into the Attr Map 01351 pCopyOfAttrMap->SetAt( CC_RUNTIME_CLASS(AttrFillGeometry), (void*)pBitmapFill ); 01352 } 01353 01354 AttrFillGeometry* pStrokeColour = new AttrStrokeColour(); 01355 if (pStrokeColour) 01356 { 01357 // Ensure the line colour is set to NONE 01358 DocColour NoCol = COLOUR_NONE; 01359 pStrokeColour->SetStartColour(&NoCol); 01360 01361 void* pOldStroke; 01362 if( pCopyOfAttrMap->Lookup( CC_RUNTIME_CLASS(AttrStrokeColour), pOldStroke ) ) 01363 { 01364 // We need to Remove and Delete the existing Stroke Colour Attr 01365 pCopyOfAttrMap->RemoveKey( CC_RUNTIME_CLASS(AttrStrokeColour) ); 01366 delete (AttrFillGeometry*)pOldStroke; 01367 } 01368 01369 // Add the new Stroke Colour into the Attr Map 01370 pCopyOfAttrMap->SetAt( CC_RUNTIME_CLASS(AttrStrokeColour), (void*)pStrokeColour ); 01371 } 01372 } 01373 01374 Success = pBecomeA->PassBack(pNewNodePath, this, pCopyOfAttrMap); 01375 } 01376 break; 01377 01378 case BECOMEA_TEST: 01379 // Do nothing 01380 break; 01381 01382 default: 01383 { 01384 ERROR3("Unhandled BecomeA type in NodeBitmap::DoBecomeA"); 01385 } 01386 } 01387 } 01388 } 01389 01390 if (!Success) 01391 { 01392 if (pNewNodePath != NULL) 01393 { 01394 // Delete all the NodePath's children (if it has any) and unlink it from the tree (if it's linked) 01395 // This is all done by CascadeDelete() 01396 pNewNodePath->CascadeDelete(); 01397 delete pNewNodePath; 01398 pNewNodePath = NULL; 01399 } 01400 } 01401 01402 return Success; 01403 } 01404 01405 /******************************************************************************************** 01406 01407 > virtual BOOL NodeBitmap::AllowOp(ObjChangeParam* pParam,BOOL SetOpPermissionState = TRUE) 01408 01409 Author: Mark_Neves (Xara Group Ltd) <camelotdev@xara.com> 01410 Created: 3/02/95 01411 Inputs: pParam = describes the way an op wants to change the node 01412 SetOpPermissionState = if TRUE the Op permission state of this node will be set according to 01413 the outcome of the call 01414 Outputs: - 01415 Returns: TRUE means the node and all its parents are happy with this op, FALSE means don't do it 01416 Purpose: This is the way to ask a node if you can do an op to it. 01417 01418 The ObjChangeParam class contains flags that describe how it will change the node 01419 01420 For example, the op could change the node's appearence (e.g. attr application, editing a path), 01421 replace the node with another node (e.g. because it uses hidden nodes to hide the original and put another 01422 node in its place, or "make shapes"), delete the node (e.g. the delete and cut ops), etc. 01423 01424 This function gives the node a chance to say NO. It also gives the parents a chance to say no too. 01425 E.g. a blend node will allow itself to be deleted, but it will NOT allow a child of itself to be deleted). 01426 01427 This call should only be made on selected, or parents of selected, nodes. It makes a decision as a 01428 straight node if it is selected. It makes a decision as a parent if it has selected children. 01429 01430 E.g. NodeBlend::AllowOp(...op delete...) 01431 if the node is selected, then it will return TRUE (parents permitting), i.e. I can be deleted 01432 if the node is a parent of selected it will return FALSE (i.e. can't delete children of blends). 01433 01434 So when the node is selected, you are asking the node if you can do the op to it. When the node is 01435 a parent of a selected node, you are asking if you can do the op to one of its children. 01436 01437 ******** 01438 01439 If the 'SetOpPermissionState' param is TRUE, the following indented lines applies: 01440 The node's op permission state is set according to the result of this function. 01441 01442 If TRUE is returned, then the node's op permission state will be left unchanged. 01443 AND the parent's op permission state will be set to PERMISSION_ALLOWED 01444 01445 if FALSE is returned, then the node's op permission state will be PERMISSION_DENIED, 01446 AND all it's parents (up to the layer) will be set to PERMISSION_DENIED 01447 01448 Also, all parents of this node are called via their AllowOp() func with the same state 01449 as this node. This means that after this call, you can guarantee that all of its parents will 01450 have either a PERMISSION_DENIED or PERMISSION_ALLOWED state. 01451 01452 Note: Even if this node tries to set all it's parents to have a PERMISSION_DENIED state, if any 01453 of its parents have previously been set to PERMISSION_ALLOWED they will remain in that state (see 01454 SetOpPermission()). Why? Well, it is possible for a parent node to have one child with a 01455 PERMISSION_DENIED and another child with a PERMISSION_ALLOWED. It this state the parent MUST be 01456 in state PERMISSION_ALLOWED, because at least one of its children will allow the op to happen to it. 01457 01458 So, after this call: 01459 The op permission state for this node will be either left unchanged (and 01460 therefore remain PERMISSION_UNDEFINED), or PERMISSION_DENIED. 01461 01462 The parent's op permission state will be either PERMISSION_ALLOWED, or PERMISSION_DENIED. 01463 01464 This is so UndoableOperation::UpdateChangedNodes() will only call OnChildChange() on parent nodes, 01465 because it only calls that func for nodes that have an op permission state of PERMISSION_ALLOWED. 01466 01467 ******** 01468 01469 SeeAlso: GetOpPermission(),SetOpPermission(); 01470 01471 ********************************************************************************************/ 01472 01473 BOOL NodeBitmap::AllowOp(ObjChangeParam* pParam, BOOL SetOpPermissionState) 01474 { 01475 ERROR2IF(pParam==NULL,FALSE,"Node::AllowOp() - pParam==NULL"); 01476 01477 // if not called by a child AllowOp(), ensure AllowOp() called for all nodes in compound nodes, 01478 if (pParam->GetDirection()!=OBJCHANGE_CALLEDBYCHILD) 01479 { 01480 BOOL AnyAllowed=AllowOp_AccountForCompound(pParam, SetOpPermissionState); 01481 // if called by a parent, just pass this result back 01482 if (pParam->GetDirection()==OBJCHANGE_CALLEDBYPARENT) 01483 return AnyAllowed; 01484 } 01485 else 01486 { 01487 // clean out the calling-child ptr, so it doesn't get passed around unintentionally. 01488 pParam->SetCallingChild(NULL); 01489 } 01490 01491 // at this point we must have been called directly by the op or via a child AllowOp() 01492 01493 // decide if we allow it ... 01494 BOOL allowed=TRUE; 01495 ObjChangeFlags Flags = pParam->GetChangeFlags(); 01496 01497 if (Flags.Attribute) 01498 { 01499 // Someone is applying an attribute ..... 01500 // We really need to check the actual attribute, so for 01501 // now we'll rely on the fact that the 'RequiresAttrib()' 01502 // function will have been called before this one. 01503 01504 // If we are applying a contone colour, then make sure we 01505 // are a Grey level bitmap, and give the user the option 01506 // of making one if not. 01507 if (ApplyContoneColour) 01508 { 01509 // 'ApplyContoneColour' is set in the 'RequiresAttrib()' 01510 // function if a contone colour change attr is applied. 01511 allowed = MakeContoneBitmap(pParam->GetOpPointer()); 01512 } 01513 } 01514 01515 // if we allowed it, see if our parents do ... 01516 if (allowed && Parent!=NULL) 01517 { 01518 ObjChangeDirection OldDirection=pParam->GetDirection(); 01519 pParam->SetCallingChild(this); 01520 pParam->SetDirection(OBJCHANGE_CALLEDBYCHILD); 01521 allowed=Parent->AllowOp(pParam,SetOpPermissionState); 01522 pParam->SetDirection(OldDirection); 01523 } 01524 01525 // if setting permisions ... 01526 if (SetOpPermissionState) 01527 { 01528 // if allowed, mark parent accordingly, else mark child as denied and update parents 01529 if (allowed) 01530 Parent->SetOpPermission(PERMISSION_ALLOWED); 01531 else 01532 SetOpPermission(PERMISSION_DENIED,TRUE); 01533 } 01534 01535 // return result (directly, or indirectly via a child AllowOp()) to op 01536 return allowed; 01537 } 01538 01539 /******************************************************************************************** 01540 01541 > BOOL NodeBitmap::MakeContoneBitmap(UndoableOperation* pOperation) 01542 01543 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 01544 Created: 27/6/95 01545 Purpose: Make this NodeBitmap into a grey level version of itself. 01546 01547 ********************************************************************************************/ 01548 01549 BOOL NodeBitmap::MakeContoneBitmap(UndoableOperation* pOperation) 01550 { 01551 KernelBitmap* pBitmap = GetBitmap(); 01552 KernelBitmap* pGreyBmp = CheckGreyscaleBitmap(pBitmap, _R(IDS_MAKEGREY), _R(IDS_DOGREY)); 01553 01554 if (pGreyBmp == NULL) 01555 return FALSE; // Failed in some way (or the user cancelled) 01556 01557 return TRUE; 01558 } 01559 01560 /******************************************************************************************** 01561 01562 > static KernelBitmap* NodeBitmap::CheckGreyscaleBitmap( KernelBitmap* pBitmap, 01563 UINT32 PromptID, UINT32 OkID) 01564 01565 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 01566 Created: 27/6/95 01567 Purpose: Checks a bitmap to see if can be applied as a texture, 01568 and gives the option to create a grey level version if not. 01569 01570 ********************************************************************************************/ 01571 01572 KernelBitmap* NodeBitmap::CheckGreyscaleBitmap(KernelBitmap* pBitmap, UINT32 PromptID, UINT32 OkID) 01573 { 01574 #if !defined(EXCLUDE_FROM_RALPH) 01575 ERROR2IF(pBitmap == NULL, NULL, "Null bitmap passed to CheckGreyscaleBitmap"); 01576 01577 // Don't need to do anything here now, as the greyscale bitmap is generated on the 01578 // fly when rendering 01579 01580 return pBitmap; 01581 #else 01582 ERROR3("NodeBitmap::CheckGreyscaleBitmap"); 01583 return NULL; 01584 #endif 01585 } 01586 01587 /******************************************************************************************** 01588 01589 > KernelBitmap* NodeBitmap::GetBitmap() 01590 01591 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 01592 Created: 12/1/95 01593 Purpose: Get the bitmap referenced by this node. 01594 01595 ********************************************************************************************/ 01596 01597 KernelBitmap* NodeBitmap::GetBitmap() 01598 { 01599 KernelBitmap* pBitmap = BitmapRef.GetBitmap(); 01600 01601 // Check for a deleted bitmap 01602 if (pBitmap && pBitmap->HasBeenDeleted()) 01603 { 01604 ERROR2IF(pBitmap->GetParentBitmapList() == NULL, NULL, "Deleted bitmap has no parent list"); 01605 01606 // Use the default bitmap instead 01607 pBitmap = pBitmap->GetParentBitmapList()->FindDefaultBitmap(); 01608 01609 // There should always be a default bitmap in the list 01610 ERROR2IF(pBitmap == NULL, 0L, "Couldn't find the default bitmap"); 01611 } 01612 01613 return pBitmap; 01614 } 01615 01616 /*********************************************************************************************** 01617 01618 > virtual BOOL NodeBitmap::HidingNode() 01619 01620 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 01621 Created: 11/1/94 01622 Returns: TRUE if all was ok. FALSE if an error occured. 01623 Purpose: This virtual function is called whenever the node is hidden. 01624 It allows the node do things like 'optimise' itself to use less memory or 01625 send a message to let others know it is being hidden etc. 01626 01627 ALWAYS CALL THE BASE CLASS' FUNCTION FROM YOUR OVERRIDDEN FUNCTION. 01628 01629 ***********************************************************************************************/ 01630 01631 BOOL NodeBitmap::HidingNode() 01632 { 01633 // Call the base class first 01634 if (!NodeRect::HidingNode()) 01635 return FALSE; 01636 01637 GetBitmapRef()->RemoveFromTree(); 01638 01639 return TRUE; 01640 } 01641 01642 /*********************************************************************************************** 01643 01644 > virtual BOOL NodeBitmap::ShowingNode() 01645 01646 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 01647 Created: 11/1/94 01648 Returns: TRUE if all was ok. FALSE if an error occured (eg Out of memory). 01649 Purpose: This virtual function is called whenever the node is re-shown after being 01650 Hidden. 01651 It allows the node to reconstruct itself if it was optimised or 01652 send a message to let others know it is back etc. 01653 01654 ALWAYS CALL THE BASE CLASS' FUNCTION FROM YOUR OVERRIDDEN FUNCTION. 01655 01656 ***********************************************************************************************/ 01657 01658 BOOL NodeBitmap::ShowingNode() 01659 { 01660 // Call the base class first 01661 if (!NodeRect::ShowingNode()) 01662 return FALSE; 01663 01664 GetBitmapRef()->AddtoTree(); 01665 01666 return TRUE; 01667 } 01668 01669 /******************************************************************************************** 01670 01671 > void NodeBitmap::SetStartColour(DocColour* NewCol) 01672 01673 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 01674 Created: 26/1/95 01675 Purpose: Set the start colour of a bitmap palette 01676 01677 ********************************************************************************************/ 01678 01679 void NodeBitmap::SetStartColour(DocColour* NewCol) 01680 { 01681 if (NewCol == NULL) 01682 Colour = COLOUR_NONE; 01683 else 01684 Colour = *NewCol; 01685 } 01686 01687 /******************************************************************************************** 01688 01689 > void NodeBitmap::SetEndColour(DocColour* NewCol) 01690 01691 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 01692 Created: 26/1/95 01693 Purpose: Set the end colour of a bitmap palette 01694 01695 ********************************************************************************************/ 01696 01697 void NodeBitmap::SetEndColour(DocColour* NewCol) 01698 { 01699 if (NewCol == NULL) 01700 EndColour = COLOUR_NONE; 01701 else 01702 EndColour = *NewCol; 01703 } 01704 01705 /******************************************************************************************** 01706 01707 > DocColour* NodeBitmap::GetStartColour() 01708 01709 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 01710 Created: 26/1/95 01711 Returns: NULL if there is no colour (> 8bpp), or a pointer to the Start Colour. 01712 Purpose: Gets the start colour of the bitmap palette 01713 01714 ********************************************************************************************/ 01715 01716 DocColour* NodeBitmap::GetStartColour() 01717 { 01718 /* 01719 if (Colour == COLOUR_NONE) 01720 return NULL; 01721 else 01722 return &Colour; 01723 */ 01724 01725 // if (GetBitmap()->GetBPP() <= 8) 01726 // { 01727 NodeAttribute* pLineAttr; 01728 01729 if (!FindAppliedAttribute(CC_RUNTIME_CLASS(AttrStrokeColour), &pLineAttr)) 01730 return NULL; 01731 01732 DocColour* Col = ((AttrStrokeColour*)pLineAttr)->GetStartColour(); 01733 if (Col && *Col != COLOUR_NONE) 01734 return Col; 01735 // } 01736 01737 return NULL; 01738 } 01739 01740 /******************************************************************************************** 01741 01742 > DocColour* NodeBitmap::GetEndColour() 01743 01744 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 01745 Created: 26/1/95 01746 Returns: NULL if there is no colour (> 8bpp), or a pointer to the End Colour. 01747 Purpose: Gets the end colour of the bitmap palette 01748 01749 ********************************************************************************************/ 01750 01751 DocColour* NodeBitmap::GetEndColour() 01752 { 01753 /* 01754 if (EndColour == COLOUR_NONE) 01755 return NULL; 01756 else 01757 return &EndColour; 01758 */ 01759 01760 // if (GetBitmap()->GetBPP() <= 8) 01761 // { 01762 NodeAttribute* pFillAttr; 01763 01764 if (!FindAppliedAttribute(CC_RUNTIME_CLASS(AttrFillGeometry), &pFillAttr)) 01765 return NULL; 01766 01767 DocColour* Col = ((AttrFillGeometry*)pFillAttr)->GetStartColour(); 01768 if (Col && *Col != COLOUR_NONE) 01769 return Col; 01770 // } 01771 01772 return NULL; 01773 } 01774 01775 01776 /******************************************************************************************** 01777 01778 > BOOL NodeBitmap::HasSimpleOrientation(RenderRegion *pRegion) 01779 01780 Author: Tim_Browse (Xara Group Ltd) <camelotdev@xara.com> 01781 Created: 31/7/95 01782 Inputs: pRegion - the region that the bitmap orientation should be tested in. 01783 Returns: TRUE if the bitmap orientation is a simple rectangular stretch, perpendicular 01784 to the co-ordinate system; 01785 FALSE if not (e.g. rotation or shearing applied to bitmap). 01786 Purpose: Determine if a bitmap is classified as a 'simple' bitmap, for use during the 01787 complex rendering of a view - if the render region can support simple bitmaps 01788 and this function returns TRUE, then we render the bitmap directly, otherwise 01789 it goes into the masked GDraw bitmap and is rendered that way. 01790 SeeAlso: DrawTransformedBitmap 01791 01792 ********************************************************************************************/ 01793 01794 BOOL NodeBitmap::HasSimpleOrientation(RenderRegion *pRegion) 01795 { 01796 PORTNOTETRACE("other","NodeBitmap::HasSimpleOrientation - do nothing"); 01797 #ifndef EXCLUDE_FROM_XARALX 01798 // Get information from the render region 01799 View *RenderView = pRegion->GetRenderView(); 01800 Matrix RenderMatrix = pRegion->GetMatrix(); 01801 01802 if (RenderView == NULL) 01803 // We can't tell - assume the worst 01804 return FALSE; 01805 01806 // Check for sideways printing - if the render matrix has rotation, then we are 01807 // printing at 270 degrees rotation, so we can't do the blit. 01808 FIXED16 RenderABCD[4]; 01809 INT32 RenderEF[2]; 01810 RenderMatrix.GetComponents(RenderABCD, RenderEF); 01811 if ((RenderABCD[1] != FIXED16(0)) || (RenderABCD[2] != FIXED16(0))) 01812 // Rotated by 270 degrees - not simple orientation 01813 return FALSE; 01814 01815 // Check the co-ordinates 01816 DocCoord *Coords = InkPath.GetCoordArray(); 01817 01818 // Use tolerance of 1 pixel when checking for perpendicular nature of the 01819 // bitmap, as undo/redo can cause small millipoint errors that we should 01820 // cope with. 01821 FIXED16 fxPixelSize; 01822 RenderView->GetScaledPixelSize(&fxPixelSize, &fxPixelSize); 01823 MILLIPOINT Tolerance = fxPixelSize.MakeLong(); 01824 01825 MILLIPOINT Diff1 = abs(Coords[0].x - Coords[3].x); 01826 MILLIPOINT Diff2 = abs(Coords[1].x - Coords[2].x); 01827 MILLIPOINT Diff3 = abs(Coords[0].y - Coords[1].y); 01828 MILLIPOINT Diff4 = abs(Coords[3].y - Coords[2].y); 01829 01830 if ((Diff1 < Tolerance) && (Diff2 < Tolerance) && 01831 (Diff3 < Tolerance) && (Diff4 < Tolerance)) 01832 { 01833 // Yes - simple rectangular orientation. 01834 return TRUE; 01835 } 01836 #endif 01837 // Complex bitmap orientation 01838 return FALSE; 01839 } 01840 01841 01842 01843 01844 /******************************************************************************************** 01845 01846 > Matrix NodeBitmap::GetInstanceTransform() 01847 01848 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 01849 Created: 27/07/2005 01850 Inputs: - 01851 Returns: Matrix containing the combined transformations that are required to 01852 get from the original bitmap size and position to that represented by the 01853 current NodeSimpleShape parallelogram. 01854 Purpose: Find the instance transform matrix 01855 Notes: Parallelogram format includes 4 coords and is stored in this format: 01856 0-------1 01857 | | 01858 3-------2 01859 (Why?) 01860 01861 ********************************************************************************************/ 01862 01863 Matrix NodeBitmap::GetInstanceTransform() 01864 { 01865 // First construct matrix to get from OriginalBitmapRect to unit square 01866 // Then construct matrix to get from unit square to current parallelogram 01867 // Then combine the two matrices 01868 // Do the maths in doubles for speed and accuracy! 01869 01870 DocRect oRect = GetOriginalBitmapRect(); 01871 01872 // Construct the original-to-unit matrix 01873 double oa = 1.0/oRect.Width(); 01874 double ob = 0; 01875 double oc = 0; 01876 double od = 1.0/oRect.Height(); 01877 double oe = -oRect.lo.x; 01878 double of = -oRect.lo.y; 01879 01880 // Construct the matrix for unit-to-instance-on-page matrix 01881 double ia = Parallel[2].x-Parallel[3].x; 01882 double ib = Parallel[2].y-Parallel[3].y; 01883 double ic = Parallel[0].x-Parallel[3].x; 01884 double id = Parallel[0].y-Parallel[3].y; 01885 double ie = Parallel[3].x; 01886 double i_f = Parallel[3].y; 01887 01888 // Multiply the two matrices 01889 double ra = oa * ia + ob * ic + 0 * ie; 01890 double rb = oa * ib + ob * id + 0 * i_f; 01891 double rc = oc * ia + od * ic + 0 * ie; 01892 double rd = oc * ib + od * id + 0 * i_f; 01893 double re = oe * ia + of * ic + 1 * ie; 01894 double rf = oe * ib + of * id + 1 * i_f; 01895 01896 // Return a crappy old FIXED16-based Matrix object 01897 return Matrix(ra, rb, rc, rd, INT32(re), INT32(rf) ); 01898 } 01899 01900 01901 01902 01903 /******************************************************************************************** 01904 01905 > DocRect NodeBitmap::GetOriginalBitmapRect() 01906 01907 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 01908 Created: 27/07/2005 01909 Inputs: - 01910 Returns: DocRect containing the size of the bitmap if it were placed on the 01911 page untransformed. 01912 Purpose: Find the starting point for the instance transform 01913 01914 ********************************************************************************************/ 01915 01916 DocRect NodeBitmap::GetOriginalBitmapRect() 01917 { 01918 DocRect oRect; 01919 KernelBitmap* pkBitmap = GetBitmap(); 01920 if (pkBitmap==NULL) 01921 return oRect; 01922 01923 oRect.lo.x = 0; 01924 oRect.lo.y = 0; 01925 // oRect.hi.x = 750.0 * pkBitmap->GetWidth(); // Note: Pixel width, ignoring bitmap's stated DPI 01926 // oRect.hi.y = 750.0 * pkBitmap->GetHeight(); // Note: Pixel height, ignoring bitmap's stated DPI 01927 oRect.hi.x = pkBitmap->GetRecommendedWidth(); 01928 oRect.hi.y = pkBitmap->GetRecommendedHeight(); 01929 01930 return oRect; 01931 } 01932 01933 01934 01935 01936 /******************************************************************************************** 01937 01938 > BOOL NodeBitmap::GetDirectBitmap(RenderRegion* pRender, LPBITMAPINFO* plpInfo, LPBYTE* plpBits, DocRect* pRect, Matrix* pMat, double* pdRes) 01939 01940 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 01941 Created: 28/07/2005 01942 Inputs: pMat - pointer to matrix awaiting update 01943 Outputs: plpInfo - LPBITMAPINFO pointer describing bitmap 01944 plpBits - LPBYTE pointer to bitmap data 01945 pRect - rect of Original bitmap data 01946 pMat - matrix describing transform from pRect to this instance on the page 01947 pdRes - resolution of this bitmap (dpi) 01948 Returns: TRUE if this node can supply direct bitmap data to the caller 01949 FALSE otherwise 01950 Purpose: Return details of direct bitmap to caller (caller is usually a NodeBitmapEffect) 01951 01952 ********************************************************************************************/ 01953 01954 BOOL NodeBitmap::GetDirectBitmap(RenderRegion* pRender, LPBITMAPINFO* plpInfo, LPBYTE* plpBits, DocRect* pRect, Matrix* pMat, double* pdRes) 01955 { 01956 KernelBitmap* pkBitmap = GetBitmap(); 01957 01958 // Initial response is to return our raw bitmap info... 01959 if (plpInfo) *plpInfo = pkBitmap->GetBitmapInfo(); 01960 if (plpBits) *plpBits = pkBitmap->GetBitmapBits(); 01961 if (pRect) *pRect = GetOriginalBitmapRect(); 01962 if (pMat) *pMat = GetInstanceTransform(); 01963 if (pdRes) *pdRes = pkBitmap->GetHorizontalDPI(); 01964 01965 // Now test whether the user is asking for a bitmap and whether our raw bitmap needs to 01966 // be specially processed... 01967 if (plpInfo && plpBits && HasBitmapAttrs()) 01968 { 01969 // Lookup processed bitmap in cache 01970 CBitmapCache* pBitmapCache = Camelot.GetBitmapCache(); 01971 if (pBitmapCache==NULL) 01972 return FALSE; 01973 01974 CBitmapCacheKey inky(this, 72000.0/pkBitmap->GetHorizontalDPI(), 2); // Option 2 is processed/rendered bitmap (see below) 01975 CCachedBitmap cbmp; 01976 BOOL bFound = pBitmapCache->Lookup(inky, cbmp); 01977 if (bFound) 01978 { 01979 if (plpInfo) *plpInfo = cbmp.pbmpInfo; 01980 if (plpBits) *plpBits = cbmp.pbmpBits; 01981 return TRUE; 01982 } 01983 01984 // We need to create a new bitmap here that captures the effects of the attributes 01985 // 01986 // If we don't have a RenderRegion, we can't build it, so return NULLs to indicate 01987 // that we need to be called again with a RenderRegion (allows quick test) 01988 // (See EnsureLiveEffectOriginalBitmaps) 01989 if (pRender == NULL) 01990 { 01991 if (plpInfo) *plpInfo = NULL; 01992 if (plpBits) *plpBits = NULL; 01993 return TRUE; 01994 } 01995 01996 // We must "render" this bitmap to capture the attributes that effect its appearance 01997 // By default, we can't do arbitrarily transformed bitmaps - use a bitmap fill. 01998 AttrFillGeometry* pTranspAttr = NULL; 01999 AttrFeather* pFeatherAttr = NULL; 02000 BitmapTranspFillAttribute* pFeatherTransp = NULL; 02001 KernelBitmap* pFeatherBitmap = NULL; 02002 MILLIPOINT mpScaledFeatherSize = 0; 02003 CProfileBiasGain profileFeather; 02004 DocRect CaptureRect = GetOriginalBitmapRect(); 02005 CaptureFlags caFlags = CaptureFlags(cfLOCKEDTRANSPARENT | cfFULLCOVERAGE); 02006 pRender->StartCapture(this, CaptureRect, CAPTUREINFO(ctNESTABLE, caFlags), TRUE, FALSE, pkBitmap->GetHorizontalDPI()); 02007 pRender->SaveContext(); 02008 02009 { // ------------------------------------------------------ 02010 // Setup coords for rendering in DirectBitmap domain 02011 DocCoord coords[3]; 02012 coords[0] = CaptureRect.lo; 02013 coords[1] = DocCoord(CaptureRect.hi.x, CaptureRect.lo.y); 02014 coords[2] = DocCoord(CaptureRect.lo.x, CaptureRect.hi.y); 02015 02016 // Create the path to be rendered in the DirectBitmap domain 02017 Path InkPath; 02018 InkPath.Initialise(); 02019 InkPath.AddMoveTo(coords[0]); 02020 InkPath.AddLineTo(coords[1]); 02021 InkPath.AddLineTo(DocCoord(coords[2].x+coords[1].x-coords[0].x, coords[2].y+coords[1].y-coords[0].y)); 02022 InkPath.AddLineTo(coords[2]); 02023 InkPath.AddLineTo(coords[0]); 02024 InkPath.CloseSubPath(); 02025 InkPath.IsFilled = TRUE; 02026 02027 // Compute the inverse transform matrix - a matrix to get from "Screen space" to "Direct space" 02028 Matrix matInverse = GetInstanceTransform().Inverse(); 02029 02030 // No lines on the rectangle 02031 pRender->SetLineColour(COLOUR_TRANS); 02032 pRender->SetLineWidth(0); 02033 02034 // Render the transparency geometry using inverse Direct-Screen transform 02035 // (This bitmap is being rendered in "Direct space" whereas the transparency attribute 02036 // was applied in "Screen space") 02037 NodeAttribute* pAttr; 02038 if (FindAppliedAttribute(CC_RUNTIME_CLASS(AttrTranspFillGeometry), &pAttr)) 02039 { 02040 if (pAttr && !pAttr->IsADefaultAttr() && !pAttr->HasEquivalentDefaultValue(TRUE)) 02041 { 02042 pTranspAttr = (AttrFillGeometry*) ((AttrFillGeometry*)pAttr)->SimpleCopy(); 02043 if (pTranspAttr) 02044 { 02045 DocCoord tcoords[4]; 02046 DocCoord* pCoord = NULL; 02047 pCoord = pTranspAttr->GetStartPoint(); 02048 tcoords[0] = pCoord ? *pCoord : DocCoord(0,0); 02049 pCoord = pTranspAttr->GetEndPoint(); 02050 tcoords[1] = pCoord ? *pCoord : DocCoord(0,0); 02051 pCoord = pTranspAttr->GetEndPoint2(); 02052 tcoords[2] = pCoord ? *pCoord : DocCoord(0,0); 02053 pCoord = pTranspAttr->GetEndPoint3(); 02054 tcoords[3] = pCoord ? *pCoord : DocCoord(0,0); 02055 02056 matInverse.transform(tcoords, 4); 02057 02058 pTranspAttr->SetStartPoint(&tcoords[0]); 02059 pTranspAttr->SetEndPoint(&tcoords[1]); 02060 pTranspAttr->SetEndPoint2(&tcoords[2]); 02061 pTranspAttr->SetEndPoint3(&tcoords[3]); 02062 02063 pTranspAttr->Render(pRender); 02064 } 02065 } 02066 } 02067 02068 // Render the feather attribute with inverse scaled feather width 02069 // (This bitmap is being rendered in "Direct space" whereas the attribute 02070 // was applied in "Screen space") 02071 if (FindAppliedAttribute(CC_RUNTIME_CLASS(AttrFeather), &pAttr)) 02072 { 02073 // currently, we only generate an offscreen bitmap for GRenderRegions, although we are 02074 // 'rendered' into all RR's. therefore we must quit quietly if pRender is not a GRR. 02075 if (pAttr && !pAttr->IsADefaultAttr() && !pAttr->HasEquivalentDefaultValue(TRUE) && pRender->IS_KIND_OF(GRenderRegion)) 02076 { 02077 // We can't render the feather attribute or a copy of it because the crappy 02078 // thing relies intimately on its connection to the tree to get geometric 02079 // information. 02080 GRenderRegion* pGRR = (GRenderRegion*)pRender; 02081 pFeatherAttr = (AttrFeather*) ((AttrFeather*)pAttr)->SimpleCopy(); 02082 if (pFeatherAttr) 02083 { 02084 mpScaledFeatherSize = pFeatherAttr->Value.GetFeatherSize(); 02085 FIXED16 f16Scale; 02086 matInverse.Decompose(&f16Scale); // Should take aspect into account as well??? 02087 mpScaledFeatherSize = (MILLIPOINT)((double)mpScaledFeatherSize * f16Scale.MakeDouble() + 0.5); 02088 pFeatherAttr->Value.SetFeatherSize(mpScaledFeatherSize); 02089 02090 profileFeather = pFeatherAttr->Value.GetProfile(); 02091 02092 // Don't let the feather render itself, but call it's core functions with 02093 // our special information to get it to create the crucial transparency bitmap fill 02094 pFeatherAttr->Value.CreateFeatherTransp(pGRR, &InkPath, 72000.0/((double)(pkBitmap->GetHorizontalDPI())), &pFeatherTransp, &pFeatherBitmap); 02095 02096 if (pFeatherTransp) 02097 { 02098 TranspFillMappingLinearAttribute* pFeatherTranspMapping = new TranspFillMappingLinearAttribute; 02099 pFeatherTranspMapping->Repeat = 0; 02100 pRender->SetTranspFillMapping(pFeatherTranspMapping, TRUE); 02101 02102 pRender->SetTranspFillGeometry(pFeatherTransp, TRUE); 02103 } 02104 } 02105 } 02106 } 02107 02108 // Simple bitmap fill which fills the whole shape 02109 BitmapFillAttribute *pBitmapAttr = new BitmapFillAttribute; 02110 pBitmapAttr->GetBitmapRef()->SetBitmap(pkBitmap); 02111 02112 if (GetStartColour()) 02113 pBitmapAttr->SetStartColour(GetStartColour()); 02114 02115 if (GetEndColour()) 02116 pBitmapAttr->SetEndColour(GetEndColour()); 02117 02118 // Set fill coords 02119 pBitmapAttr->StartPoint = coords[0]; 02120 pBitmapAttr->EndPoint = coords[1]; 02121 pBitmapAttr->EndPoint2 = coords[2]; 02122 02123 // Set bitmap attribute, and get the render region to throw it away when it's finished 02124 // with (hence the TRUE parameter). 02125 pRender->SetFillGeometry(pBitmapAttr, TRUE); 02126 02127 // Set the mapping to have no repeat, otherwise we get artifacts at the edges when 02128 // anti-aliasing is enabled (see bug 1391). 02129 FillMappingLinearAttribute *pNoRepeatAttr = new FillMappingLinearAttribute; 02130 02131 // Prevent tesselation to get rid of possible edge effects 02132 pNoRepeatAttr->Repeat = 0; 02133 02134 // Set mapping attribute, and get the render region to throw it away when it's finished 02135 // with (hence the TRUE parameter). 02136 pRender->SetFillMapping(pNoRepeatAttr, TRUE); 02137 02138 // Draw the bitmap by rendering a bitmap filled path. 02139 pRender->DrawPath(&InkPath); 02140 } // ------------------------------------------------------ 02141 02142 pRender->RestoreContext(); 02143 if (pTranspAttr) 02144 { 02145 delete pTranspAttr; 02146 pTranspAttr = NULL; 02147 } 02148 02149 if (pFeatherAttr) 02150 { 02151 delete pFeatherAttr; 02152 pFeatherAttr = NULL; 02153 } 02154 02155 // Don't need this because pFeatherTransp is rendered with "Temp=TRUE" so that the RenderRegion will delete it 02156 // if (pFeatherTransp) 02157 // { 02158 // delete pFeatherTransp; 02159 // pFeatherTransp = NULL; 02160 // } 02161 02162 if (pFeatherBitmap != NULL) 02163 { 02164 delete pFeatherBitmap; 02165 pFeatherBitmap = NULL; 02166 } 02167 02168 LPBITMAPINFO lpInfo = NULL; 02169 LPBYTE lpBits = NULL; 02170 pRender->StopCapture(this, FALSE, FALSE, &lpInfo, &lpBits, &CaptureRect); 02171 02172 // We should now have a bitmap containing an upright version of the NodeBitmap 02173 // with transparency and contoning applied as per the attributes in the tree 02174 if (lpInfo && lpBits) 02175 { 02176 *plpInfo = lpInfo; 02177 *plpBits = lpBits; 02178 02179 // Cache the PROCESSED/RENDERED bitmap as Option 2 02180 CBitmapCacheKey inky(this, 72000.0/pkBitmap->GetHorizontalDPI(), 2); 02181 CCachedBitmap cbmp; 02182 cbmp.pbmpBits = lpBits; 02183 cbmp.pbmpInfo = lpInfo; 02184 cbmp.SetCachedRect(CaptureRect); 02185 cbmp.nPriority = CACHEPRIORITY_TEMPBITMAP_HIGH; 02186 if (cbmp.IsValid()) 02187 pBitmapCache->StoreBitmap(inky, cbmp); 02188 } 02189 } 02190 02191 return TRUE; 02192 } 02193 02194 02195 02196 02197 /******************************************************************************************** 02198 02199 > BOOL NodeBitmap::HasBitmapAttrs() 02200 02201 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 02202 Created: 29/07/2005 02203 Inputs: - 02204 Outputs: - 02205 Returns: TRUE if this node has attributes applied which affect the way it renders 02206 FALSE otherwise 02207 Purpose: Test whether we need to render this bitmap before we can return it from 02208 GetDirectBitmap 02209 02210 ********************************************************************************************/ 02211 02212 BOOL NodeBitmap::HasBitmapAttrs() 02213 { 02214 if (GetStartColour() || GetEndColour()) 02215 return TRUE; 02216 02217 NodeAttribute* pAttr; 02218 if (FindAppliedAttribute(CC_RUNTIME_CLASS(AttrTranspFillGeometry), &pAttr)) 02219 { 02220 if (pAttr && !pAttr->IsADefaultAttr() && !pAttr->HasEquivalentDefaultValue(TRUE)) 02221 return TRUE; 02222 } 02223 02224 if (FindAppliedAttribute(CC_RUNTIME_CLASS(AttrFeather), &pAttr)) 02225 { 02226 if (pAttr && !pAttr->IsADefaultAttr() && !pAttr->HasEquivalentDefaultValue(TRUE)) 02227 return TRUE; 02228 } 02229 02230 return FALSE; 02231 } 02232 02233 02234 02235 02236 /******************************************************************************************** 02237 02238 > virtual BOOL NodeBitmap::ReleaseCached(BOOL bAndParents = TRUE, 02239 BOOL bAndChildren = TRUE, 02240 BOOL bSelf = TRUE, 02241 BOOL bAndDerived = TRUE) 02242 02243 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 02244 Created: 30/07/2005 02245 Inputs: bAndParents - TRUE if should release parent objects 02246 bAndChildren - TRUE if should release child objects 02247 bSelf - TRUE if should release own cached data 02248 bAndDerived - TRUE if should release cached data derived from this object 02249 Outputs: - 02250 Returns: TRUE 02251 Purpose: Get rid of cached data held in the tree 02252 02253 ********************************************************************************************/ 02254 02255 BOOL NodeBitmap::ReleaseCached(BOOL bAndParents, BOOL bAndChildren, BOOL bSelf, BOOL bAndDerived) 02256 { 02257 BOOL bRemoveOpaqueBitmapsOnly = IsDragged(); // If we're being dragged, only remove opaque bmps 02258 CBitmapCache* pBitmapCache = Camelot.GetBitmapCache(); 02259 if (pBitmapCache!=NULL && bSelf) 02260 { 02261 CBitmapCacheKey inky(this, 42); 02262 pBitmapCache->RemoveAllOwnedBitmaps(inky, bRemoveOpaqueBitmapsOnly); 02263 } 02264 02265 // If we should release our children's caches as well... 02266 if (bAndChildren) 02267 { 02268 Node* pChild = FindFirstChild(); 02269 while (pChild) 02270 { 02271 if (pChild->IsBounded()) 02272 ((NodeRenderableBounded*)pChild)->ReleaseCached(FALSE, TRUE, TRUE, TRUE); 02273 02274 pChild = pChild->FindNext(); 02275 } 02276 } 02277 02278 // If I can't be cached, neither can my parent... 02279 if (bAndParents && FindParent() && FindParent()->IsBounded()) 02280 ((NodeRenderableBounded*)FindParent())->ReleaseCached(TRUE, FALSE, TRUE, TRUE); 02281 02282 return TRUE; 02283 } 02284 02285 02286 02287 02288 /******************************************************************************************** 02289 02290 > virtual BOOL NodeBitmap::SupportsClipboardFormat(InternalClipboardFormat *Format) const 02291 02292 Author: Jason_Williams (Xara Group Ltd) <camelotdev@xara.com> 02293 Created: 26/4/95 02294 02295 Returns: TRUE = This node supports the given format 02296 FALSE = This node does not support the format (or the format is unknown) 02297 02298 Purpose: Determine if a node supports a given internal data type. This is used 02299 by the clipboard when exporting to other applications in order to 02300 determine if certain data types can be supplied. 02301 02302 e.g. The basic formats include: 02303 Vector - this is ALWAYS assumed to be available (Vector format 02304 includes every Node, e.g. export in Camelot .art format) 02305 02306 Text - As well as paths, some objects can provide text chars 02307 02308 Bitmap - Bitmap fills can render a filled object or supply the 02309 bitmap used for filling with. 02310 02311 See InternalClipboardFormat (kernel\cliptype.h) for more details 02312 02313 Notes: TextChars can be exported as either "vector" or "text" data 02314 02315 SeeAlso: InternalClipboardFormat; Node::SupportsClipboardFormat 02316 02317 ********************************************************************************************/ 02318 02319 BOOL NodeBitmap::SupportsClipboardFormat(InternalClipboardFormat *Format) const 02320 { 02321 #if !defined(EXCLUDE_FROM_RALPH) 02322 // bitmaps can be exported as either "vector" or "bitmap" data 02323 InternalClipboardFormat temp(CLIPTYPE_BITMAP); 02324 return(Format->IsSameFormat(temp)); 02325 // return(Format->IsSameFormat(InternalClipboardFormat(CLIPTYPE_BITMAP))); 02326 #else 02327 return FALSE; 02328 #endif 02329 } 02330 02331 /******************************************************************************************** 02332 02333 > virtual BOOL NodeBitmap::NeedsTransparency() const 02334 02335 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 02336 Created: 5/6/96 02337 Inputs: - 02338 Outputs: - 02339 Returns: TRUE if this node requires transparency mode to render properly. 02340 Purpose: Called 02341 Errors: - 02342 SeeAlso: Node::AttachNode 02343 02344 ********************************************************************************************/ 02345 02346 BOOL NodeBitmap::NeedsTransparency() const 02347 { 02348 NodeBitmap* pNonConst = (NodeBitmap*) this; 02349 02350 // BOOL NeedsTransparency = FALSE; 02351 02352 return(pNonConst->GetBitmap()->IsTransparent()); 02353 02354 /* if (pNonConst->GetBitmap() != NULL) 02355 { 02356 // If the bitmap is 8 bpp or less then check for a transparent colour 02357 if(pNonConst->GetBitmap()->GetBPP() <= 8) 02358 { 02359 INT32 TranspIndex; 02360 02361 // If the bitmap has a transparency index then we'll need to force transparency on 02362 if (pNonConst->GetBitmap()->GetTransparencyIndex(&TranspIndex)) 02363 return TRUE; 02364 } 02365 02366 if(pNonConst->GetBitmap()->GetBPP() == 32) 02367 { 02368 // Mark H - If we`ve got a 32 bit bitmap then we must make sure we render into a 32bit 02369 // render region to get the correct output! 02370 return TRUE; 02371 } 02372 } 02373 02374 return FALSE; 02375 */ 02376 } 02377 02378 /******************************************************************************************** 02379 02380 > BOOL WritePreChildrenWeb(BaseCamelotFilter* pFilter); 02381 BOOL WritePreChildrenNative(BaseCamelotFilter* pFilter); 02382 02383 Author: Andy_Hayward (Xara Group Ltd) <camelotdev@xara.com> 02384 Created: 14/06/96 02385 Inputs: pFilter - file filter to save to 02386 Returns: TRUE if successful, false otherwise 02387 Purpose: saves a NodeBitmap to the filter 02388 02389 ********************************************************************************************/ 02390 02391 BOOL NodeBitmap::WritePreChildrenWeb(BaseCamelotFilter *pFilter) 02392 { 02393 #ifdef DO_EXPORT 02394 ERROR2IF(pFilter==NULL, FALSE, "Parameter pFilter == NULL"); 02395 02396 return CXaraFileNodeBitmap::WritePreChildrenWeb(pFilter, this); 02397 #else 02398 return FALSE; 02399 #endif 02400 } 02401 02402 BOOL NodeBitmap::WritePreChildrenNative(BaseCamelotFilter *pFilter) 02403 { 02404 #ifdef DO_EXPORT 02405 ERROR2IF(pFilter==NULL, FALSE, "Parameter pFilter == NULL"); 02406 02407 return CXaraFileNodeBitmap::WritePreChildrenNative(pFilter, this); 02408 #else 02409 return FALSE; 02410 #endif 02411 } 02412 02413 /******************************************************************************************** 02414 02415 > KernelBitmap *NodeBitmap::EnumerateBitmaps(UINT32 Count) 02416 02417 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 02418 Created: 02/17/95 02419 Inputs: Count - the bitmap to get (see Purpose). 02420 Returns: The KernelBitmap in use by the node, or NULL if no more are used. 02421 Purpose: Find out what bitmaps, if any, are used by this node. 02422 02423 The base class returns NULL always, so you over-ride this in any node classes 02424 that use bitmaps. 02425 02426 This function supports nodes that use more than one bitmap - you call this 02427 function repeatedly and keep incrementing the Count parameter that you pass 02428 in each time by 1. You should stop calling it when it returns NULL, as this 02429 indicates that no more bitmaps are used by this node. 02430 Count should start off as 0 for the first call. Note that this function 02431 can (and often will) return NULL for the first call, as many nodes don't 02432 use bitmaps, obviously. 02433 02434 SeeAlso: KernelBitmap 02435 02436 ********************************************************************************************/ 02437 02438 KernelBitmap *NodeBitmap::EnumerateBitmaps(UINT32 Count) 02439 { 02440 if (Count == 0) return GetBitmap(); 02441 02442 return NULL; 02443 } 02444 02445 02446 /**************************************************************************** 02447 02448 > double NodeBitmap::GetEffectiveBitmapMinDPI(KernelBitmap* pBitmap) 02449 02450 Author: Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com> 02451 Created: 07/08/2006 02452 02453 Inputs: pBitmap - pointer to a KernelBitmap 02454 Returns: 02455 Purpose: 02456 02457 ****************************************************************************/ 02458 02459 double NodeBitmap::GetEffectiveBitmapMinDPI(KernelBitmap* pBitmap) 02460 { 02461 if (GetBitmap() == pBitmap) 02462 { 02463 // Do we have a valid bitmap ? 02464 OILBitmap *OilBM = pBitmap->ActualBitmap; 02465 if (OilBM != NULL) 02466 { 02467 BitmapInfo Info; 02468 OilBM->GetInfo(&Info); 02469 02470 // Get the Width of the Bitmap in Pixels 02471 INT32 PixWidth = Info.PixelWidth; 02472 INT32 PixHeight = Info.PixelHeight; 02473 02474 // Get the Width of the Bitmap in Millipoints 02475 INT32 Width = INT32(Parallel[0].Distance(Parallel[1])); 02476 INT32 Height = INT32(Parallel[1].Distance(Parallel[2])); 02477 02478 // Use doubles so that we can round up as well as down. This improves 02479 // the dpi calculated. 02480 double HDpi = 0; 02481 double VDpi = 0; 02482 02483 if (Width > 0) 02484 HDpi = ((double)PixWidth * 72000.0)/(double)Width; 02485 02486 if (Height > 0) 02487 VDpi = ((double)PixHeight * 72000.0)/(double)Height; 02488 02489 // Use the smaller of the two dpi values 02490 if (HDpi < VDpi) 02491 return(HDpi); 02492 else 02493 return(VDpi); 02494 } 02495 } 02496 02497 return(1e9); 02498 } 02499 02500 02501 02502 /**************************************************************************** 02503 02504 > BOOL NodeBitmap::ReplaceBitmap(KernelBitmap* pOrigBitmap, KernelBitmap* pNewBitmap) 02505 02506 Author: Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com> 02507 Created: 07/08/2006 02508 02509 Inputs: pOrigBitmap - pointer to a KernelBitmap 02510 pNewBitmap - pointer to a KernelBitmap 02511 Returns: TRUE if ok, FALSE if bother 02512 Purpose: 02513 02514 ****************************************************************************/ 02515 02516 BOOL NodeBitmap::ReplaceBitmap(KernelBitmap* pOrigBitmap, KernelBitmap* pNewBitmap) 02517 { 02518 if (GetBitmap() == pOrigBitmap) 02519 { 02520 BitmapRef.Attach(pNewBitmap); 02521 return(TRUE); 02522 } 02523 02524 return FALSE; 02525 } 02526 02527 02528 /******************************************************************************************** 02529 > BOOL NodeBitmap::IsABitmap() const 02530 02531 Author: Justin_Flude (Xara Group Ltd) <camelotdev@xara.com> 02532 Created: 02/17/95 02533 Returns: TRUE 02534 SeeAlso: Node::IsABitmap 02535 ********************************************************************************************/ 02536 02537 BOOL NodeBitmap::IsABitmap() const 02538 { 02539 return TRUE; 02540 } 02541 02542 02543 02544 /******************************************************************************************** 02545 02546 > BOOL NodeBitmap::OnClick(DocCoord PointerPos, 02547 ClickType Click, 02548 ClickModifiers ClickMods, 02549 Spread* pSpread) 02550 02551 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 02552 Created: 21/01/2004 02553 Inputs: PointerPos - The Location of the mouse pointer at the time of the click 02554 Click - The type of click received (single, double, drag etc) 02555 ClickMods - The modifiers to the click (eg shift, control etc ) 02556 Returns: BOOL - TRUE if the node claims the click as its own and FALSE if it is 02557 not interested in the click 02558 Purpose: Allows the Node to respond to clicks by selecting its blobs or starting 02559 drags etc. 02560 This functions should be overridden in the all the NodeRenderableInk classes 02561 so that this version never gets called. Eg the NodePath class might claim 02562 the click if it happened over one of its unselected blobs. 02563 02564 ********************************************************************************************/ 02565 02566 BOOL NodeBitmap::OnClick(DocCoord PointerPos, 02567 ClickType Click, 02568 ClickModifiers ClickMods, 02569 Spread* pSpread) 02570 { 02571 PORTNOTE("other","OnClick - Remove XPE edit") 02572 #ifndef EXCLUDE_FROM_XARALX 02573 if (Click == CLICKTYPE_DOUBLE) 02574 { 02575 // We're going to start up a new dialog so we want to clear out any click 02576 // processing logic that may be in process... 02577 DocView* pDocView = DocView::GetCurrent(); 02578 if (pDocView) 02579 pDocView->ClearClickState(); 02580 02581 // Invoke and XPE Edit operation 02582 OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_XPE_EDIT); 02583 if (pOpDesc) 02584 { 02585 pOpDesc->Invoke(); 02586 return TRUE; 02587 } 02588 } 02589 #endif 02590 // did not use the click 02591 return FALSE; 02592 } 02593 02594 02595 02596 02597 /******************************************************************************************** 02598 02599 > virtual void NodeBitmap::SetAspectRatio(double dExWidth, double dExHeight, BOOL bPathAndFill) 02600 02601 Author: Phil_Martin (Xara Group Ltd) <camelotdev@xara.com> 02602 Created: 27/01/2004 02603 Inputs: dExWidth - Sample width (numerator) 02604 dExHeight - Sample height (denominator) 02605 bPathAndFill - Apply this logic to both the path and the bitmap fill??? 02606 Returns: - 02607 Purpose: To reset the stored path and Parallelogram to retain their shape and scale 02608 but to take on a new aspect ratio. 02609 02610 ********************************************************************************************/ 02611 02612 void NodeBitmap::SetAspectRatio(double dExWidth, double dExHeight, BOOL bPathAndFill) 02613 { 02614 /* 02615 Gavin says: 02616 If the parallelogram is defined by the three points P0, P1, P2 02617 where P1-P0 is the x axis of the bitmap and P2-P0 is the y axis 02618 and the bitmap had old size W,H and new size NW, NH 02619 then the new parallelogram NP0,NP1,NP2 will be 02620 NP0 = P0 02621 NP1x = P0x+(P1x-P0x)*NW/W 02622 NP1y = P0y+(P1y-P0y)*NW/W 02623 NP2x = P0x+(P2x-P0x)*NH/H 02624 NP2y = P0y+(P2y-P0y)*NH/H 02625 The fourth points of the parallelogram can be found from the other three: 02626 P3 = P2+P1-P0 02627 02628 If you dont want the centre to move then: 02629 C = (P1+P2)*0.5 02630 Dxx = (P1x-P0x)*NW/W 02631 Dxy = (P1y-P0y)*NW/W 02632 Dyx = (P2x-P0x)*NH/H 02633 Dyy = (P2y-P0y)*NH/H 02634 NP0x = (P1x+P2x-Dxx -Dyx)*0.5 02635 NP0y = (P1y+P2y-Dxy -Dyy)*0.5 02636 NP1x = NP0x+Dxx 02637 NP1y = NP0y+Dxy 02638 NP2x = NP0x+Dyx 02639 NP2y = NP0y+Dyy 02640 NP3x = NP0x+Dxx+Dyx 02641 NP3y = NP0y+Dxy+Dyy 02642 02643 Phil says: 02644 Parallelogram points are stored in this order: 02645 3 <- 2 02646 v ^ 02647 0 -> 1 02648 */ 02649 DocCoord p0 = Parallel[0]; 02650 DocCoord p1 = Parallel[1]; 02651 DocCoord p2 = Parallel[3]; 02652 02653 double w = double(GetBitmap()->GetWidth()); 02654 double h = double(GetBitmap()->GetHeight()); 02655 02656 DocCoord C = DocCoord::OneHalf( p1, p2 ); 02657 INT32 dxx = INT32(( p1.x - p0.x ) * dExWidth / w); 02658 INT32 dxy = INT32(( p1.y - p0.y ) * dExWidth / w); 02659 INT32 dyx = INT32(( p2.x - p0.x ) * dExHeight / h); 02660 INT32 dyy = INT32(( p2.y - p0.y ) * dExHeight / h); 02661 02662 INT32 ox = INT32(( p1.x + p2.x - dxx - dyx ) * 0.5); 02663 INT32 oy = INT32(( p1.y + p2.y - dxy - dyy ) * 0.5); 02664 Parallel[0].x = ox; 02665 Parallel[0].y = oy; 02666 Parallel[1].x = ox+dxx; 02667 Parallel[1].y = oy+dxy; 02668 Parallel[3].x = ox+dyx; 02669 Parallel[3].y = oy+dyy; 02670 Parallel[2].x = ox+dxx+dyx; 02671 Parallel[2].y = oy+dxy+dyy; 02672 02673 UpdateShape(); 02674 InvalidateBoundingRect(); 02675 } 02676 02677 02678 02679 02680 #if !defined(EXCLUDE_FROM_RALPH) 02681 //----------------------------------------------------------------------------------------------- 02682 02683 // OpCreateNodeBitmap - the operation that is used to create a new NodeBitmap 02684 02685 /******************************************************************************************** 02686 02687 > BOOL OpCreateNodeBitmap::Init() 02688 02689 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 02690 Created: 31/1/95 02691 Inputs: - 02692 Outputs: - 02693 Returns: TRUE if the operation could be successfully initialised 02694 FALSE if no more memory could be allocated 02695 02696 Purpose: OpCreateNodeBitmap initialiser method 02697 Errors: ERROR will be called if there was insufficient memory to allocate the 02698 operation. 02699 SeeAlso: - 02700 02701 ********************************************************************************************/ 02702 02703 BOOL OpCreateNodeBitmap::Init() 02704 { 02705 return (RegisterOpDescriptor( 02706 0, 02707 0, 02708 CC_RUNTIME_CLASS(OpCreateNodeBitmap), 02709 OPTOKEN_CREATENODEBITMAP, 02710 OpCreateNodeBitmap::GetState, 02711 0, /* help ID */ 02712 0, 02713 0 /* bitmap ID */)); 02714 } 02715 02716 /******************************************************************************************** 02717 02718 > OpState OpCreateNodeBitmap::GetState(String_256*, OpDescriptor*) 02719 02720 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 02721 Created: 31/1/95 02722 Inputs: - 02723 Outputs: - 02724 Returns: The state of the OpCreateNodeBitmap operation 02725 Purpose: For finding the OpCreateNodeBitmap's state. 02726 Errors: - 02727 SeeAlso: - 02728 02729 ********************************************************************************************/ 02730 02731 OpState OpCreateNodeBitmap::GetState(String_256* UIDescription, OpDescriptor*) 02732 { 02733 OpState OpSt; 02734 02735 // If there are no open documents, you can't create a node bitmap 02736 OpSt.Greyed = (Document::GetSelected() == NULL); 02737 02738 return(OpSt); 02739 } 02740 02741 /******************************************************************************************** 02742 02743 > void OpCreateNodeBitmap::DoWithParam(OpDescriptor* OpDesc, OpParam* pOpParam) 02744 02745 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 02746 Created: 31/1/95 02747 Inputs: - 02748 Outputs: - 02749 Returns: - 02750 Purpose: Creates a new bitmap object 02751 Errors: - 02752 SeeAlso: - 02753 02754 ********************************************************************************************/ 02755 02756 void OpCreateNodeBitmap::DoWithParam(OpDescriptor* OpDesc, OpParam* pOpParam) 02757 { 02758 BOOL ok = FALSE; 02759 02760 ERROR3IF(pOpParam == NULL, "NULL OpParam passed to OpCreateNodeBitmap"); 02761 02762 KernelBitmap* KernelBmp = (KernelBitmap*)(void *)pOpParam->Param1; 02763 PageDropInfo* pDropInfo = (PageDropInfo*)(void *)pOpParam->Param2; 02764 02765 DocView* pDocView = DocView::GetCurrent(); 02766 Spread* pSpread = pDropInfo->pSpread; 02767 DocCoord DropPos = pDropInfo->DropPos; 02768 02769 02770 NodeBitmap* pNodeBitmap = new NodeBitmap(); 02771 if ((pNodeBitmap == NULL) || (!pNodeBitmap->SetUpPath(12,12))) 02772 goto EndOp; 02773 02774 // Attach the Dropped Bitmap to our Node 02775 pNodeBitmap->GetBitmapRef()->Attach(KernelBmp); 02776 if (pNodeBitmap->GetBitmap() != KernelBmp) 02777 { 02778 // It didn't use the bitmap we gave it, so we can delete it 02779 delete KernelBmp; 02780 } 02781 02782 { 02783 DocRect BoundsRect; 02784 BitmapInfo Info; 02785 02786 // Import worked - try to add the bitmap object into the tree. 02787 // First, set the rectangle to the right size for the bitmap... 02788 pNodeBitmap->GetBitmap()->ActualBitmap->GetInfo(&Info); 02789 02790 // When pasting from XPE we don't have a docview, so fabricate 96dpi measurement (NB this gives 02791 // no remainder, just expressed as division to make derivation clear) 02792 FIXED16 pixHorz = NULL != pDocView ? pDocView->GetPixelWidth() : FIXED16( 72000 / 96 ); 02793 FIXED16 pixVert = NULL != pDocView ? pDocView->GetPixelHeight() : FIXED16( 72000 / 96 ); 02794 const INT32 HPixelSize = ( pixHorz + 0.5 ).MakeLong(); // Size of output pixel in millipoints 02795 const INT32 VPixelSize = ( pixVert + 0.5 ).MakeLong(); // Size of output pixel in millipoints 02796 02797 // Make sure that this is snapped to a pixel grid 02798 BoundsRect.lo.x = DropPos.x - ( Info.RecommendedWidth / 2 ); 02799 BoundsRect.lo.y = DropPos.y - ( Info.RecommendedHeight / 2 ); 02800 BoundsRect.lo.x = GridLock(BoundsRect.lo.x, HPixelSize); 02801 BoundsRect.lo.y = GridLock(BoundsRect.lo.y, VPixelSize); 02802 // And now add in the rest of the bounds 02803 BoundsRect.hi.x = BoundsRect.lo.x + Info.RecommendedWidth; 02804 BoundsRect.hi.y = BoundsRect.lo.y + Info.RecommendedHeight; 02805 BoundsRect.hi.x = GridLock(BoundsRect.hi.x, HPixelSize); 02806 BoundsRect.hi.y = GridLock(BoundsRect.hi.y, VPixelSize); 02807 02808 // And set this in our bitmap node 02809 pNodeBitmap->CreateShape(BoundsRect); 02810 02811 // Set the default attrs 02812 // This Must be done before the NodeBitmap is inserted into the tree 02813 if (!pNodeBitmap->ApplyDefaultBitmapAttrs(this)) 02814 goto EndOp; 02815 02816 // Insert the node 02817 if (!DoInsertNewNode(pNodeBitmap, pSpread, TRUE)) 02818 { 02819 // It didn't work - delete the sub-tree we just created. 02820 delete pNodeBitmap; 02821 goto EndOp; 02822 } 02823 02824 // Get the spread's bounding rectangle and convert it to spread coords. 02825 DocRect SpreadRect = pSpread->GetPasteboardRect(); 02826 pSpread->DocCoordToSpreadCoord(&SpreadRect); 02827 02828 // If bounding box off the spread - limit it to the edge of the spread: 02829 02830 // (a) Horizontal adjustment 02831 DocCoord Offset(0,0); 02832 if (BoundsRect.lo.x < SpreadRect.lo.x) 02833 Offset.x += (SpreadRect.lo.x - BoundsRect.lo.x); 02834 else if (BoundsRect.hi.x > SpreadRect.hi.x) 02835 Offset.x -= (BoundsRect.hi.x - SpreadRect.hi.x); 02836 02837 // (b) Vertical adjustment (most useful to clip hi co-ords) 02838 if (BoundsRect.hi.y > SpreadRect.hi.y) 02839 Offset.y -= (BoundsRect.hi.y - SpreadRect.hi.y); 02840 else 02841 if (BoundsRect.lo.y < SpreadRect.lo.y) 02842 Offset.y += (SpreadRect.lo.y - BoundsRect.lo.y); 02843 02844 // Actually do the translation if needed 02845 if( 0 != Offset.x || 02846 0 != Offset.y ) 02847 { 02848 Offset.x = GridLock(Offset.x, HPixelSize); 02849 Offset.y = GridLock(Offset.y, VPixelSize); 02850 02851 // Build the matrix and transform the bitmap to the correct place 02852 Trans2DMatrix Xlate(Offset.x, Offset.y); 02853 pNodeBitmap->Transform(Xlate); 02854 } 02855 02856 // We can't do this without a docview 02857 if( NULL != pDocView ) 02858 { 02859 // Does the bitmap fit with our current view? 02860 DocRect docrectBounds = pNodeBitmap->GetBoundingRect(); 02861 DocRect docrectView = pDocView->GetDocViewRect( pSpread ); 02862 pSpread->DocCoordToSpreadCoord( &docrectView ); 02863 if( ( docrectBounds.lo.x < docrectView.lo.x || 02864 docrectBounds.lo.y < docrectView.lo.y || 02865 docrectBounds.hi.x > docrectView.hi.x || 02866 docrectBounds.hi.y > docrectView.hi.y ) && 02867 BaseBitmapFilter::GetZoomOnImport() ) 02868 { 02869 // Calculate bounding rect of view plus new photo and then make sure that edges in 02870 // in both axes grow by same amount. We make use of the fact that zoom code only allows 02871 // zooming in both axes by the same amount, so we don't need to make sure that growth in 02872 // both axes is by the same percentage. 02873 docrectBounds = docrectBounds.Union( docrectView ); 02874 if( docrectView.lo.x - docrectBounds.lo.x > docrectBounds.hi.x - docrectView.hi.x ) 02875 docrectBounds.hi.x = docrectView.hi.x + docrectView.lo.x - docrectBounds.lo.x; 02876 else 02877 docrectBounds.lo.x = docrectView.lo.x - docrectBounds.hi.x + docrectView.hi.x; 02878 if( docrectView.lo.y - docrectBounds.lo.y > docrectBounds.hi.y - docrectView.hi.y ) 02879 docrectBounds.hi.y = docrectView.hi.y + docrectView.lo.y - docrectBounds.lo.y; 02880 else 02881 docrectBounds.lo.y = docrectView.lo.y - docrectBounds.hi.y + docrectView.hi.y; 02882 02883 // No, zoom out so the all the bitmap can be seen 02884 OpZoomFitRectDescriptor* pOpDesc = (OpZoomFitRectDescriptor*)OpDescriptor::FindOpDescriptor( OPTOKEN_ZOOMRECT ); 02885 if( NULL != pOpDesc ) 02886 { 02887 pOpDesc->SetZoomRect( docrectBounds ); 02888 pOpDesc->Invoke(); 02889 } 02890 02891 // Keep user informed about the zoom operation 02892 if( !BaseBitmapFilter::GetWarnedZoomOnImport() ) 02893 { 02894 ErrorInfo Info; 02895 memset( &Info, 0, sizeof(Info) ); 02896 Info.ErrorMsg = _R(IDS_ZOOM_ON_IMAGE_IMPORT); 02897 Info.Button[0] = _R(IDS_OK); 02898 Info.Button[1] = _R(IDS_DONT_SHOW_AGAIN); 02899 Info.OK = 1; 02900 if( _R(IDS_DONT_SHOW_AGAIN) == UINT32(InformMessage( &Info )) ) 02901 BaseBitmapFilter::SetWarnedZoomOnImport( TRUE ); 02902 } 02903 } 02904 } 02905 } 02906 02907 ok = TRUE; 02908 02909 EndOp: 02910 if (!ok) 02911 FailAndExecute(); 02912 02913 End(); 02914 } 02915 02916 void OpCreateNodeBitmap::GetOpName(String_256* OpName) 02917 { 02918 OpName->Load(_R(IDS_K_NODEBMP_CREATEBITMAP)); 02919 } 02920 02921 #endif 02922 02924 // 02925 // ChangeBitmapPtrAction class // 02926 // 02928 02929 /******************************************************************************************** 02930 02931 > ChangeBitmapPtrAction::ChangeBitmapPtrAction() 02932 02933 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 02934 Created: 27/6/95 02935 Inputs: - 02936 Outputs: - 02937 Returns: - 02938 Purpose: Constructor for the action to undo fill modification 02939 Errors: - 02940 SeeAlso: - 02941 02942 ********************************************************************************************/ 02943 02944 ChangeBitmapPtrAction::ChangeBitmapPtrAction() 02945 { 02946 pChangedBmpNode = NULL; 02947 } 02948 02949 /******************************************************************************************** 02950 02951 > ActionCode ChangeBitmapPtrAction::Init( Operation* pOp, 02952 ActionList* pActionList, 02953 Action** NewAction) 02954 02955 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 02956 Created: 27/6/95 02957 Inputs: pOp is the pointer to the operation to which this action belongs 02958 pActionList is the action list to which this action should be added 02959 Outputs: NewAction is a pointer to a pointer to an action, allowing the function to return 02960 a pointer to the created action 02961 Returns: ActionCode, one of AC_OK, AC_NO_RECORD or AC_FAIL 02962 Purpose: This is the function which creates an instance of this action. If there is no room 02963 in the undo buffer (which is determined by the base class Init function called within) 02964 the function will either return AC_NO_RECORD which means the operation can continue, 02965 but no undo information needs to be stored, or AC_OK which means the operation should 02966 continue AND record undo information. If the function returns AC_FAIL, there was not 02967 enough memory to record the undo information, and the user has decided not to continue 02968 with the operation. 02969 Errors: - 02970 SeeAlso: Action::Init() 02971 02972 ********************************************************************************************/ 02973 02974 ActionCode ChangeBitmapPtrAction::Init( Operation* pOp, 02975 ActionList* pActionList, 02976 Action** NewAction) 02977 { 02978 UINT32 ActSize = sizeof(ChangeBitmapPtrAction); 02979 ActionCode Ac = Action::Init( pOp, pActionList, ActSize, CC_RUNTIME_CLASS(ChangeBitmapPtrAction), NewAction); 02980 02981 TRACEUSER( "Will", _T("Creating ChangeBitmapPtrAction") ); 02982 02983 return Ac; 02984 } 02985 02986 /******************************************************************************************** 02987 02988 > void ChangeBitmapPtrAction::StoreChanges(NodeBitmap* pBmpNode) 02989 02990 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 02991 Created: 27/6/95 02992 Inputs: pBmpNode, is the NodeBitmap that is being changed. 02993 Outputs: - 02994 Returns: - 02995 Purpose: This function initialises the array pointers in this action. Note that the 02996 variable NumElements is initialised in the Init function 02997 Errors: - 02998 SeeAlso: - 02999 03000 ********************************************************************************************/ 03001 03002 void ChangeBitmapPtrAction::StoreChanges(NodeBitmap* pBmpNode) 03003 { 03004 ERROR3IF(pBmpNode == NULL, "NodeBitmap is NULL in ChangeBitmapPtrAction::StoreChanges()"); 03005 if (pBmpNode == NULL) 03006 return; 03007 03008 pChangedBmpNode = pBmpNode; 03009 BitmapRef.Attach(pBmpNode->GetBitmap(), pOperation->GetWorkingDoc()); 03010 BitmapRef.RemoveFromTree(); 03011 } 03012 03013 /******************************************************************************************** 03014 03015 > ActionCode ChangeBitmapPtrAction::Execute() 03016 03017 Author: Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> 03018 Created: 27/6/95 03019 Inputs: - 03020 Outputs: - 03021 Returns: Action code, one of AC_OK, AC_NORECORD or AC_FAIL. 03022 Purpose: This is the virtual function that is called when the action is executed 03023 by the Undo/Redo system. This is the function that actually undoes the 03024 ChangeBitmapPtr action by changing the attribute values, and 03025 records redo information from the current values. 03026 Errors: - 03027 SeeAlso: - 03028 03029 ********************************************************************************************/ 03030 03031 ActionCode ChangeBitmapPtrAction::Execute() 03032 { 03033 ChangeBitmapPtrAction* ModAction; 03034 03035 ActionCode Act; 03036 Act = ChangeBitmapPtrAction::Init(pOperation, pOppositeActLst, (Action**)(&ModAction)); 03037 if (Act == AC_FAIL) 03038 return AC_FAIL; 03039 03040 // Store away the current bitmap attached to the node 03041 ModAction->StoreChanges(pChangedBmpNode); 03042 03043 // Now restore the old one 03044 pChangedBmpNode->GetBitmapRef()->Attach(BitmapRef.GetBitmap(), pOperation->GetWorkingDoc()); 03045 03046 ((UndoableOperation*)pOperation)-> 03047 DoInvalidateNodeRegion((NodeRenderableInk*)pChangedBmpNode, TRUE); 03048 03049 return Act; 03050 }