sgbitmap.cpp

Go to the documentation of this file.
00001 // $Id: sgbitmap.cpp 1664 2006-08-04 10:06:16Z gerry $
00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
00003 ================================XARAHEADERSTART===========================
00004  
00005                Xara LX, a vector drawing and manipulation program.
00006                     Copyright (C) 1993-2006 Xara Group Ltd.
00007        Copyright on certain contributions may be held in joint with their
00008               respective authors. See AUTHORS file for details.
00009 
00010 LICENSE TO USE AND MODIFY SOFTWARE
00011 ----------------------------------
00012 
00013 This file is part of Xara LX.
00014 
00015 Xara LX is free software; you can redistribute it and/or modify it
00016 under the terms of the GNU General Public License version 2 as published
00017 by the Free Software Foundation.
00018 
00019 Xara LX and its component source files are distributed in the hope
00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the
00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00022 See the GNU General Public License for more details.
00023 
00024 You should have received a copy of the GNU General Public License along
00025 with Xara LX (see the file GPL in the root directory of the
00026 distribution); if not, write to the Free Software Foundation, Inc., 51
00027 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
00028 
00029 
00030 ADDITIONAL RIGHTS
00031 -----------------
00032 
00033 Conditional upon your continuing compliance with the GNU General Public
00034 License described above, Xara Group Ltd grants to you certain additional
00035 rights. 
00036 
00037 The additional rights are to use, modify, and distribute the software
00038 together with the wxWidgets library, the wxXtra library, and the "CDraw"
00039 library and any other such library that any version of Xara LX relased
00040 by Xara Group Ltd requires in order to compile and execute, including
00041 the static linking of that library to XaraLX. In the case of the
00042 "CDraw" library, you may satisfy obligation under the GNU General Public
00043 License to provide source code by providing a binary copy of the library
00044 concerned and a copy of the license accompanying it.
00045 
00046 Nothing in this section restricts any of the rights you have under
00047 the GNU General Public License.
00048 
00049 
00050 SCOPE OF LICENSE
00051 ----------------
00052 
00053 This license applies to this program (XaraLX) and its constituent source
00054 files only, and does not necessarily apply to other Xara products which may
00055 in part share the same code base, and are subject to their own licensing
00056 terms.
00057 
00058 This license does not apply to files in the wxXtra directory, which
00059 are built into a separate library, and are subject to the wxWindows
00060 license contained within that directory in the file "WXXTRA-LICENSE".
00061 
00062 This license does not apply to the binary libraries (if any) within
00063 the "libs" directory, which are subject to a separate license contained
00064 within that directory in the file "LIBS-LICENSE".
00065 
00066 
00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
00068 ----------------------------------------------
00069 
00070 Subject to the terms of the GNU Public License (see above), you are
00071 free to do whatever you like with your modifications. However, you may
00072 (at your option) wish contribute them to Xara's source tree. You can
00073 find details of how to do this at:
00074   http://www.xaraxtreme.org/developers/
00075 
00076 Prior to contributing your modifications, you will need to complete our
00077 contributor agreement. This can be found at:
00078   http://www.xaraxtreme.org/developers/contribute/
00079 
00080 Please note that Xara will not accept modifications which modify any of
00081 the text between the start and end of this header (marked
00082 XARAHEADERSTART and XARAHEADEREND).
00083 
00084 
00085 MARKS
00086 -----
00087 
00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
00089 designs are registered or unregistered trademarks, design-marks, and/or
00090 service marks of Xara Group Ltd. All rights in these marks are reserved.
00091 
00092 
00093       Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
00094                         http://www.xara.com/
00095 
00096 =================================XARAHEADEREND============================
00097  */
00098 // SGBitmap.cpp - Bitmap SuperGallery classes - BitmapSGallery and SGDisplayBitmap
00099 
00100 #include "camtypes.h"
00101 
00102 //#include "app.h"      // For GetApplication() - in camtypes.h [AUTOMATICALLY REMOVED]
00103 //nclude "gallery.h"    // For _R(IDC_GALLERY_LISTBOX)
00104 //#include "galstr.h"
00105 //#include "galres.h"
00106 #include "sgbitmap.h"   
00107 #include "sginit.h" 
00108 #include "sgmenu.h"
00109 
00110 //nclude "ccdc.h"       // For render-into-dialogue support
00111 //nclude "fillval.h"
00112 //nclude "grnddib.h"
00113 //#include "will.h"     // For OpShowBitmapGallery ID's
00114 //nclude "bitmap.h" 
00115 #include "bitmpinf.h"   
00116 //#include "fillattr.h"  - in camtypes.h [AUTOMATICALLY REMOVED]
00117 //nclude "attrmgr.h"    
00118 #include "nodebmp.h"    
00119 //nclude "convert.h"    
00120 //#include "resource.h" // For _R(IDS_CANCEL)
00121 
00122 #include "dragmgr.h"
00123 #include "dragbmp.h"
00124 //nclude "viewrc.h"     // FOR _R(IDC_CANDROPONPAGE)
00125 
00126 //#include "docview.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00127 //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00128 #include "tracedlg.h"
00129 #include "bfxdlg.h"
00130 //nclude "bfxalu.h"
00131 //nclude "bitmapfx.h"
00132 #include "impexpop.h"   // Import/Export ops
00133 //#include "scrcamvw.h"
00134 //#include "fixmem.h" - in camtypes.h [AUTOMATICALLY REMOVED]
00135 
00136 //nclude "sglib.h"
00137 
00138 //#include "richard2.h" // extra resource strings
00139 #include "bmpcomp.h"    
00140 //#include "will3.h"    
00141 //#include "phil.h"
00142 
00143 #include "comattrmsg.h"
00144 #include "bmpsdlg.h"
00145 //#include "bmpdlgr.h"
00146 //#include "bmpsdlgr.h"
00147 #include "giffiltr.h"
00148 #include "bmpsrc.h"
00149 
00150 #include "plugop.h"     // PlugInsContextMenu
00151 #include "backgrnd.h"   // OpBackground
00152 #include "keypress.h"   // KeyPress
00153 #include "impexpop.h"   // BitmapExportParam
00154 #include "prevwdlg.h"   // PreviewDialog::Init()
00155 #include "bmpexprw.h"   // BitmapExportPreviewDialog::Init()
00156 
00157 #include "helpuser.h"       //For the help button
00158 //#include "xshelpid.h"     //For the help button
00159 //#include "helppath.h"
00160 //#include "xpehost.h"      // For OPTOKEN_XPE_EDIT
00161 #include "qualattr.h"
00162 #include "bfxop.h"          // useful BFX plug-in related operations
00163 #include "fillattr2.h"
00164 
00165 #ifdef PHOTOSHOPPLUGINS
00166 #include "plugmngr.h"   // CheckHaveDetailsOnPlugIns
00167 #endif //PHOTOSHOPPLUGINS
00168 
00169 #include "camview.h"
00170 
00171 // Implement the dynamic class bits...
00172 CC_IMPLEMENT_DYNCREATE(BitmapSGallery, SuperGallery)
00173 CC_IMPLEMENT_DYNAMIC(SGDisplayKernelBitmap, SGDisplayItem)
00174 CC_IMPLEMENT_DYNCREATE(OpDisplayBitmapGallery,Operation);
00175 CC_IMPLEMENT_DYNAMIC(SGBitmapDragTarget, SGListDragTarget);
00176 
00177 CC_IMPLEMENT_DYNCREATE(GalleryBitmapDragInfo, BitmapDragInformation)
00178 
00179 // Enable Background redraw in the bitmap gallery...
00180 //#define SGBITMAP_BACKGROUND_REDRAW
00181 
00182 // This line mustn't go before any CC_IMPLEMENT_... macros
00183 #define new CAM_DEBUG_NEW
00184 
00185 
00186 BOOL BitmapSGallery::IgnoreBmpListChange = FALSE;
00187 
00188 
00189 /********************************************************************************************
00190 
00191 >   SGBitmapDragTarget::SGBitmapDragTarget(DialogOp *TheDialog, CGadgetID TheGadget = NULL)
00192      
00193     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00194     Created:    25/3/95
00195     Inputs:     TheDialog - The kernel dialog in which the target exists
00196                 TheGadget - The gadget within that dialogue which is the target
00197 
00198     Purpose:    Constructor
00199 
00200 ********************************************************************************************/
00201 
00202 SGBitmapDragTarget::SGBitmapDragTarget(DialogOp *TheDialog, CGadgetID TheGadget)
00203                     : SGListDragTarget(TheDialog, TheGadget)
00204 {
00205     ERROR3IF(!TheDialog->IsKindOf(CC_RUNTIME_CLASS(BitmapSGallery)),
00206             "You can only use SGBitmapDragTargets with BitmapSGallery dialogues!");
00207 }
00208 
00209 
00210 
00211 /********************************************************************************************
00212 
00213     BOOL SGBitmapDragTarget::ProcessEvent(DragEventType Event, DragInformation *pDragInfo,
00214                                             OilCoord *pMousePos, KeyPress* pKeyPress)
00215 
00216     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00217     Created:    25/3/95
00218     Inputs:     Event - Indicates what has happened
00219                 pDragInfo - points to drag information describing this drag. This
00220                 should be a BitmapDragInformation or derivation thereof
00221                 pMousePos - points to information on the current mouse position, in OIL coords
00222                 pKeyPress - NULL, or if for a keypress event, keypress information
00223 
00224     Returns:    TRUE to claim the event, FALSE to let it through to other targets
00225 
00226     Purpose:    Event Handler for SuperGallery listitem drag events. Overrides the
00227                 base class handler to enable it to sort out the node being dragged
00228                 for Bitmap drags.
00229 
00230 ********************************************************************************************/
00231 
00232 BOOL SGBitmapDragTarget::ProcessEvent(DragEventType Event, DragInformation *pDragInfo,
00233                                         OilCoord *pMousePos, KeyPress* pKeyPress)
00234 {
00235     if (!pDragInfo->IsKindOf(CC_RUNTIME_CLASS(BitmapDragInformation)))
00236         return(FALSE);
00237 
00238     SGDisplayNode *DraggedNode = NULL;
00239     BOOL IsSimpleBitmapDrag = TRUE;         // Only one bitmap is being dragged
00240 
00241     if (IS_A(pDragInfo, GalleryBitmapDragInfo))
00242     {
00243         DraggedNode = ((GalleryBitmapDragInfo *)pDragInfo)->GetDraggedBitmap();
00244 
00245         IsSimpleBitmapDrag = FALSE;         // We started the drag, so we will accept multiple
00246                                             // bitmaps being dragged in a single operation
00247     }
00248 
00249     if (DraggedNode != NULL)
00250     {
00251         switch(Event)
00252         {
00253             case DRAGEVENT_COMPLETED:
00254                 HandleDragCompleted((SuperGallery *) TargetDialog,
00255                                     DraggedNode, pMousePos, IsSimpleBitmapDrag);
00256                 return(TRUE);
00257 
00258 
00259             case DRAGEVENT_MOUSESTOPPED:
00260             case DRAGEVENT_MOUSEMOVED:
00261             case DRAGEVENT_MOUSEIDLE:
00262                 // Call a subroutine to work out and set our current cursor shape
00263                 return(DetermineCursorShape((SuperGallery *) TargetDialog,
00264                                             DraggedNode, pMousePos));
00265             default:
00266                 break;
00267         }
00268     }
00269     // Otherwise, we aren't interested in the event, so we don't claim it
00270     return(FALSE);
00271 }
00272 
00273 /********************************************************************************************
00274 
00275 >   void GalleryBitmapDragInfo::GalleryBitmapDragInfo() 
00276      
00277     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00278     Created:    19/3/95       
00279 
00280     Purpose:    Default constructor - do not call this constructor
00281 
00282 ********************************************************************************************/
00283 
00284 GalleryBitmapDragInfo::GalleryBitmapDragInfo()
00285 {
00286     ERROR3("Default GalleryBitmapDragInfo constructor called"); 
00287 }
00288 
00289 
00290 
00291 /********************************************************************************************
00292 
00293 >   GalleryBitmapDragInfo::GalleryBitmapDragInfo(SGDisplayKernelBitmap *pSourceItem,
00294                                             SGMouseInfo *pMouseInfo, SGMiscInfo *pMiscInfo,
00295                                             BOOL IsAdjust = FALSE)
00296      
00297     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00298     Created:    19/3/95       
00299 
00300     Inputs:     pSourceItem - The gallery item from which the drag originated
00301                 pMouseInfo  - The mouse info which made the item start the drag
00302                 pMiscInfo   - The MiscInfo which accompanied the mouse event
00303                 IsAdjust    - TRUE if this is an adjust (line-Bitmap) drag
00304 
00305     Purpose:    Constructor
00306 
00307 ********************************************************************************************/
00308 
00309 GalleryBitmapDragInfo::GalleryBitmapDragInfo(SGDisplayKernelBitmap *pSourceItem,
00310                                             SGMouseInfo *pMouseInfo, SGMiscInfo *pMiscInfo,
00311                                             BOOL IsAdjust)
00312                     : BitmapDragInformation(pSourceItem->GetDisplayedKernelBitmap(),
00313                                             120, 0, 0, 0, IsAdjust)
00314 {
00315     SourceItem  = pSourceItem;  // Copy the source item pointer
00316 
00317     MouseInfo   = *pMouseInfo;  // Duplicate the structures (they may cease to exist
00318     MiscInfo    = *pMiscInfo;   // soon after the drag is started)
00319 }
00320 
00321 /********************************************************************************************
00322 
00323 >   GalleryBitmapDragInfo::~GalleryBitmapDragInfo()
00324  
00325     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00326     Created:    19/3/95       
00327 
00328     Purpose:    Destructor
00329 
00330 ********************************************************************************************/
00331 
00332 GalleryBitmapDragInfo::~GalleryBitmapDragInfo()
00333 {
00334 }
00335 
00336 
00337 /********************************************************************************************
00338 
00339 >   void GalleryBitmapDragInfo::OnClick(INT32 Flags,POINT Point) 
00340      
00341     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00342     Created:    19/3/95       
00343     Inputs:     -
00344     Outputs:    -
00345     Returns:    -
00346     Purpose:    This is called if a drag was attempted but never started because it was a 
00347                 click all along. It calls back the SourceItem SGDisplayBitmap, to get it
00348                 to handle the click.
00349     Errors:     -
00350     SeeAlso:    -
00351 
00352 ********************************************************************************************/
00353 
00354 void GalleryBitmapDragInfo::OnClick(INT32 Flags ,POINT Point)
00355 {
00356     if (SourceItem != NULL)
00357         SourceItem->DragWasReallyAClick(&MouseInfo, &MiscInfo);
00358 }
00359 
00360 /********************************************************************************************
00361 
00362 >   void GalleryBitmapDragInfo::GetCursorID(DragTarget* pDragTarget)
00363 
00364     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00365     Created:    25/3/95
00366     Purpose:    Set cursor over this target
00367 
00368 
00369 ********************************************************************************************/
00370 
00371 UINT32 GalleryBitmapDragInfo::GetCursorID(DragTarget* pDragTarget)
00372 {
00373     if (pDragTarget && pDragTarget->IS_KIND_OF(ViewDragTarget))
00374     {
00375         PageDropInfo PageDropInfo;
00376         ((ViewDragTarget*)pDragTarget)->GetDropInfo(&PageDropInfo);
00377 
00378         NodeRenderableInk* pObjectHit   = PageDropInfo.pObjectHit;
00379         ObjectDragTarget TargetHit      = PageDropInfo.TargetHit;
00380 
00381         if (pObjectHit && pObjectHit->IS_KIND_OF(NodeBitmap))
00382             TargetHit = NO_TARGET;              // Ignore NodeBitmap objects
00383 
00384         ClickModifiers ClickMods = ClickModifiers::GetClickModifiers();
00385         BOOL IsInside = ClickMods.Constrain;
00386 
00387         if (!IsInside && pObjectHit && pObjectHit->IsCompound())
00388         {
00389             TargetHit = MANY_TARGET;
00390         }
00391 
00392         UINT32 CanFill = IsInside ? _R(IDC_DROPINSIDEONFILL) : _R(IDC_CANDROPONFILL);
00393 
00394         switch (TargetHit)
00395         {
00396             case FILL_TARGET:
00397             case LINE_TARGET:
00398             case STARTCOL_TARGET:
00399             case ENDCOL_TARGET:
00400             case ENDCOL2_TARGET:
00401             case ENDCOL3_TARGET:
00402             case MANY_TARGET:
00403                 return CanFill;
00404 
00405             case NO_TARGET:
00406                 // bitmap gallery - drop = add bitmap, CTRL + drop = page fill
00407                 return IsInside ? _R(IDC_CANFILLPAGE) : _R(IDC_CANDROPONPAGE);
00408                 //return _R(IDC_CANDROPONPAGE);
00409         };
00410 
00411         return _R(IDC_CANDROPONPAGE);
00412     }
00413 
00414     return _R(IDC_CANTDROP);
00415 }
00416 
00417 /********************************************************************************************
00418 
00419 >   virtual BOOL GalleryBitmapDragInfo::GetStatusLineText(String_256 * TheText, DragTarget* pDragTarget)
00420 
00421     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00422     Created:    25/3/95
00423     Returns:    Whether String is valid
00424     Purpose:    provide status line text for this target
00425    
00426 ********************************************************************************************/
00427 
00428 BOOL GalleryBitmapDragInfo::GetStatusLineText(String_256 * TheText, DragTarget* pDragTarget)
00429 {
00430     ERROR2IF(TheText==NULL,FALSE,"NULL string in GetStatusLineText()");
00431 
00432     if (TheBitmap == NULL || TheBitmap->ActualBitmap == NULL)
00433         return FALSE;
00434 
00435     String_256 DragString;
00436     String_256 BmpName(TheBitmap->ActualBitmap->GetName());
00437     DragString.MakeMsg(_R(IDS_SGBITMAP_DRAGGING_BITMAP), (TCHAR *)BmpName); // "Dragging Bitmap 'Bitmap' : ");
00438 
00439     if (pDragTarget && pDragTarget->IS_KIND_OF(ViewDragTarget))
00440     {
00441         PageDropInfo PageDropInfo;
00442         ((ViewDragTarget*)pDragTarget)->GetDropInfo(&PageDropInfo);
00443 
00444         NodeRenderableInk* pObjectHit   = PageDropInfo.pObjectHit;
00445         ObjectDragTarget TargetHit      = PageDropInfo.TargetHit;
00446 
00447         String_256 ObjectDesc = String_32(_R(IDS_SGBITMAP_THIS_OBJECT)); // " this object";
00448 
00449         if (pObjectHit)
00450         {
00451             ObjectDesc = pObjectHit->Describe(FALSE);
00452         }
00453 
00454         if (pObjectHit && pObjectHit->IS_KIND_OF(NodeBitmap))
00455             TargetHit = NO_TARGET;              // Ignore NodeBitmap objects
00456 
00457         ClickModifiers ClickMods = ClickModifiers::GetClickModifiers();
00458         BOOL IsInside = ClickMods.Constrain;
00459 
00460         if (!IsInside && pObjectHit && pObjectHit->IsCompound())
00461         {
00462             TargetHit = MANY_TARGET;
00463         }
00464 
00465         switch (TargetHit)
00466         {
00467             case FILL_TARGET:
00468             case LINE_TARGET:
00469             case STARTCOL_TARGET:
00470             case ENDCOL_TARGET:
00471             case ENDCOL2_TARGET:
00472             case ENDCOL3_TARGET:
00473                 DragString += String_256(_R(IDS_SGBITMAP_DROP_APPLY_FILL)); // "Drop to apply a Bitmap fill to this ";
00474                 DragString += ObjectDesc;
00475                 if (IsInside)
00476                     DragString += String_16(_R(IDS_SGBITMAP_ALONE)); // " alone";
00477                 break;
00478             case MANY_TARGET:
00479                 DragString += String_256(_R(IDS_SGBITMAP_DROP_APPLY_FILL)); // "Drop to apply a Bitmap fill to this ";
00480                 DragString += ObjectDesc;
00481                 DragString += String_256(_R(IDS_SGBITMAP_CONTROL_DROP_INSIDE)); // "; Press 'Control' to drop 'Inside'";
00482                 break;
00483             case NO_TARGET:
00484                 if (IsInside)
00485                 {
00486                     DragString += String_256(_R(IDS_DRAGBMP_DROP_SETPAGEBACKGROUND)); // "Drop to set the Bitmap fill of the page background";
00487                 }
00488                 else
00489                 {
00490                     DragString += String_256(_R(IDS_SGBITMAP_DROP_INSERT_BITMAP)); // "Drop to Insert a new Bitmap object on the Page";
00491                 }
00492                 break;
00493         };
00494 
00495         *TheText = DragString;
00496         return TRUE;
00497     }
00498     
00499     return FALSE;
00500 }
00501 
00502 /********************************************************************************************
00503 
00504 >   BOOL GalleryBitmapDragInfo::OnPageDrop(ViewDragTarget* pDragTarget)
00505  
00506     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00507     Created:    19/3/95       
00508     Inputs:     -
00509     Outputs:    -
00510     Returns:    -
00511     Purpose:    Called when a bitmap is dropped onto the page.
00512     Errors:     -
00513     SeeAlso:    -
00514 
00515 ********************************************************************************************/
00516 
00517 BOOL GalleryBitmapDragInfo::OnPageDrop(ViewDragTarget* pDragTarget)
00518 {
00519     PageDropInfo ThePageDropInfo;
00520     ((ViewDragTarget*)pDragTarget)->GetDropInfo(&ThePageDropInfo);
00521     NodeRenderableInk* pObjectHit = ThePageDropInfo.pObjectHit;
00522 
00523     // Find the bitmap to apply
00524     KernelBitmap* BitmapToApply = TheBitmap;
00525     TheBitmap = NULL;
00526 
00527     if(BitmapToApply == NULL)
00528         return FALSE;
00529 
00530     // See if the user dropped the bitmap onto an object(s) on the page
00531     // If so then try and apply that bitmap as a fill to that object(s).
00532     if (pObjectHit && !pObjectHit->IS_KIND_OF(NodeBitmap)) 
00533     {
00534         // Fill the object(s) with the dropped bitmap
00535         AttrBitmapColourFill* Attrib = new AttrBitmapColourFill;
00536         if (Attrib == NULL)
00537             return FALSE;
00538 
00539         Attrib->AttachBitmap(BitmapToApply);
00540 
00541         AttributeManager::ApplyAttribToNode(pObjectHit, Attrib);
00542     }
00543     else
00544     {
00545         // Not dropped onto an object on the page
00546         // See if the control key is pressed
00547         BOOL Constrain = KeyPress::IsConstrainPressed();
00548         if (Constrain)
00549         {
00550             // If the control key is pressed then apply the bitmap as a new background
00551             // We should use the document given to us by the page info class
00552             Document * pDocument = ThePageDropInfo.pDoc;
00553             if (pDocument == NULL)
00554                 return FALSE;
00555             OpBackgroundParam Param;
00556             Param.pBitmap = BitmapToApply;
00557             Param.pDoc = pDocument;         
00558             Param.pSpread = ThePageDropInfo.pSpread;
00559             
00560             // Obtain a pointer to the op descriptor for the create operation 
00561             OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_BACKGROUND);
00562 
00563             // Invoke the operation, passing in our parameters
00564             if (pOpDesc)
00565                 pOpDesc->Invoke(&Param);         
00566         }
00567         else
00568         {
00569             // Create a new bitmap on the page at the drop point
00570 
00571             // Obtain a pointer to the op descriptor for the create operation 
00572             OpDescriptor* OpDesc = OpDescriptor::FindOpDescriptor(CC_RUNTIME_CLASS(OpCreateNodeBitmap));
00573 
00574             if (OpDesc)
00575             {
00576                 // Invoke the operation, passing DocView and Pos as parameters
00577                 OpParam param((void *)BitmapToApply,(void *)&ThePageDropInfo);
00578                 OpDesc->Invoke(&param);      
00579             }
00580         }
00581     }
00582 
00583     return TRUE;
00584 }
00585 
00586 
00587 /***********************************************************************************************
00588 
00589 >   SGDisplayKernelBitmap::SGDisplayKernelBitmap()
00590 
00591     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00592     Created:    27/1/95 (base generated in sgbase.cpp)
00593 
00594     Purpose:    SGDisplayKernelBitmap constructor
00595                 DON'T call this constructor. It ERROR3's. Call the other constructor
00596 
00597 ***********************************************************************************************/
00598 
00599 SGDisplayKernelBitmap::SGDisplayKernelBitmap()
00600 {
00601     ERROR3("Illegal call on default SGDisplayKernelBitmap constructor - call the other one!");
00602     TheKernelBitmap = NULL;
00603 }
00604 
00605 
00606 /***********************************************************************************************
00607 
00608 >   SGDisplayKernelBitmap::SGDisplayKernelBitmap(KernelBitmap *KernelBitmapToDisplay)
00609 
00610     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00611     Created:    27/1/95 (base generated in sgbase.cpp)
00612 
00613     Inputs:     KernelBitmapToDisplay - The KernelBitmap this item will display
00614 
00615     Purpose:    SGDisplayKernelBitmap constructor
00616 
00617 ***********************************************************************************************/
00618 
00619 SGDisplayKernelBitmap::SGDisplayKernelBitmap(KernelBitmap *KernelBitmapToDisplay)
00620 {
00621     ERROR3IF(KernelBitmapToDisplay == NULL,
00622                 "SGDisplayKernelBitmap - trying to construct me with a NULL parameter is bad");
00623 
00624     TheKernelBitmap = KernelBitmapToDisplay;
00625 }
00626 
00627 
00628 
00629 /***********************************************************************************************
00630 
00631 >   virtual void SGDisplayKernelBitmap::CalculateMyRect(SGFormatInfo *FormatInfo,
00632                                                 SGMiscInfo *MiscInfo)
00633 
00634     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00635     Created:    27/1/95 (base generated in sgbase.cpp)
00636 
00637     Inputs:     FormatInfo - The formatting info from which to calculate my position/size
00638                 MiscInfo - As usual, the useful misc info struct
00639 
00640     Outputs:    member variable FormatRect - is returned filled in with the size/position of
00641                 this KernelBitmap item's display area. This is dependent upon the current display
00642                 mode and format state
00643 
00644                 FormatInfo will be updated as a result of the formatting operation
00645 
00646     Purpose:    Shared code for KernelBitmap items to calculate where they will appear in the
00647                 grand scheme of things
00648 
00649     Notes:      KernelBitmaps supply only one display mode ("full info")
00650 
00651     Scope:      private (for use of SGDisplayKernelBitmap class only)
00652 
00653 ***********************************************************************************************/
00654 
00655 void SGDisplayKernelBitmap::CalculateMyRect(SGFormatInfo *FormatInfo, SGMiscInfo *MiscInfo)
00656 {
00657     INT32 XSize;
00658     INT32 YSize;
00659 
00660     switch (MiscInfo->DisplayMode)
00661     {
00662         case 1:                     // 1 - Small full info
00663             XSize = GridLock(MiscInfo, SG_InfiniteWidth);
00664             YSize = GridLock(MiscInfo, SG_DefaultSmallBmp);
00665             break;
00666 
00667         case 2:                     // 2 - Large icon with name
00668             XSize = GridLock(MiscInfo, SG_DefaultLargeBmpText);
00669             YSize = GridLock(MiscInfo, SG_DefaultLargeBmp);
00670             break;
00671 
00672         default:                    // 0 - Full Info
00673             XSize = GridLock(MiscInfo, SG_InfiniteWidth);
00674             YSize = GridLock(MiscInfo, SG_DefaultLargeBmp);
00675             break;
00676     }
00677 
00678     BitmapInfo Info;
00679     INT32 MaxYSize = YSize;
00680 
00681     if (TheKernelBitmap->ActualBitmap &&
00682         TheKernelBitmap->ActualBitmap->GetInfo( &Info )
00683         )
00684     {
00685         // We will adjust the Height of the format rect
00686         // according to the Height of the bitmap.
00687 
00688         double BitmapWidth  = Info.RecommendedWidth;
00689         double BitmapHeight = Info.RecommendedHeight;
00690 
00691         // Calculate the spect ratio of the bitmap
00692         double Ratio = BitmapHeight/BitmapWidth;
00693 
00694         YSize = INT32(YSize * Ratio);
00695 
00696         // ... set a minimum height for each item
00697         INT32 SelHeight = 16000;
00698 
00699         if (YSize < SelHeight*3)
00700             YSize = SelHeight*3;
00701 
00702         if (YSize > MaxYSize)
00703             YSize = MaxYSize;
00704     }
00705 
00706     CalculateFormatRect(FormatInfo, MiscInfo, XSize, YSize);
00707 }
00708 
00709 
00710 
00711 /***********************************************************************************************
00712 
00713 >   virtual void SGDisplayKernelBitmap::HandleRedraw(SGRedrawInfo *RedrawInfo,
00714                                                 SGFormatInfo *FormatInfo)
00715 
00716     Author:     Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
00717     Created:    27/1/95 (base generated in sgbase.cpp)
00718 
00719     Inputs:     RedrawInfo  - The information on the kernel-rendered redraw area
00720                 FormatInfo  - The formatting information structure
00721 
00722                 member variable FormatRect should be set up (before calling this method)
00723                 to be the rectangle in which to draw this item
00724 
00725     Purpose:    SGDisplayKernelBitmap item redraw method - removed from the main HandleEvent
00726                 method merely to make the code tidier.
00727 
00728     Scope:      private
00729 
00730 ***********************************************************************************************/
00731 
00732 void SGDisplayKernelBitmap::HandleRedraw(SGRedrawInfo *RedrawInfo, SGMiscInfo *MiscInfo)
00733 {
00734     if (TheKernelBitmap == NULL || TheKernelBitmap->ActualBitmap == NULL)
00735         return;
00736 
00737     StartRendering(RedrawInfo, MiscInfo);
00738 
00739     DocRect MyRect(FormatRect);     // Get my redraw position from the cached FormatRect
00740 
00741 
00742     // Is this a valid format rectangle ?
00743     if (MyRect.IsEmpty() || !MyRect.IsValid())
00744     {
00745         // No, so just ignore it
00746         // Erroring here is not good, as we are in the middle of a redraw loop
00747         StopRendering(RedrawInfo, MiscInfo);
00748         return;
00749     }
00750 
00751     // Check the rectangle is at least our minimum height,
00752     // and adjust it if not
00753     //INT32 SelHeight = 16000; 
00754     // Changed to allow a third line of text.
00755     INT32 SelHeight = 23000; 
00756 
00757     if (MyRect.Height() < SelHeight*3)
00758     {
00759         INT32 diff = SelHeight*3 - MyRect.Height();
00760         MyRect.Inflate(0, diff);
00761     }
00762 
00763     RenderRegion *Renderer = RedrawInfo->Renderer;
00764 
00765     INT32 OnePixel          = (INT32) DevicePixels(MiscInfo, 1);
00766     INT32 TwoPixels         = (INT32) DevicePixels(MiscInfo, 2);
00767     INT32 ThreePixels   = (INT32) DevicePixels(MiscInfo, 3);
00768 
00769     Renderer->SetLineWidth(0);
00770     Renderer->SetLineColour(RedrawInfo->Transparent);
00771 
00772     // Now calculate the rectangle to plot the bitmap into
00773     DocRect IconRect(MyRect);
00774 
00775     BitmapInfo Info;
00776 
00777     BOOL bScaleDown = FALSE;
00778 
00779     if (TheKernelBitmap->ActualBitmap &&
00780         TheKernelBitmap->ActualBitmap->GetInfo( &Info ))
00781     {
00782         // We will try and make all the bitmaps the same width on screen.
00783         double BitmapWidth  = Info.RecommendedWidth;
00784         double BitmapHeight = Info.RecommendedHeight;
00785 
00786         // Calculate the spect ratio of the bitmap
00787         double Ratio = BitmapWidth/BitmapHeight;
00788 
00789         INT32 IconWidth = INT32(IconRect.Height() * Ratio);
00790 
00791         INT32 YSize;
00792         switch (MiscInfo->DisplayMode)
00793         {
00794             case 1:                     // 1 - Small full info
00795                 YSize = GridLock(MiscInfo, SG_DefaultSmallBmp);
00796                 break;
00797 
00798             case 2:                     // 2 - Large icon with name
00799                 YSize = GridLock(MiscInfo, SG_DefaultLargeBmp);
00800                 break;
00801 
00802             default:                    // 0 - Full Info
00803                 YSize = GridLock(MiscInfo, SG_DefaultLargeBmp);
00804                 break;
00805         }
00806         
00807         // If the bitmap is very Wide and Thin, then we need to scale it
00808         // so it fits into out maximum icon width
00809         if (IconWidth > YSize)
00810         {
00811             Matrix Scale;
00812             Ratio = double(IconWidth)/double(YSize);
00813 
00814             Scale = Matrix(FIXED16(1)/Ratio, FIXED16(1)/Ratio);
00815 
00816             DocCoord Centre;
00817             Centre.x = IconRect.lo.x;
00818             Centre.y = IconRect.lo.y + IconRect.Height()/2;
00819 
00820             // Scale the bitmap rectangle about the Left Middle so
00821             // that it is always 'YSize' in Width
00822             IconRect.Translate(-Centre.x, -Centre.y);
00823             Scale.transform(&IconRect.lo);
00824             Scale.transform(&IconRect.hi);
00825             IconRect.Translate(Centre.x, Centre.y);
00826 
00827             IconWidth = YSize;
00828             bScaleDown = TRUE;
00829         }
00830 
00831         INT32 RightSpace = 0;
00832 
00833         if (IconWidth < YSize)
00834         {
00835             INT32 LeftSpace = TwoPixels * 4;
00836             RightSpace = YSize - IconWidth - LeftSpace;
00837             IconRect.Translate(LeftSpace, 0);   // Move it over a bit
00838         }
00839 
00840         // Now setup the IconRect
00841         IconRect.hi.x = IconRect.lo.x + IconWidth;
00842 
00843         MyRect.lo.x = IconRect.hi.x + RightSpace + TwoPixels;   // And exclude it from 'MyRect'
00844         MyRect.lo.x += TwoPixels;
00845 
00846         // Now check the Icon isn't too tall
00847 
00848         INT32 MaxYSize = YSize;
00849         INT32 IconHeight = IconRect.Height();
00850         if (IconHeight > MaxYSize)
00851         {
00852             Matrix Scale;
00853             Ratio = double(IconHeight)/double(YSize);
00854 
00855             Scale = Matrix(FIXED16(1)/Ratio, FIXED16(1)/Ratio);
00856 
00857             DocCoord Centre;
00858             Centre.x = IconRect.lo.x + IconRect.Width()/2;
00859             Centre.y = IconRect.hi.y;
00860 
00861             // Scale the bitmap rectangle about the Middle so
00862             // that it is always 'YSize' in Height
00863             IconRect.Translate(-Centre.x, -Centre.y);
00864             Scale.transform(&IconRect.lo);
00865             Scale.transform(&IconRect.hi);
00866             IconRect.Translate(Centre.x, Centre.y);
00867 
00868             MyRect.lo.y = IconRect.lo.y;
00869             MyRect.hi.y = IconRect.hi.y;
00870             bScaleDown = TRUE;
00871         }
00872     }
00873 
00874     // This section doesn't currently do anything special as we 
00875     // have gone back to using an OSRenderRegion
00876     // If the display quality is too bad then we should modify 
00877     // this code to render a high quality thumbnail and store it 
00878     // for future use, rendering the thumbnail into an OSRenderRegion
00879 /*  Renderer->SetUsingSmoothedBitmaps(bScaleDown);
00880     if (bScaleDown)
00881     {
00882         Quality qual;
00883         qual.SetQuality(QUALITY_MAX);
00884         QualityAttribute *pQuality = new QualityAttribute(qual);
00885         Renderer->SetQuality(pQuality, TRUE);           // Temp
00886     }
00887     else
00888     {
00889         Quality qual;   // QUALITY_DEFAULT is implied
00890         QualityAttribute *pQuality = new QualityAttribute(qual);
00891         Renderer->SetQuality(pQuality, TRUE);           // Temp
00892     }*/
00893 
00894     GridLockRect(MiscInfo, &MyRect);    // Ensure the new 'MyRect' is pixel-grid-aligned
00895 
00896     // If we can, we need to leave a little space around the
00897     // edges of the bitmap rect, so we can see the 'Selected' rectangle
00898     // behind it.  We only try this if the rectangle is big enough
00899     // otherwise the Inflate routine will create an invalid rectangle.
00900 
00901     if (IconRect.Height() > ThreePixels * 2)
00902         IconRect.Inflate(0, -ThreePixels);      // Leave a bit of space around the edge
00903 
00904     if (IconRect.Width() > ThreePixels * 2)
00905         IconRect.Inflate(-ThreePixels, 0);      // Leave a bit of space around the edge
00906     
00907     GridLockRect(MiscInfo, &IconRect);  // Ensure it maps exactly to specific pixels
00908 
00909     // Need to remember the icon rect size before the selection rectangle takes over...
00910     DocRect ThumbnailRect(IconRect);
00911 
00912     // In the bitmap gallery, it's better to show something than nothing
00913     // So if the thumbnail has become so thin as to be invisible
00914     // We will bodge it back into shape even if that distorts things a bit
00915     if (ThumbnailRect.Width()==0)
00916         ThumbnailRect.hi.x = ThumbnailRect.lo.x + OnePixel;
00917     if (ThumbnailRect.Height()==0)
00918         ThumbnailRect.hi.y = ThumbnailRect.lo.y + OnePixel;
00919 
00920     // Set up the colours for rendering our text, and fill the background if selected
00921     if (Flags.Selected)
00922     {
00923         // This Item is Selected
00924 
00925         // Fill the entire background with the 'selected' colour, so we don't
00926         // get gaps between bits of text or uneven rectangles in multiple selections
00927         Renderer->SetFillColour(RedrawInfo->SelBackground);
00928 
00929         Renderer->SetFillColour(COLOUR_BLACK);
00930         IconRect.Inflate(ThreePixels);
00931 
00932         // Draw a Three Pixel wide rectangle around the edge of the bitmap
00933         // (Actually we're plotting a filled rectangle which is three pixels
00934         //  bigger than the bitmap rectangle)
00935         Renderer->DrawRect(&IconRect);
00936 
00937         // If the icon rect is wider than the gallery, then MyRect could have become invalid,
00938         // so we only try to draw the selection background if any of it is actually visible
00939         if (MyRect.IsValid())
00940         {
00941             DocRect SelRect(MyRect);
00942             if (SelHeight > MyRect.Height()/2)
00943                 SelHeight = MyRect.Height()/2;
00944 
00945             SelRect.hi.y = MyRect.lo.y + MyRect.Height()/2 + SelHeight;
00946             SelRect.lo.y = MyRect.lo.y + MyRect.Height()/2 - SelHeight;
00947             SelRect.lo.x += ThreePixels;
00948             GridLockRect(MiscInfo, &SelRect);   // Ensure it maps exactly to specific pixels
00949 
00950             Renderer->SetFillColour(RedrawInfo->SelBackground);
00951             Renderer->DrawRect(&SelRect);
00952         }
00953 
00954         Renderer->SetFixedSystemTextColours(&RedrawInfo->SelForeground, &RedrawInfo->SelBackground);
00955     }
00956     else
00957     {
00958         // This Item is Not Selected
00959         Renderer->SetFixedSystemTextColours(&RedrawInfo->Foreground, &RedrawInfo->Background);
00960     }
00961 
00962 
00963 #ifdef SGBITMAP_BACKGROUND_REDRAW
00964 
00965     BOOL DrawnBitmap = FALSE;
00966 
00967     if (ShouldIDrawForeground(DrawnBitmap))
00968     {
00969         if(!DrawnBitmap)
00970         {
00971             // Now we need to create a temporary NodeBitmap, which we will
00972             // use to render the bitmap preview.
00973             NodeBitmap* DummyBmp = new NodeBitmap();
00974             if (DummyBmp == NULL)
00975             {
00976                 // Just exit if we're out of memory
00977                 SGLibDisplayItem::DrawNullBitmapRect(Renderer, MiscInfo, &ThumbnailRect, FALSE);
00978                 StopRendering(RedrawInfo, MiscInfo);
00979                 return;
00980             }
00981 
00982             // Set the NodeBitmap path to be our IconRect, 
00983             // and attach the Bitmap to it.
00984             DummyBmp->SetUpPath();
00985             DummyBmp->CreateShape(ThumbnailRect);
00986             DummyBmp->GetBitmapRef()->SetBitmap(TheKernelBitmap);
00987 
00988             // Now render the bitmap preview
00989             DummyBmp->Render(Renderer);
00990 
00991             delete DummyBmp;
00992         }
00993     }
00994     else
00995     {
00996         // We should background render, so we just draw a blank grey box
00997         if(!DrawnBitmap)
00998             SGLibDisplayItem::DrawNullBitmapRect(Renderer, MiscInfo, &ThumbnailRect, TRUE);
00999     }
01000 
01001 #else
01002 
01003     // Now we need to create a temporary NodeBitmap, which we will
01004     // use to render the bitmap preview.
01005     NodeBitmap* DummyBmp = new NodeBitmap();
01006     if (DummyBmp == NULL)
01007     {
01008         // Just exit if we're out of memory
01009         StopRendering(RedrawInfo, MiscInfo);
01010         return;
01011     }
01012 
01013     // Set the NodeBitmap path to be our IconRect, 
01014     // and attach the Bitmap to it.
01015     DummyBmp->SetUpPath();
01016     DummyBmp->CreateShape(ThumbnailRect);
01017     DummyBmp->GetBitmapRef()->SetBitmap(TheKernelBitmap);
01018 
01019     // Now render the bitmap preview
01020     DummyBmp->Render(Renderer);
01021 
01022     delete DummyBmp;
01023 
01024 #endif
01025 
01026     // Leave a small gap before text begins
01027     MyRect.lo.x += SG_GapBeforeText*2;
01028 
01029     // And now render the text describing the bitmap
01030     // ...but only if there is any space left (i.e. MyRect is still valid)
01031     if (MyRect.IsValid())
01032     {
01033         // First get the name of the bitmap
01034         String_256 BitmapName = TheKernelBitmap->ActualBitmap->GetName();
01035 
01036         // Now find how many colours it has
01037         String_256 BitmapCols;
01038         INT32 bpp = TheKernelBitmap->GetBPP();
01039 
01040         BOOL HasTransparency = FALSE;
01041         
01042         if (bpp <= 8)
01043         {
01044             // Check to see if this is a masked bitmap
01045             INT32 Index;
01046 
01047             if (TheKernelBitmap->GetTransparencyIndex(&Index))
01048                 HasTransparency = TRUE;
01049         }
01050 
01051         switch (bpp)
01052         {
01053             case 1:
01054                 if (HasTransparency)
01055                     BitmapCols = _R(IDS_SGBITMAP_MONOCHROME_T); // "Monochrome, transparent";
01056                 else
01057                     BitmapCols = _R(IDS_SGBITMAP_MONOCHROME);   // "Monochrome";
01058                 break;
01059 
01060             case 2:
01061                 if (HasTransparency)
01062                     BitmapCols = _R(IDS_SGBITMAP_4COLOURS_T);   // "3 colours, transparent";
01063                 else
01064                     BitmapCols = _R(IDS_SGBITMAP_4COLOURS);     // "4 colours";
01065                 break;
01066 
01067             case 4:
01068                 if (HasTransparency)
01069                     BitmapCols = _R(IDS_SGBITMAP_16COLOURS_T);  // "15 colours, transparent";
01070                 else
01071                     BitmapCols = _R(IDS_SGBITMAP_16COLOURS);    // "16 colours";
01072                 break;
01073 
01074             case 8:
01075                 if (HasTransparency)
01076                     BitmapCols = _R(IDS_SGBITMAP_256COLOURS_T); // "255 colours, transparent";
01077                 else
01078                     BitmapCols = _R(IDS_SGBITMAP_256COLOURS);   // "256 colours";
01079                 break;
01080 
01081             case 16:
01082                 BitmapCols = _R(IDS_SGBITMAP_65COLOURS);        // "65K colours";
01083                 break;
01084 
01085             case 24:
01086                 BitmapCols = _R(IDS_SGBITMAP_MILLIONS_COLOURS); // "Millions of colours";
01087                 break;
01088 
01089             case 32:
01090                 BitmapCols = _R(IDS_SGBITMAP_32_BIT); // "Millions of colours";
01091                 break;
01092 
01093             default:
01094                 BitmapCols = "";
01095                 break;
01096         }
01097 
01098         // Now get its pixel Width and Height
01099         String_256 BitmapWidth;
01100         Convert::LongToString(Info.PixelWidth, &BitmapWidth);
01101         
01102         String_256 BitmapHeight;
01103         Convert::LongToString(Info.PixelHeight, &BitmapHeight);
01104 
01105         // Find the delay value;
01106         UINT32 BitmapDelay = TheKernelBitmap->ActualBitmap->GetBitmapAnimDelay();
01107         String_256 Delay;
01108         Convert::LongToString(BitmapDelay, &Delay);
01109 
01110         // And finally, work out how much memory it is using
01111         // The memory size depends on whether this is a bitmap or JPEG.
01112 
01113         INT32 Bytes = 0;
01114         BitmapSource* pSource = NULL;
01115         BaseBitmapFilter* pDummyFilter;
01116 
01117 PORTNOTE("other", "Removed XPE hook")
01118 #ifndef EXCLUDE_FROM_XARALX
01119         KernelBitmap* pMaster = NULL;
01120         IXMLDOMDocumentPtr pEdits = NULL;
01121         TheKernelBitmap->GetXPEInfo(pMaster, pEdits);
01122         BOOL bIsXPE = (pMaster!=NULL && pEdits!=NULL);
01123 #else
01124         BOOL bIsXPE = FALSE;
01125 #endif
01126 
01127         BOOL OriginalSourcePresent = TheKernelBitmap->GetOriginalSource(&pSource, &pDummyFilter);
01128         String_256 BitmapFormat;
01129         if(OriginalSourcePresent)
01130         {
01131             if (pSource != NULL)
01132             {
01133                 if (pSource->IsJPEG())
01134                 {
01135                     Bytes = pSource->GetSize();
01136                     BitmapFormat = _R(IDS_FORMAT_JPEG);
01137                 }
01138             }
01139         }
01140         else if (bIsXPE)
01141         {
01142             BitmapFormat = _R(IDS_FORMAT_XPE);
01143         }
01144         else
01145         {
01146             Bytes = (Info.PixelWidth * Info.PixelHeight * bpp)/8;
01147             BitmapFormat = _R(IDS_FORMAT_BITMAP);
01148         }
01149 
01150         String_256 MemoryUsed;
01151         Convert::BytesToString(&MemoryUsed, Bytes);
01152 
01153         if (!BaseCamelotFilter::ShouldSaveXPEBitmaps() && bIsXPE)
01154         {
01155             // If the bitmap is generated from a Master and edit list
01156             // Then don't show size in bytes 'cos it's meaningless
01157             MemoryUsed.Load(_R(IDS_SGBITMAP_XPE));
01158         }
01159 
01160         // Now we are going to plot all that information
01161         // split into two lines of text
01162         DocRect TopRect(MyRect);
01163         DocRect MiddleRect(MyRect);
01164         DocRect BottomRect(MyRect);
01165 
01166         //TopRect.lo.y  += 11000;
01167         TopRect.lo.y    += 18000;
01168         MiddleRect.hi.y     -= 5000;
01169         //MiddleRect.hi.y   -= 16000; Down
01170         BottomRect.hi.y -= 26000; 
01171 
01172         // Plot the Name and Memory used on the Top Line
01173         String_256 TopLine; // = "'"+BitmapName+"', "+BitmapFormat", "+MemoryUsed;
01174         TopLine.MakeMsg(_R(IDS_SGBITMAP_FULLINFO_TOPLINE),(TCHAR *)BitmapName,(TCHAR*)BitmapFormat,(TCHAR *)MemoryUsed);
01175         Renderer->DrawFixedSystemText(&TopLine, TopRect);               
01176 
01177 
01178         // Plot the Dimensions and Colours on the Bottom Line
01179         String_256 MiddleLine; //  = BitmapWidth+" by "+BitmapHeight+" pixels,  "+BitmapCols;
01180 
01181         // Calculate the dpi of the original winbitmap...
01182         UINT32 hdpi = TheKernelBitmap->ActualBitmap->GetHorizontalDPI();
01183         UINT32 vdpi = TheKernelBitmap->ActualBitmap->GetVerticalDPI();
01184 
01185         if (hdpi == vdpi)
01186         {
01187             String_256 dpitext;
01188             Convert::LongToString(hdpi, &dpitext);
01189             MiddleLine.MakeMsg(_R(IDS_SGBITMAP_FULLINFO_BOTTOMLINE), (TCHAR *)BitmapWidth, (TCHAR *)BitmapHeight, (TCHAR *)BitmapCols, (TCHAR *)dpitext);
01190         }
01191         else
01192         {
01193             String_256 dpitext;
01194             camSnprintf(dpitext, 256, _T("%u x %u"), hdpi, vdpi);
01195             MiddleLine.MakeMsg(_R(IDS_SGBITMAP_FULLINFO_BOTTOMLINE), (TCHAR *)BitmapWidth, (TCHAR *)BitmapHeight, (TCHAR *)BitmapCols, (TCHAR *)dpitext);
01196         }
01197         Renderer->DrawFixedSystemText(&MiddleLine, MiddleRect);             
01198 
01199 
01200         // Find the Restore type 
01201         GIFDisposalMethod RestoreType = TheKernelBitmap->ActualBitmap->GetAnimationRestoreType();
01202         
01203         switch(RestoreType)
01204         {
01205             case GDM_NONE:
01206             {
01207                 String_256 BottomLine;
01208                 String_256 Nothing(_R(IDS_NOTHING));
01209                 BottomLine.MakeMsg(_R(IDS_SGBITMAP_DELAY_RESTORE_BOTTOMLINE), (