00001 // $Id: bfxopun.cpp 1282 2006-06-09 09:46:49Z 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 00100 #include "camtypes.h" 00101 00102 // temp bodge, must be here to avoid Rect problems 00103 #include "makebmp.h" // MakeBitmapFilter; 00104 00105 #include "bfxopun.h" // useful Bfx plug-in related undoable operations 00106 #include "bfxop.h" // useful Bfx plug-in related operations 00107 //#include "plugres.h" // _R(IDS_PLUGIN_FAMILY) 00108 00109 #include "plugmngr.h" // main plug-in manager 00110 #include "bfxitem.h" // useful Bfx plug-in related items 00111 //#include "app.h" // GetApplication() - in camtypes.h [AUTOMATICALLY REMOVED] 00112 00113 //#include "bitmap.h" // KernelBitmap - in camtypes.h [AUTOMATICALLY REMOVED] 00114 00115 //#include "simon.h" // _R(IDS_NO_DOC) _R(IDS_NO_OBJECTS_SELECTED) 00116 //#include "nodebmp.h" // NodeBitmap 00117 //#include "fillattr.h" // AttrFillGeometry 00118 00119 // Place any IMPLEMENT type statements here 00120 CC_IMPLEMENT_DYNCREATE(BfxPlugInUndoOp, PlugInUndoOp); 00121 00122 // We want better memory tracking 00123 #define new CAM_DEBUG_NEW 00124 00125 /******************************************************************************************** 00126 00127 > BfxPlugInUndoOp::BfxPlugInUndoOp() 00128 00129 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00130 Created: 6/3/97 00131 Inputs: 00132 Outputs: 00133 Returns: 00134 Purpose: Constructor for BfxPlugInUndoOp operation. It is undoable. 00135 It is derived off PlugInUndoOp which is derived off 00136 SelOperation as we are working off the selection. 00137 Errors: None 00138 00139 ********************************************************************************************/ 00140 00141 BfxPlugInUndoOp::BfxPlugInUndoOp() 00142 { 00143 } 00144 00145 /******************************************************************************************** 00146 00147 > static BOOL BfxPlugInUndoOp::Init() 00148 00149 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00150 Created: 6/3/97 00151 Returns: TRUE if the Op was started ok 00152 Purpose: Creates all the opDescriptors that call this operation. 00153 00154 ********************************************************************************************/ 00155 00156 BOOL BfxPlugInUndoOp::Init() 00157 { 00158 BOOL ok = TRUE; 00159 // Set up some standard operations 00160 //ok = ok && RegisterOpToken(OPTOKEN_Bfx_UNDO_PLUGINS, _R(IDS_Bfx_PLUGINS), 00161 // CC_RUNTIME_CLASS(BfxPlugInUndoOp), BfxPlugInUndoOp::GetState); 00162 //ok = ok && RegisterOpToken(OPTOKEN_Bfx_UNDO_APPLYLAST, _R(IDS_Bfx_APPLYLAST), 00163 // CC_RUNTIME_CLASS(BfxPlugInUndoOp), BfxPlugInUndoOp::GetState); 00164 00165 return ok; 00166 } 00167 00168 /******************************************************************************************** 00169 00170 > static BOOL BfxPlugInUndoOp::CheckBitmapWithPlugIn(const String_256& OpName, 00171 KernelBitmap * pBitmap, 00172 BOOL IncludeUniqueName = TRUE, 00173 BOOL IncludeUndoAbleSig = FALSE) 00174 00175 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00176 Created: 6/3/97 00177 Inputs: OpName - the name of the OpToken being requested. 00178 pBitmap - the bitmap being checked. 00179 IncludeUniqueName - Set to True (Default) if want the 00180 unique name of the plug-in added to the OpToken 00181 IncludeUndoAbleSig - Set to True is want the unique undoable 00182 sig added to the OpToken. (Default = FALSE.) 00183 Returns: True if the item is ok with the plug-in, False otherwise 00184 Purpose: To ask the plug-in which matches the OpName whether the 00185 bitmap is ok. 00186 Assumes only working on Bfx plug-ins. Not that this should 00187 make much difference at present. 00188 SeeAlso: PLugInOp::CheckBitmapWithPlugIn; 00189 00190 ********************************************************************************************/ 00191 00192 BOOL BfxPlugInUndoOp::CheckBitmapWithPlugIn(const String_256& OpName, KernelBitmap * pBitmap, 00193 BOOL IncludeUniqueName, BOOL IncludeUndoAbleSig) 00194 { 00195 // If no bitmap then always return False 00196 if (pBitmap == NULL) 00197 return FALSE; 00198 00199 // Search the plug-ins list for the specified plug-in and check 00200 // that this colour depth is ok with it 00201 INT32 ColourDepth = pBitmap->GetBPP(); 00202 BOOL GreyScale = pBitmap->IsGreyscale(); 00203 PlugInManager* pManager = GetApplication()->GetPlugInManager(); 00204 if (pManager) 00205 { 00206 PlugInItem * pPlugIn = pManager->GetFirstPlugIn(); 00207 String_32 OpToken; 00208 // Add the unique undo signature 00209 String_32 UndoSig(TEXT(PLUGIN_UNDO_SIG)); 00210 while (pPlugIn) 00211 { 00212 // If we are to include the unique name in the test then do so 00213 if (IncludeUniqueName) 00214 OpToken = pPlugIn->GetUniqueID(); 00215 else 00216 OpToken.Empty(); 00217 if (IncludeUndoAbleSig) 00218 OpToken += UndoSig; 00219 OpToken += pPlugIn->GetPlugInName(); 00220 if (OpName == OpToken) 00221 { 00222 // Ask the plug-in item whether it likes this colour depth 00223 // Returns True if likes it, False otherwise, so we must negate this to 00224 // set the greyed state. 00225 return pPlugIn->IsBitmapModeOk(ColourDepth, GreyScale); 00226 } 00227 00228 pPlugIn = pManager->GetNextPlugIn(pPlugIn); 00229 } 00230 } 00231 00232 // Cannot find plug-in so return False 00233 return FALSE; 00234 } 00235 00236 /******************************************************************************************** 00237 00238 > OpState BfxPlugInUndoOp::GetState(String_256* pUIDescription, OpDescriptor* pOpDesc) 00239 00240 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00241 Created: 6/3/97 00242 Inputs: pOpDesc - the OpDescriptor for the operation 00243 Outputs: pUIDescription - if the Operation is enabled Then return the name of the operation to 00244 be undone Else return the reason why it is disabled 00245 Returns: OpState the state of the operation 00246 Purpose: To provide greying and ticking functionality for the 00247 operation. 00248 Errors: - 00249 SeeAlso: OpConvertToBitmap::GetState; 00250 00251 ********************************************************************************************/ 00252 00253 OpState BfxPlugInUndoOp::GetState(String_256* pUIDescription, OpDescriptor* pOpDesc) 00254 { 00255 OpState OpSt; 00256 String_256 DisableReason; 00257 00258 // Ensure that a document exists 00259 if (Document::GetSelected() == NULL) 00260 { 00261 // There is no selected document 00262 OpSt.Greyed = TRUE; 00263 00264 // Load reason why operation is disabled 00265 DisableReason = String_256(_R(IDS_NO_DOC)); 00266 if (pUIDescription) 00267 *pUIDescription = DisableReason; 00268 return OpSt; 00269 } 00270 00271 // See if there is a bitmap in the current selection 00272 KernelBitmap *pBitmap = NULL; 00273 BOOL FoundBitmap = FALSE; 00274 00275 SelRange *pSelRange = GetApplication()->FindSelection(); 00276 if (pSelRange) 00277 { 00278 // Look for bitmap nodes and bitmap fills 00279 AttrFillGeometry* pFillAttr; 00280 FoundBitmap = pSelRange->FindBitmap(&pBitmap, NULL, NULL, &pFillAttr); 00281 } 00282 00283 if (!FoundBitmap) 00284 { 00285 OpSt.Greyed = TRUE; 00286 // Load reason why operation is disabled 00287 DisableReason = String_256(_R(IDS_NO_OBJECTS_SELECTED)); 00288 if (pUIDescription) 00289 *pUIDescription = DisableReason; 00290 } 00291 else 00292 { 00293 if (pBitmap) 00294 { 00295 // We are always available at present if there is a bitmap 00296 OpSt.Greyed = FALSE; 00297 00298 /* // If we have a valid bitmap then checks that it is of the correct type 00299 INT32 ColourDepth = pBitmap->GetBPP(); 00300 00301 // Only allow bitmaps of 24bpp or of 8bpp greyscale 00302 if (ColourDepth == 24 || (ColourDepth == 8 && pBitmap->IsGreyscale())) 00303 { 00304 // Check the bitmap depth with the plug-in itself 00305 // Returns True if likes it, False otherwise, so we must negate this to 00306 // set the greyed state. 00307 OpSt.Greyed = !CheckBitmapWithPlugIn(pOpDesc->Token, pBitmap, TRUE, TRUE); 00308 } 00309 else 00310 OpSt.Greyed = TRUE; 00311 */ 00312 } 00313 } 00314 00315 return OpSt; 00316 } 00317 00318 /******************************************************************************************** 00319 00320 > void BfxPlugInUndoOp::Do(OpDescriptor*) 00321 00322 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00323 Created: 6/3/97 00324 Inputs: pOpDesc the OpDescriptor of the item to invoke 00325 Outputs: None 00326 Returns: None 00327 Purpose: Invokes the plug-in specified by the OpDescriptor. 00328 Errors: if no OpDescriptor is supplied 00329 SeeAlso: OpConvertToBitmap::Do; 00330 00331 ********************************************************************************************/ 00332 00333 void BfxPlugInUndoOp::Do(OpDescriptor* pOpDesc) 00334 { 00335 // Store away a copy of the OpDescriptor for later use 00336 m_pOpDesc = pOpDesc; 00337 00338 // Search the plug-ins list for the specified plug-in and invoke it 00339 PlugInManager* pManager = GetApplication()->GetPlugInManager(); 00340 if (pManager == NULL) 00341 { 00342 ERROR3("Called BfxPlugInUndoOp with no PlugInManager"); 00343 End(); 00344 return; 00345 } 00346 00347 SelRange *pSelRange = GetApplication()->FindSelection(); 00348 if (pSelRange == NULL) 00349 { 00350 ERROR3("Called BfxPlugInUndoOp with no selection range!"); 00351 End(); 00352 return; 00353 } 00354 00355 KernelBitmap * pBitmap = NULL; 00356 KernelBitmapRef * pFoundBitmapRef = NULL; 00357 NodeBitmap * pFoundNode = NULL; 00358 AttrFillGeometry * pFoundFillAttribute = NULL; 00359 BOOL FoundBitmap = pSelRange->FindBitmap(&pBitmap, &pFoundBitmapRef, &pFoundNode, &pFoundFillAttribute); 00360 if (!FoundBitmap || pBitmap == NULL || pFoundBitmapRef == NULL) 00361 { 00362 ERROR3("Called BfxPlugInUndoOp with no selected bitmap in the range!"); 00363 End(); 00364 return; 00365 } 00366 00367 // We need to invalidate the region 00368 Range Sel(*pSelRange); 00369 if (!DoInvalidateNodesRegions(Sel, TRUE)) 00370 { 00371 End(); 00372 return; 00373 } 00374 00375 PlugInItem * pPlugIn = pManager->GetFirstPlugIn(); 00376 PlugInItem * pPlugInToApply = NULL; 00377 BOOL Found = FALSE; 00378 String_32 OpToken; 00379 // Add the unique undo signature 00380 String_32 UndoSig(TEXT(PLUGIN_UNDO_SIG)); 00381 while (pPlugIn && !Found) 00382 { 00383 OpToken = pPlugIn->GetUniqueID(); 00384 OpToken += UndoSig; 00385 OpToken += pPlugIn->GetPlugInName(); 00386 if (pOpDesc->Token == OpToken) 00387 { 00388 // Note the plug-in for later use 00389 pPlugInToApply = pPlugIn; 00390 Found = TRUE; 00391 break; 00392 } 00393 00394 pPlugIn = pManager->GetNextPlugIn(pPlugIn); 00395 } 00396 00397 if (!DoStartSelOp(FALSE,FALSE)) // Try to record the selection state , don't render the blobs though 00398 { 00399 FailAndExecute(); 00400 End(); 00401 return; 00402 } 00403 00404 // We have searched high and low for the plug-in to apply. 00405 // We should have found it by now and so can get on to actually using it 00406 Document * pDocument = Document::GetSelected(); 00407 // If we haven't found one or there is no selected document then get out now 00408 if (pPlugInToApply == NULL || pDocument == NULL) 00409 { 00410 FailAndExecute(); 00411 End(); 00412 return; 00413 } 00414 00415 // We have found the desired plug-in so use it to do its stuff 00416 KernelBitmap* pBitmapCreated = NULL; 00417 00418 BOOL AppliedOk = TRUE; 00419 AppliedOk = pPlugInToApply->Apply(pBitmap, pDocument, &pBitmapCreated); 00420 00421 // the brightness and resize plugins are causing access violations when we simply press ok 00422 // within their dialog boxes. This is caused through pBitmapCreated having been deleted. 00423 // i'm not exactly sure where the problem is occuring, but the following code fixes the problem. 00424 // the following code also guards against this sort of thing in general .... 00425 00426 // lets just check the actual bitmap that has been returned. If this is NULL, or 0xdddddddd 00427 // then we cannot allow the op to continue .... 00428 00429 if (AppliedOk) 00430 { // verify that please .... 00431 if (!pBitmapCreated) 00432 { 00433 AppliedOk = FALSE; 00434 } 00435 else 00436 { 00437 if (pBitmapCreated->HasBeenDeleted ()) 00438 { 00439 AppliedOk = FALSE; // although everything appeared to work, the bitmap has been deleted 00440 // => abort the op 00441 } 00442 } 00443 } 00444 00445 if (!AppliedOk) 00446 { 00447 FailAndExecute(); 00448 End(); 00449 return; 00450 } 00451 00452 #if 0 00453 // Use the special Bitmap filter as a temp bodge to stick the new bitmap in the tree 00454 MakeBitmapFilter* pBitmapFilter = new MakeBitmapFilter(); 00455 if (pBitmapFilter == NULL) 00456 { 00457 FailAndExecute(); 00458 End(); 00459 return; 00460 } 00461 00462 if (!pBitmapFilter->InsertBitmapIntoDocument(this, pBitmapCreated, pDocument)) 00463 { 00464 delete pBitmapFilter; 00465 FailAndExecute(); 00466 End(); 00467 return; 00468 } 00469 00470 delete pBitmapFilter; 00471 00472 #else 00473 // Create an action to Undo the resizing operation 00474 ActionApplyPlugInToBitmap *APR; 00475 00476 ActionCode ApplyPlugInAction = ActionApplyPlugInToBitmap::Init( this, 00477 &UndoActions, 00478 sizeof(ActionApplyPlugInToBitmap), 00479 pDocument, 00480 pBitmap, 00481 pFoundBitmapRef, 00482 pFoundNode, 00483 pFoundFillAttribute, 00484 (Action**)(&APR) 00485 ); 00486 00487 // If the init happened ok then go and do the first operation 00488 if (ApplyPlugInAction != AC_FAIL) 00489 { 00490 // Apply the initial 'Do' operation - switch the node or fill to use the 00491 // new bitmap that the plug-in has generated. 00492 if (pFoundNode != NULL) 00493 { 00494 // Its a node bitmap so change its bitmap reference to be the new one 00495 pFoundBitmapRef->Attach(pBitmapCreated, pDocument); 00496 00497 // Say that the bitmap has changed 00498 //DoInvalidateNodeRegion((NodeRenderableInk*)pFoundNode, TRUE); 00499 } 00500 else if (pFoundFillAttribute != NULL) 00501 { 00502 // Its a bitmap fill so change its bitmap reference to be the new one 00503 pFoundBitmapRef->Attach(pBitmapCreated, pDocument); 00504 } 00505 else 00506 { 00507 ERROR3("Called ActionApplyPlugInToBitmap::Execute with no node or fill selected!"); 00508 FailAndExecute(); 00509 End(); 00510 return; 00511 } 00512 } 00513 else 00514 { 00515 FailAndExecute(); 00516 End(); 00517 return; 00518 } 00519 #endif 00520 00521 // Make sure that the new selection is up to date 00522 pSelRange = GetApplication()->FindSelection(); 00523 if (pSelRange == NULL || !DoInvalidateNodesRegions(*pSelRange, TRUE)) 00524 { 00525 // We need to invalidate the region 00526 FailAndExecute(); 00527 End(); 00528 return; 00529 } 00530 00531 End(); 00532 return; 00533 } 00534