OpSlice Class Reference

The "Image Slice" menu item. More...

#include <slice.h>

Inheritance diagram for OpSlice:

OpMenuImport SelOperation UndoableOperation Operation MessageHandler ListItem CCObject SimpleCCObject List of all members.

Public Member Functions

void Do (OpDescriptor *)
 Exports the current document as slices defined by named selections.

Static Public Member Functions

static BOOL Init ()
 Declares the OpDescriptor.
static OpState GetState (String_256 *, OpDescriptor *)
 This item is always available, so long as a document is visible. Not really sure if I even need this!!!
static DocRect ScanLargeSliceBounds (const String_256 &Name)

Protected Member Functions

BOOL AddSlice (INT32 Ax, INT32 Ay, INT32 Cx, INT32 Cy, CList< CSlice *, CSlice * > *pMosaicList, String_256 SliceName)
 slice rect ABCD A---B | | D---C pMosaicList should start with one entry which is the whole drawing extent that is to be split up into sections. The passed in slice (AC) is added to the list of pieces which is a named user defined slice. Existing pieces that are occupy the same area are cut into smaller parts or absorbed.
BOOL InRect (CSlice *pRect, INT32 x, INT32 y)
 Tests if the point X,Y is in the rectangle defined by the slice.
BOOL Slice (CSlice *pRect, INT32 Ax, INT32 Ay, INT32 Bx, INT32 By, CList< CSlice *, CSlice * > *pMosaicList)
 Split the Slice pRect into smaller rectangles along the line AB.
BOOL CutsRect (CSlice *pRect, INT32 Ax, INT32 Ay, INT32 Bx, INT32 By)
 Tests to see if the line AB cuts the rectangle pRect.
BOOL SortSlices (CList< CSlice *, CSlice * > *pMosaicList, const DocRect &Bounds)
 Sorts the slices into order. Merges together suitable slices. Fills in colm & row positions, spans and width/heights for defining an HTML table. Gives names to nameless slices in the form r*c*.
BOOL ExportImageSliceHTML (CList< CSlice *, CSlice * > *pMosaicList, const String_256 &HTMLFile, INT32 FileNumber=1)
 Creates an HTML file with a table that re-weaves the sliced images back together Also if rollovers have been defined they are also incorperated.
BOOL ExportSliceGraphic (CSlice *pSlice, BitmapExportOptions *pExportOptions, const String_256 &GraphicFileName)
 Generates a graphic of a section of the whole image defined by the rectangular area of the slice. Params: pSlice - the slice to export contains area rect and name.
BOOL SaveFileDlg ()
 Brings up the save dlg to ask the user where to save the html and the slices too. Also has the filter selection to choose from when picking the default slice. Sets the path location, name and graphic type into the variable m_PathName.
INT32 TidyMosaicList (CList< CSlice *, CSlice * > *pMosaicList)
 Deletes all the slices in the list now that we are done with them. So there will be no memory leeks.
void UpdateSliceFileExts (CList< CSlice *, CSlice * > *pMosaicList)
 Changes all non set file types to be the type the user picks from the file dlg.
void NudgeSliceIfClose (INT32 &Ax, INT32 &Ay, INT32 &Cx, INT32 &Cy, CList< CSlice *, CSlice * > *pMosaicList)
 Moves the new slice over a bit if it just overlaps with an existing slice due to the pixel infation. It does this by adjusting the AC rectangle passed in.
void RemoveIlligalFileAndJavaChars (String_256 &Str)
 Replaces any illigal chars in the Str as far as filenames and use as javascript variables for use in rollovers is concerned.
String_256 TurnUnderScoreIntoSpace (const String_256 &StartStr)
void PixelAlignedInflate (DocRect *r)
 Infates a DocRect to the nearest pixel aligned boundary.
void MarkEmptySlices (CList< CSlice *, CSlice * > *pMosaicList, DocRect &SelRect, BitmapExportOptions *pExportOptions)
 What it is meant to do is check if the drawing has anything that is visible within this slice. So if there is nothing visible don't bother generating a graphic for it. Any empty slices are set as empty in the list of slices. Method used is to render the image to be exported as a 32bit graphic and then check the alpha channel for anything non-transparent. Param pMoasicList - List of the slices SelRect - The rect of the image being exported Returns - Errors Not putting a graphic into the HTML table may screw up the sizing of cells in the table if it was relying on this cell to get the size information. So instead I re-use the shim graphic expanded to that size (see the ExportHTML fn).
void ScanTextStorySliceBounds (const String_256 &Name, DocRect &Bounds)
CSliceGetButtonNumber (CList< CSlice *, CSlice * > *pMosaicList, INT32 buttonno)
BOOL ScanForRolloverStates (CList< CSlice *, CSlice * > *pMosaicList)
 Sets the m_RolloverState member variable by scanning the layers and finding out what specail named layers exist for the creation of rollovers.
BOOL ExportRollOverSlice (CSlice *pSlice, BitmapExportOptions *pExportOptions)
 Exports all the rollover states of this given slice if they are defined.
void ShowRolloverLayer (INT32 ShowLayer)
 Shows the layer number passed to it and hides the other of the rollover layers. Pass it DEFAULT, MOUSE, CLICKED, SELECTED, ORIGINAL_LAYERS or ALL_LAYERS.
BOOL URLScan (String_256 *pLinkName, CList< CSlice *, CSlice * > *pMosaicList)
 Scans through the tree looking for URL tags. If it finds one it looks for a set name on the same node. If it finds a set name it scans the Mosaic list for the button with that set name and records the URL as the link name for that button number Param pMoasicList - List of the slices pLinkName - The dynamic array holding the URLs for each button Returns TRUE if it ran ok.
void FailledToExportHTML (const String_256 &file)
 Puts up an error msg saying that it could export the HTML and marks it as unexported Param file - The file it failled to export Returns.

Static Protected Member Functions

static BYTE * LoadFileIntoMemory (String_256 FileName, DWORD &Size)
 Creates a copy of the file in memory and says how big it is Param Filename - The file to open Size - Fills in this param with the size of the memory object created Returns a ptr to the memory, or NULL if it failled.
static BYTE * FindNextOccuranceOf (BYTE *pSearch, BYTE *pFrom)
 Finds the next occurance of a string in the other large 'string'. Pass in lowercase and it will match with uppercase letters Param pSearch - The shorter string being searched for pFrom - The larger string to find it in Returns a ptr to the memory where the search string was located nearest to the starting point, or NULL if it wasn't found.
static BYTE * FindPreviousChar (char Search, BYTE *pFrom, BYTE *pLimit)
static void WriteText (ofstream &f, BYTE *pData, INT32 NoOfBytes)
 There appeared to be a slight problem when using the write function to output text to the ofstream that contained chars 10 & 13. This function neatens this up cutting out 10,13 & 0 and putting a nice
in the right places. Param f - The output stream pData - the string to output NoOfBytes - Number of bytes to send to the stream Returns.

Protected Attributes

PathName m_PathName
String_256 m_HTMLext
INT32 m_lRed
INT32 m_lGreen
INT32 m_lBlue
String_256 m_ErrorStr
BOOL m_UsedShimGraphic
BOOL m_UsesDesignNotes
String_256m_pLinkName
RolloverState m_RolloverState [4]
BOOL m_FoundRolloverStates
INT32 m_NumberOfButtons
BOOL m_ExportedHTMLOK
BOOL m_InjectHTML

Detailed Description

The "Image Slice" menu item.

Author:
Simon_Knight (Xara Group Ltd) <camelotdev@xara.com>
Date:
20/7/99
See also:

Definition at line 194 of file slice.h.


Member Function Documentation

BOOL OpSlice::AddSlice INT32  Ax,
INT32  Ay,
INT32  Cx,
INT32  Cy,
CList< CSlice *, CSlice * > *  pMosaicList,
String_256  SliceName
[protected]
 

slice rect ABCD A---B | | D---C pMosaicList should start with one entry which is the whole drawing extent that is to be split up into sections. The passed in slice (AC) is added to the list of pieces which is a named user defined slice. Existing pieces that are occupy the same area are cut into smaller parts or absorbed.

Author:
Simon_Knight (Xara Group Ltd) <camelotdev@xara.com>
Date:
23/7/99
Params: Axy, Cxy defines the new slice pMosaic is this list of the slices SliceName is the name of the new slice

Returns:
TRUE if it worked - FALSE if something failled

Definition at line 983 of file slice.cpp.

00984 {
00985     // ignore empty slices as we could hardly export them
00986     // but since slices containing nothing could exist we should cater
00987     // for the possibility
00988     if (Ax == Cx || Ay == Cy) return TRUE;
00989 
00990     // if the inflate to pixel aligned rect has swapped over two named slices
00991     // set them to being on the same boundry
00992     NudgeSliceIfClose(Ax, Ay, Cx, Cy, pMosaicList);
00993 
00994     BOOL ok = TRUE;
00995     POSITION pos = pMosaicList->GetHeadPosition();
00996 
00997     while (pos)
00998     {
00999         POSITION thispos = pos;
01000         CSlice * pRect = pMosaicList->GetNext(pos);
01001         BOOL RemoveMe = TRUE;
01002         
01003         if (Ax == pRect->left && Cx == pRect->right && Ay == pRect->top && Cy == pRect->bottom)
01004         {
01005             // remove existing identical slices
01006             // keep the name if it has one and the replacement doesn't.
01007             if (!pRect->name.IsEmpty())
01008             {
01009                 TRACE( _T("Identically named slices\n"));
01010                 if (SliceName.IsEmpty())
01011                     SliceName = pRect->name;
01012             }
01013         }
01014         else
01015         if (InRect(pRect, Ax, Ay)) // A in rect
01016             ok = Slice (pRect, Ax, Ay, Cx, Ay, pMosaicList); // slice AB
01017         else
01018         if (InRect(pRect, Cx, Ay)) // B in rect
01019             ok = Slice (pRect, Ax, Ay, Cx, Ay, pMosaicList); // slice AB
01020         else
01021         if (CutsRect(pRect, Ax, Ay, Cx, Ay)) // cuts AB
01022             ok = Slice (pRect, Ax, Ay, Cx, Ay, pMosaicList); // slice AB
01023         else
01024         if (InRect(pRect, Cx, Cy)) // C in rect
01025             ok = Slice (pRect, Cx, Ay, Cx, Cy, pMosaicList); // slice BC
01026         else
01027         if (CutsRect(pRect, Cx, Ay, Cx, Cy)) // cuts BC
01028             ok = Slice (pRect, Cx, Ay, Cx, Cy, pMosaicList); // slice BC
01029         else
01030         if (InRect(pRect, Ax, Cy)) // D in rect
01031             ok = Slice (pRect, Ax, Ay, Ax, Cy, pMosaicList); // slice AD
01032         else
01033         if (CutsRect(pRect, Ax, Ay, Ax, Cy)) // cuts AD
01034             ok = Slice (pRect, Ax, Ay, Ax, Cy, pMosaicList); // slice AD
01035         else
01036         if (CutsRect(pRect, Ax, Cy, Cx, Cy)) // cuts DC
01037             ok = Slice (pRect, Ax, Cy, Cx, Cy, pMosaicList); // slice DC
01038         else
01039         if (pRect->left >= Ax && pRect->right <= Cx && pRect->top >= Ay && pRect->bottom <= Cy) // rect in ABCD
01040             //remove rect from list
01041         {
01042             TRACE( _T("remove sub rect\n"));
01043             // NB doing nothing will result in it being removed
01044         }
01045         else // this piece doesn't interact with the slice at all
01046             RemoveMe = FALSE; // so don't let it be taken from us
01047 
01048         if (!ok)
01049             return FALSE; // an error occurred
01050         
01051         pos = thispos;
01052         // reget the next item to check that we haven't extended the list
01053         pRect = pMosaicList->GetNext(pos);
01054 
01055         if (RemoveMe)
01056         {
01057             pMosaicList->RemoveAt(thispos);
01058             delete pRect;
01059         }
01060     }
01061 
01062     // add the slice passed in
01063     // remember to give it the users individually selected graphic type
01064     // which isn't yet implimented
01065     RemoveIlligalFileAndJavaChars(SliceName);
01066     pMosaicList->AddHead(new CSlice(Ax, Ay, Cx, Cy, SliceName, m_PathName.GetType(), TRUE));
01067 
01068     return ok;
01069 }

BOOL OpSlice::CutsRect CSlice pRect,
INT32  Ax,
INT32  Ay,
INT32  Bx,
INT32  By
[protected]
 

Tests to see if the line AB cuts the rectangle pRect.

Author:
Simon_Knight (Xara Group Ltd) <camelotdev@xara.com>
Date:
23/7/99
Returns:
TRUE if it does cut

Definition at line 1139 of file slice.cpp.

01140 {
01141     if (Ax == Bx) // Vert cut
01142     {
01143         // top & bottom outside rect
01144         // while the vertical line cuts through the rect
01145         if (Ay <= pRect->top && By >= pRect->bottom
01146             && Ax < pRect->right && Ax > pRect->left)
01147             return TRUE;
01148     }
01149     else
01150     if (Ay == By) // Horiz cut
01151     {
01152         // left & right outside rect
01153         // while the horizontal line cuts through the rect
01154         if (Ax <= pRect->left && Bx >= pRect->right
01155             && Ay < pRect->bottom && Ay > pRect->top)
01156             return TRUE;
01157     }
01158     
01159     return FALSE;
01160 }

void OpSlice::Do OpDescriptor  )  [virtual]
 

Exports the current document as slices defined by named selections.

Author:
Simon_Knight (Xara Group Ltd) <camelotdev@xara.com>
Date:
20/7/99
Returns:
Errors: -

Reimplemented from OpMenuImport.

Definition at line 285 of file slice.cpp.

00286 {
00287     // there needs to be a spread
00288     Spread* pSelSpread = Document::GetSelectedSpread();
00289     if (pSelSpread == NULL)
00290         return;
00291 
00292     //  Let's set a variable in BmapPrevDlg which will be used to determine
00293     //  which of the tab controls should be enabled or disabled.
00294     BmapPrevDlg::m_bSlicingImage = TRUE;
00295 
00296     m_ErrorStr = "none";
00297     m_HTMLext = "htm";
00298 
00299     m_NumberOfButtons = 0;
00300 
00301     // init the export path - which probably isn't needed
00302     // but better safe than sorry etc...
00303     // set to .non so that any slices that are defined from this can be
00304     // found and redefined later. see UpdateSliceFileExts() - sjk
00305     m_PathName.SetPathName("c:\\untitled.non");
00306 
00307     m_InjectHTML = FALSE; // don't inject without thinking about it - you know it makes sense!
00308 
00309     m_ExportedHTMLOK = TRUE; // asumes the best :-)
00310 
00311     // start a slow job
00312     Progress LongJob;
00313     LongJob.Start();
00314 
00315     // test if we use design notes
00316     m_UsesDesignNotes = UsesDesignNotes();
00317 
00318     // calculate the background colour
00319     DocColour dcol = Page::GetPageColour();
00320     m_lRed = m_lGreen = m_lBlue = 255;
00321 
00322     BOOL HasBitmapBackground = FALSE;
00323 
00324     Layer * pLayer = pSelSpread->FindFirstPageBackgroundLayer();
00325     if (pLayer)
00326     {
00327         Node * pNode = SliceHelper::FindNextOfClass(pLayer, pLayer, CC_RUNTIME_CLASS(AttrFlatColourFill));
00328         if (pNode)
00329             dcol = *(((AttrFlatFill *)pNode)->GetStartColour());
00330         else
00331         {
00332             if (SliceHelper::FindNextOfClass(pLayer, pLayer, CC_RUNTIME_CLASS(AttrBitmapColourFill)))
00333                 HasBitmapBackground = TRUE;
00334         }
00335     }
00336 
00337     dcol.GetRGBValue(&m_lRed, &m_lGreen, &m_lBlue);
00338 
00339     
00340     // calculate the bounds of the entire image
00341     // init the mosaic list which stores all the parts of the image
00342 
00343     CList <CSlice *, CSlice *> MosaicList;
00344     MosaicList.RemoveAll();
00345 
00346     // the bounds of the drawing
00347     DocRect SpreadBounds = BaseBitmapFilter::GetSizeOfDrawing(pSelSpread); // returns in spread co-ords ignoring silly layers
00348     
00349     // get the selection
00350     Range Sel(*(GetApplication()->FindSelection()));
00351 
00352     // set the range flags so it includes shadow and bevel manager nodes
00353     RangeControl rg = Sel.GetRangeControlFlags();
00354     rg.PromoteToParent = TRUE;
00355     Sel.Range::SetRangeControl(rg);
00356     BOOL UseWholeDrawing = TRUE;
00357     
00358     // get the size of the selection
00359     // if there is a selection use this as the area to export rather than the drawing area
00360     // which we will use if there is no selection made
00361     if (!Sel.IsEmpty())
00362     {
00363         SpreadBounds = Sel.GetBoundingRect();
00364         UseWholeDrawing = FALSE;
00365     }
00366 
00367     PixelAlignedInflate(&SpreadBounds); // pixel align the starting rect
00368 
00369     // find the defined slices
00370     NameGallery* pNameGallery = NameGallery::Instance();
00371     SGUsedNames* pNames = pNameGallery?NameGallery->GetUsedNames():NULL;
00372 
00373     if (!pNames)
00374     {
00375         InformWarning( _R(IDS_NOSLICES) );
00376         //  Reset:
00377         BmapPrevDlg::m_bSlicingImage = FALSE;
00378         return;
00379     }
00380 
00381     // make sure we are dealing with the most uptodate information
00382     pNameGallery->FastUpdateNamedSetSizes();
00383 
00384     // for each defined slice in the name gallery
00385     BOOL NoProblems = TRUE;
00386     BOOL AddedASlice = FALSE;
00387     BOOL OutsideSpread = FALSE;
00388 
00389     INT32 Attempts = 0; // first try with the large rects then if that fails try the smaller ones
00390     String_256 strName(TEXT("Empty"));
00391     String_256 Slice1ErrorStr = "";
00392     String_256 Slice2ErrorStr = "";
00393     INT32 SlicesDefinedInDrawing = 0;
00394 
00395     do
00396     {
00397         NoProblems = TRUE;
00398         AddedASlice = FALSE;
00399         OutsideSpread = FALSE;
00400         SlicesDefinedInDrawing = 0;
00401 
00402         // the original mosaic piece is the whole bounded image
00403         // which will be broken up
00404         TidyMosaicList(&MosaicList);
00405         MosaicList.AddHead(new CSlice(SpreadBounds.lox, SpreadBounds.loy, SpreadBounds.hix, SpreadBounds.hiy));
00406 
00407         SGNameItem* pItem = (SGNameItem*) pNames->GetChild();
00408 
00409         while (pItem != 0 && NoProblems)
00410         {
00411             // is the tick set in the name gallery to use this slice?
00412             BOOL UseThisSlice = TRUE;
00413             NamedTickboxProp * pSliceTick = (NamedTickboxProp *) pItem->GetProperty(1); // 1 is slices
00414             if (pSliceTick)
00415             {
00416                 UseThisSlice = pSliceTick->GetState();
00417                 if (UseThisSlice)
00418                     SlicesDefinedInDrawing++;
00419             }
00420 
00421             // dont use an unselected slice if it is not the whole drawing being exported
00422             if (!UseWholeDrawing && pItem->IsNoneSelected())
00423                 UseThisSlice = FALSE;
00424 
00425             if (UseThisSlice)
00426             {
00427                 DocRect r;
00428                 r = pItem->GetSetBounds();          // (returned in spread co-ords)
00429 
00430                 pItem->GetNameText(&strName);
00431 
00432                 // expand for actual text story visible size
00433                 ScanTextStorySliceBounds(strName, r);
00434 
00435                 if (Attempts == 0)
00436                 {
00437                     DocRect rLarge = ScanLargeSliceBounds(strName);
00438                     r = r.Union(rLarge); // use the large rects
00439                 }
00440 
00441                 // r must be in the spread bounds
00442                 // if it is outside the bounds it should be ignored
00443                 PixelAlignedInflate(&r);        // pixel align the slice
00444 
00445                 // trim anything that just strays over the bounds
00446                 r = r.Intersection(SpreadBounds);
00447 
00448                 // cut the existing mosaic pieces by the edges of this new piece
00449                 // which of course creates even more pieces
00450                 if (r.IsValid() && r.Height() > 0 && r.Width() > 0)
00451                 {
00452                     NoProblems = NoProblems && AddSlice(r.lox, r.loy, r.hix, r.hiy, &MosaicList, strName);
00453                     AddedASlice = TRUE;
00454                 }
00455                 else
00456                 {
00457                     TRACEUSER( "SimonK", _T("Slice outside bounds of the drawing!!!\n"));
00458                 }
00459             }
00460 
00461             if (NoProblems) pItem = (SGNameItem*) pItem->GetNext();
00462         }
00463 
00464         Attempts++;
00465         if (!NoProblems)
00466         {
00467             Slice1ErrorStr = m_ErrorStr;
00468             Slice2ErrorStr = strName;
00469         }
00470 
00471     } while (!NoProblems && Attempts < 2); // try twice , first with the max size slices, then with the smaller slices
00472 
00473 /* Dont ask the question Asumme that the user will choose to have the shadows cut if they do overlap (sjk 20/12/00)
00474     if (Attempts == 2 && NoProblems && AddedASlice)
00475     {   // worked with the smaller rects but not with the larger ones
00476 
00477         // I need to force this message to reappear again if they click 'Help' - Matt 10/11/2000
00478         INT32 result = 3;
00479         while (result == 3)
00480         {
00481             result = AskQuestion(_R(IDS_SLICES_MAY_OVERLAP), _R(IDS_YES), _R(IDS_NO), _R(IDS_HELP));
00482             if (result == 2)
00483             {
00484                 NoProblems = FALSE; // it is a problem if you say it is
00485                 m_ErrorStr = Slice1ErrorStr; // restore the shapes that were causing problems for the first case
00486                 strName = Slice2ErrorStr;
00487             }
00488             if (result == 3)
00489             {
00490                 HelpUserTopic(_R(IDH_Alert_Exclude_peripheral_elements));
00491             }
00492         }
00493     }
00494 */
00495     POSITION Test = NULL;
00496 
00497     if (NoProblems && AddedASlice) 
00498     {
00499         // sort the mosaic using SortSlices()
00500         // it also merges small bits back together if it can
00501         SortSlices(&MosaicList, SpreadBounds);
00502 
00503         // mark which states exist
00504         m_FoundRolloverStates = ScanForRolloverStates(&MosaicList);
00505 
00506         BOOL ReplaceFiles = TRUE;
00507         BOOL FilesOverwriten = FALSE;
00508         do // loop to ask where to save to which may be asked more than once if they dont want
00509             // to overwrite files
00510         {
00511 
00512             // ask where to save the files
00513             // and find out which slice export type to use
00514             if (!SaveFileDlg())
00515             {
00516                 // tidy up and leave if cancelled
00517                 TidyMosaicList(&MosaicList);
00518                 Error::ClearError();
00519                 //  Reset:
00520                 BmapPrevDlg::m_bSlicingImage = FALSE;
00521                 return;
00522             }
00523 
00524 
00525             // cope with things being .html, which the BmapPrevDlg doesn't set correctly as its not 8.3
00526             String_256 temp = m_PathName.GetFileName(FALSE);
00527             INT32 dot = temp.FindNextChar(TCHAR ('.'));
00528             if (dot > 0)
00529             {
00530                 String_256 end = "";
00531                 temp.Split(&temp, &end, dot, FALSE);
00532                 if (end.CompareTo(".html", FALSE) == 0)
00533                 {
00534                     m_HTMLext = "html";
00535                     m_PathName.SetFileName(temp);
00536                 }
00537             }
00538 
00539             CString ClickedFile(temp);
00540             ClickedFile += "." + m_HTMLext;
00541 
00542             ReplaceFiles = FileExists(ClickedFile);
00543             FilesOverwriten = FALSE;
00544 
00545             if (!ReplaceFiles)
00546             {
00547                 // test if these names we are creating are already in existance
00548                 Test = MosaicList.GetHeadPosition();
00549                 while (Test && !FilesOverwriten)
00550                 {
00551                     CSlice* pTestSlice = MosaicList.GetNext(Test);
00552                     CString TestName (pTestSlice->name);
00553 
00554                     // we dont know exactly what file type for each element will be
00555                     // but it is best to warn the user that they may be overwriting their files
00556                     FilesOverwriten = FileExists(TestName + ".gif");
00557                     if (!FilesOverwriten) FilesOverwriten = FileExists(TestName + ".jpg");
00558                     if (!FilesOverwriten) FilesOverwriten = FileExists(TestName + ".jpeg");
00559                     if (!FilesOverwriten) FilesOverwriten = FileExists(TestName + ".png");
00560                     if (!FilesOverwriten) FilesOverwriten = FileExists(TestName + ".bmp");
00561                 }
00562             }
00563 
00564             if (FilesOverwriten && !ReplaceFiles)
00565             {
00566                 // ask the user "This folder contains a graphic file with a conflicting name.
00567                 // Do you want to overwrite any conflicting files in this folder?"
00568                 if (InformWarning(_R(IDS_CONFLICTING_SLICE_FILENAMES), _R(IDS_OVERWRITE_GRAPHIC), _R(IDS_SAVE_ELSEWHERE)) == 1)
00569                     ReplaceFiles = TRUE;
00570             }
00571 
00572         } while (FilesOverwriten && !ReplaceFiles); // end of overwrite loop
00573 
00574 
00575         // The preview dlg wants to know the path of the image being
00576         // exported so give it the m_PathName
00577         BmapPrevDlg::m_pthExport = m_PathName;
00578 
00579         // set up the export options
00580         BitmapExportOptions * pExportOptions = NULL;
00581         BOOL ok = TRUE;
00582 
00583         ShowRolloverLayer(ALL_LAYERS);
00584 
00585         // WARNING SetUpExportOptions() actually 'new's the ExportOptions
00586         // so you will have to delete them or pass them to a function
00587         // that deletes them for you
00588         String_256 strExt = m_PathName.GetType();
00589         strExt.toLower();
00590         if (strExt.CompareTo("jpg") == 0)
00591         {
00592             JPEGExportFilter f;
00593             ok = f.SetUpExportOptions(&pExportOptions);
00594         }
00595         else
00596         if (strExt.CompareTo("bmp") == 0)
00597         {
00598             BMPFilter f;
00599             ok = f.SetUpExportOptions(&pExportOptions);
00600         }
00601         else
00602         if (strExt.CompareTo("png") == 0)
00603         {
00604             PNGFilter f;
00605             ok = f.SetUpExportOptions(&pExportOptions);
00606         }
00607         else
00608         //if (strExt == "gif")
00609         {
00610             TI_GIFFilter f;
00611             ok = f.SetUpExportOptions(&pExportOptions);
00612         }
00613 
00614         // the export options may have changed types
00615         // so ask the export dlg for the actual export options
00616         pExportOptions = BmapPrevDlg::m_pExportOptions;
00617         // take responsibility for the export options away from the bmp preview dlg
00618         BmapPrevDlg::m_pExportOptions = 0;
00619 
00620         // Cancelled from the export options dlg
00621         if (!ok)
00622         {
00623             if (pExportOptions)
00624             {
00625                 delete pExportOptions;
00626             }
00627             // tidy up and leave
00628             TidyMosaicList(&MosaicList);
00629             Error::ClearError();
00630             //  Reset:
00631             BmapPrevDlg::m_bSlicingImage = FALSE;
00632             return;
00633         }
00634 
00635         // read the m_PathName back since
00636         // setting up the export options could
00637         // have changed this value
00638         m_PathName = BmapPrevDlg::m_pthExport;
00639 
00640 
00641         // clear the screen by calling an idle
00642         (DocView::GetSelected())->ForceRedraw();
00643         GetApplication()->OnIdle(TRUE);             // Phil 2/7/2004 YUK! What's wrong with ServiceRendering?
00644 
00645         // change the non-user defined slices to use the graphic type
00646         // just picked by the user in the SaveFileDlg
00647         UpdateSliceFileExts(&MosaicList);
00648 
00649         // mark any "empty" slices in the list
00650         // but not if we have a background bitmap
00651         if (!HasBitmapBackground)
00652             MarkEmptySlices(&MosaicList, SpreadBounds, pExportOptions);
00653 
00654         // export each section of the mosaic as a seperate graphic
00655         Test = MosaicList.GetHeadPosition();
00656         while (Test)
00657         {
00658             CSlice* pTestSlice = MosaicList.GetNext(Test);
00659 
00660             if (m_FoundRolloverStates && pTestSlice->IsNamedSlice)
00661                 // export this slice as a rollover
00662                 ExportRollOverSlice(pTestSlice, pExportOptions);
00663             else
00664                 // do a normal slice
00665             {
00666                 // only export the graphic for a none-empty slice
00667                 if (!pTestSlice->IsEmpty)
00668                     ExportSliceGraphic(pTestSlice, pExportOptions, pTestSlice->name);
00669             }
00670 
00671             // This function calls DoExportWithParams() which used to
00672             // delete the export options (and not zero the pointer - tusk!)
00673             // Behaviour now changed by using DontLetFilterDeleteMyPointer()
00674             // so we can keep using the same export options, but of course we
00675             // must then delete them ourselves.
00676         }
00677 
00678         // tidy up our generated export options
00679         if (pExportOptions != 0)
00680         {
00681             delete pExportOptions;
00682             pExportOptions = 0;
00683         }
00684 
00685         // And clean up the image export options in the bitmap dialogue.
00686 //      BmapPrevDlg::CancelTransparency ();
00687 
00688         // export the HTML to display the mosaic put back together
00689         // the name is that typed in but with the htm extension
00690 
00691         // build up the list of link names with each button
00692         // rather than just going on adding a number to the file
00693         // users want to not have to edit HTML, do it all for them!
00694         m_UsedShimGraphic = FALSE;
00695         PathName HTMLPath = m_PathName;
00696         HTMLPath.SetType(m_HTMLext);
00697         m_pLinkName = NULL;
00698         INT32 i = 0;
00699         String_256 LaunchString = HTMLPath.GetFileName();
00700 
00701         INT32 LinkEntries = max (m_NumberOfButtons, 1);
00702         m_pLinkName = new String_256[LinkEntries];
00703 
00704         if (m_pLinkName)
00705         {
00706             m_pLinkName[0] = HTMLPath.GetPath();
00707 
00708             INT32 FileNumber = 0;
00709             // fill the link names with default names if there are no URLs found
00710             for (i = 0; i < m_NumberOfButtons; i++)
00711             {
00712                 m_pLinkName[i] = m_PathName.GetFileName(FALSE);
00713 
00714                 CSlice * pTestSlice = GetButtonNumber (&MosaicList, i+1);
00715                 if (pTestSlice && pTestSlice->ExistsOnLayerState[SELECTED])
00716                 {
00717                     FileNumber++;
00718 
00719                     if (m_FoundRolloverStates && m_RolloverState[SELECTED].Exists && FileNumber > 1)
00720                     {
00721                         String_256 NewName;
00722                         NewName.MakeMsg(_R(IDS_HTML_NAME_SPEC), (LPCSTR) m_PathName.GetFileName(FALSE), FileNumber);
00723                         m_pLinkName[i] = NewName;
00724                     }
00725                 }
00726 
00727                 m_pLinkName[i] += ".";
00728                 m_pLinkName[i] += m_HTMLext;
00729             }
00730 
00731             // scan the tree for any URLs used associated with the buttons in the Mosaic list
00732             // this will overwrite the defaults already set in m_pLinkName
00733             URLScan(m_pLinkName, &MosaicList);
00734 
00735             FileNumber = 0;
00736 
00737             // export each HTML file required
00738             if (m_RolloverState[SELECTED].Exists)
00739                 for (i = 0; i < LinkEntries; i++)
00740                 {
00741                     String_256 NewName = m_pLinkName[i];
00742                     String_256 Temp = "";
00743 
00744                     // dont try to create a file http://www.stuff...
00745                     NewName.Left(&Temp,5);
00746                     BOOL isURL = (Temp.CompareTo("http:", FALSE) == 0);
00747                     if (!isURL)
00748                     {
00749                         NewName.Right(&Temp,1);
00750                         isURL = (Temp.CompareTo("/") == 0);
00751                     }
00752 
00753                     CSlice * pTestSlice = GetButtonNumber (&MosaicList, i+1);
00754                     if (pTestSlice && pTestSlice->ExistsOnLayerState[SELECTED])
00755                     {
00756                         FileNumber++;
00757 
00758                         if (isURL)
00759                         {
00760                             NewName.MakeMsg(_R(IDS_HTML_NAME_SPEC), (LPCSTR) m_PathName.GetFileName(FALSE), FileNumber);
00761                             NewName += ".";
00762                             NewName += m_HTMLext;
00763                         }
00764 
00765                         HTMLPath.SetPathName(NewName);
00766 
00767                         if (!ExportImageSliceHTML(&MosaicList, HTMLPath.GetPath(), i+1))
00768                             FailledToExportHTML (HTMLPath.GetPath());
00769 
00770                         // set file to launch if changed by the URL
00771                         if (FileNumber == 1)
00772                         {
00773                             LaunchString = HTMLPath.GetFileName();
00774                         }
00775                     }
00776 
00777                 }
00778             else
00779                 if (!ExportImageSliceHTML(&MosaicList, HTMLPath.GetPath()))
00780                     FailledToExportHTML (HTMLPath.GetPath());
00781 
00782             delete [] m_pLinkName;
00783             m_pLinkName = NULL;
00784         }
00785 
00786         // Export out the required shim
00787         if (m_UsedShimGraphic)
00788         {
00789             // also needs shim.gif exported
00790             // set up the path of where to save it
00791             PathName ShimPath = m_PathName;
00792 
00793             ShimPath.SetFileName("shim");
00794             ShimPath.SetType("gif");
00795 
00796             CCDiskFile File;
00797             if(File.open(ShimPath.GetPath(), (ios::in | ios::out | ios::binary)))
00798             {
00799                 BYTE buf[] =   {0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x01, 0x00,
00800                                 0x01, 0x00, 0x80, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
00801                                 0x00, 0x00, 0x00, 0x21, 0xF9, 0x04, 0x01, 0x14,
00802                                 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00,
00803                                 0x01, 0x00, 0x01, 0x00, 0x00, 0x02, 0x02, 0x44,
00804                                 0x01, 0x00, 0x3B, 0x00  };
00805 
00806                 // make the shim of the correct colour
00807                 buf[13] = (BYTE) m_lRed;
00808                 buf[14] = (BYTE) m_lGreen;
00809                 buf[15] = (BYTE) m_lBlue;
00810 
00811                 // write the file
00812                 File.write((BYTE *)buf, 44);
00813                 File.close();
00814             }
00815         }
00816         
00817         // display the export HTML now?
00818         if (m_ExportedHTMLOK && AskQuestion(_R(IDS_SHOW_HTML_NOW), _R(IDS_YES), _R(IDS_NO)) == 1)
00819         {
00820             // shell execute the browser
00821             HINSTANCE hChild = ShellExecute(HWND_DESKTOP, "open", LaunchString, NULL, NULL ,SW_SHOW);
00822 
00823             // If the function (ShellExecute()) fails, then an error value that is less than or equal to 32 is returned. 
00824             INT32 Result = (INT32)hChild;
00825             // problems?
00826             if (Result <= 32)
00827             {
00828                 InformWarning(_R(IDS_NO_BROWSER));
00829             }
00830         }
00831     
00832     }
00833     else if (!AddedASlice) // user forgot to define any slices
00834     {
00835         if (SlicesDefinedInDrawing == 0)
00836             InformWarning( _R(IDS_NOSLICES) );
00837         else
00838             InformWarning( _R(IDS_NOSLICES_SELECTED) );
00839     }
00840     else // some error occured such as intersecting named slices
00841     {
00842         if (OutsideSpread)
00843         {
00844             // An invisible slice is outside the bounds of the rendered spread
00845             InformWarning(_R(IDS_SLICE_OUT_OF_BOUNDS));
00846         }
00847         else
00848         {
00849             // should mention that it is pTestSlice->name that is overlapping       
00850             String_256 temp(TEXT(""));
00851             temp.MakeMsg(_R(IDS_SLICES_OVERLAP), (LPCTSTR) m_ErrorStr, (LPCTSTR) strName);
00852 
00853             ErrorInfo Info;
00854             Info.ErrorMsg = 0;
00855             Info.Button[0] = _R(IDS_OK);
00856             Info.Button[1] = _R(IDS_HELP);
00857             Info.OK = 1;
00858             Info.Help = 2;
00859             Info.Title = _R(IDBBL_IMAGESLICE);
00860 
00861             BOOL Again;
00862             do
00863             {
00864                 // Set the error message
00865                 Error::SetError( 0, temp, 0 );
00866 
00867                 Again = FALSE;
00868                 switch (AskQuestion(&Info))
00869                 {
00870                     case _R(IDS_HELP):
00871                         HelpUserTopic(_R(IDS_HELPPATH_Alert_Named_Objects_Overlap));
00872                         Again = TRUE;
00873                         break;
00874                 }
00875             } while (Again);
00876         }
00877     }
00878 
00879     // tidey up before leaving
00880     TidyMosaicList(&MosaicList);
00881 
00882     // end a slow job
00883     // done through the progress class being destroyed
00884 
00885     //  Reset:
00886     BmapPrevDlg::m_bSlicingImage = FALSE;
00887 }

BOOL OpSlice::ExportImageSliceHTML CList< CSlice *, CSlice * > *  pMosaicList,
const String_256 HTMLFile,
INT32  FileNumber = 1
[protected]
 

Creates an HTML file with a table that re-weaves the sliced images back together Also if rollovers have been defined they are also incorperated.

Author:
Simon_Knight (Xara Group Ltd) <camelotdev@xara.com>
Date:
23/7/99
Returns:
FALSE if some error occured SideEffect: On m_UsedShimGraphic to set it correctly - assuming it is FALSE to start with.

Definition at line 1749 of file slice.cpp.

01750 {
01751     BOOL InjectFile = m_InjectHTML;
01752 
01753     // varibales used in the inject file and reinject file modes
01754     BYTE * pPreviousHTML = NULL;
01755     DWORD PreviousHTMLSize = 0;
01756     BYTE * pHeadEnd = NULL;
01757     BYTE * pBodyStart = NULL;
01758     BYTE * pBodyStartAbsolute = NULL;
01759     BYTE * pNavDefStart = NULL;
01760     BYTE * pNavDefEnd = NULL;
01761     BYTE * pNavTableStart = NULL;
01762     BYTE * pNavTableEnd = NULL;
01763 
01764     // file doesn't exist? then we cant inject!
01765     CString tempFile(HTMLFile);
01766     if (InjectFile && !FileExists(tempFile))
01767         InjectFile = FALSE;
01768 
01769     if (InjectFile)
01770     {
01771         // read the previous file into memory and identify important locations within it
01772         pPreviousHTML = LoadFileIntoMemory(HTMLFile, PreviousHTMLSize);
01773         if (!pPreviousHTML)
01774             return FALSE;
01775 
01776         // find where the <head> tag finishes
01777         pHeadEnd = FindNextOccuranceOf((BYTE *)&"</head>", pPreviousHTML);
01778         if (!pHeadEnd)
01779             return FALSE;
01780 
01781         // find the navbar definition by looking for the marker comment
01782         // this will be in the header part inside the dummy javascript comment
01783         pNavDefStart = FindNextOccuranceOf((BYTE *)&"<!-- Navbar def -->", pPreviousHTML);
01784         if (pNavDefStart)
01785         {
01786             // find the end of the navbar definition by looking for the marker comment
01787             pNavDefEnd = FindNextOccuranceOf((BYTE *)&"<!-- Navbar def end -->", pNavDefStart);
01788             if (pNavDefEnd)
01789                 pNavDefEnd += 23;
01790         }
01791 
01792         // find where the <body> tag starts & ends
01793         pBodyStartAbsolute = FindNextOccuranceOf((BYTE *)&"<body", pHeadEnd);
01794         if (!pBodyStartAbsolute)
01795             return FALSE;
01796         pBodyStart = FindNextOccuranceOf((BYTE *)&">", pBodyStartAbsolute);
01797         if (!pBodyStart)
01798             return FALSE;
01799 
01800         // the table that holds the navbar is marked by having name tag of "XaraTable"
01801         // find this and the locate the start of the table tag
01802         pNavTableStart = FindNextOccuranceOf((BYTE *)&"name=\"XaraTable", pBodyStart);
01803         if (pNavTableStart)
01804         {
01805             BYTE * pTemp = FindPreviousChar('<', pNavTableStart, pBodyStart);
01806             BYTE * pTemp2 = FindNextOccuranceOf((BYTE *)&"<table", pTemp);
01807 
01808             if (pTemp == pTemp2) // is in start of <table>
01809             {
01810                 pNavTableStart = pTemp;
01811 
01812                 // find the end of the table tag
01813                 pNavTableEnd = FindNextOccuranceOf((BYTE *)&"</table>", pNavTableStart);
01814                 if (pNavTableEnd)
01815                     pNavTableEnd += 8;
01816             }
01817             else
01818                 pNavTableStart = NULL;
01819         }
01820     }
01821 
01822     // injecting HTML where we have injected before?
01823     // ie we have found the markers and can just replace these bits of code
01824     BOOL ReInject = pNavTableEnd ? TRUE : FALSE;
01825 
01826     // open the file to output the HTML
01827     ofstream f(HTMLFile);
01828     if ( !f.is_open() )
01829     {
01830         return FALSE;
01831     }
01832 
01833     POSITION pos = 0;
01834 
01835     if (ReInject)
01836     {
01837         // write the stuff till the start navbar marker
01838         if (pNavDefEnd)
01839             WriteText (f, pPreviousHTML, pNavDefStart - pPreviousHTML);
01840     }
01841     else
01842     {
01843         if (InjectFile)
01844         {
01845             // write everything in the file up to the <\head>
01846             WriteText(f, pPreviousHTML, pHeadEnd - pPreviousHTML);
01847         }
01848         else
01849         {
01850             // export HTML
01851             f << "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 transitional//EN\">\n";
01852             f << "<html>\n<head>\n";
01853             f << "<title>Sliced Image</title>\n";
01854         }
01855     }
01856 
01857     // any javascript images go in here
01858 
01859     if (m_FoundRolloverStates)
01860     {
01861         // add the start java button marker
01862         f << "<!-- Navbar def -->\n";
01863 
01864         f << "<script language=\"JavaScript\">\n";
01865         f << "<!-- Dummy comment to hide code from non-JavaScript browsers.\n\n";
01866         f << "if (document.images) {\n";
01867 
01868         // iterate throught the slices for named slices to add their images to the document
01869         pos = pMosaicList->GetHeadPosition();
01870         while (pos)
01871         {
01872             CSlice * pSlice = pMosaicList->GetNext(pos);
01873 
01874             if (pSlice->IsNamedSlice)
01875             {
01876                 for (INT32 i = 0; i < 3 ; i++) // not including SELECTED
01877                     if (m_RolloverState[i].Exists && pSlice->ExistsOnLayerState[i])
01878                     {
01879                         f << pSlice->name;
01880                         f << m_RolloverState[i].Name;
01881                         f << " = new Image(); ";
01882                         f << pSlice->name;
01883                         f << m_RolloverState[i].Name;
01884                         f << ".src = \"";
01885                         f << pSlice->name;
01886                         if (i > 0 && m_RolloverState[i].Exists)
01887                             f << m_RolloverState[i].Name;
01888 
01889                         f << "." << pSlice->FileTypeExtStr;
01890                         f << "\"\n";
01891                     }
01892             }
01893         }
01894         f << "}\n\n";
01895 
01896         // set up the list of graphics
01897         for (INT32 n = 0; n < 3; n++) // not including selected
01898             if (m_RolloverState[n].Exists)
01899             {
01900                 f << "function turn" << m_RolloverState[n].Name;
01901                 f << "(ImageName) {\n";
01902                 f << "\tif (document.images != null) {\n";
01903                 f << "\t\tdocument[ImageName].src = eval(ImageName + \"";
01904                 f << m_RolloverState[n].Name;
01905                 f << ".src\");\n\t}\n";
01906                 //if (n == CLICKED)
01907                 //  f << "return true;\n";
01908                     
01909                 f << "}\n\n";
01910             }
01911 
01912         f << "// End of dummy comment -->\n";
01913         f << "</script>\n";
01914         // mark the end of the java script buttons def
01915         f << "<!-- Navbar def end -->\n";
01916 
01917     } // end of m_FoundRolloverStates - adding rollover start javascript
01918 
01919 
01920     if (ReInject)
01921     {
01922             // write the stuff between the end of the navr bar def and
01923             // the begining of the table
01924         if (pNavDefEnd)
01925             WriteText(f, pNavDefEnd, pNavTableStart - pNavDefEnd);
01926         else
01927             // write the stuff from the begining of the old file to the table start marker
01928             WriteText(f, pPreviousHTML, pNavTableStart - pPreviousHTML);
01929     }
01930     else
01931     {
01932 
01933         f << "</head>\n\n";
01934 
01935         if (InjectFile)
01936         {
01937             // recover the exisitng body tag
01938             WriteText(f, pBodyStartAbsolute, pBodyStart - pBodyStartAbsolute + 1);
01939         }
01940         else
01941         {
01942             // set body tag something like this
01943             f << "<body bgcolor=\"";
01944 
01945             char col[8];
01946             wsprintf(col, "#%02x%02x%02x", (BYTE) m_lRed, (BYTE) m_lGreen, (BYTE) m_lBlue);
01947             f << col;
01948 
01949             f << "\" text=\"";
01950 
01951             // sort out the text colour
01952             if (m_lRed + m_lGreen + m_lBlue < 300)
01953                 f << "white";
01954             else
01955                 f << "black";
01956                 
01957             // set the rest of the body tag
01958             f << "\" link=\"red\" vlink=\"blue\" alink=\"yellow\">\n";
01959         }
01960     }
01961 
01962     // Sliced images are set into a table
01963     f << "<table name=\"XaraTable\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\">\n\n";
01964 
01965     BOOL RequireEndOfRowShims = FALSE;
01966     BOOL RequireShimRow = FALSE;
01967     pos = pMosaicList->GetHeadPosition();
01968     while (pos)
01969     {
01970         CSlice * pSlice = pMosaicList->GetNext(pos);
01971         if (pSlice->rowspan > 1)
01972             RequireEndOfRowShims = TRUE;
01973         if (pSlice->colmspan > 1)
01974             RequireShimRow = TRUE;
01975     }
01976 
01977     // add a shim row if there is any colm spanning
01978     if (RequireShimRow)
01979     {
01980         BOOL AddedShimRow = FALSE;
01981         pos = pMosaicList->GetHeadPosition();
01982         INT32 shimcolm = 2; // they are all out of sinc by one so start at 2!?!
01983                             // never mind they only have to be (nearly) all there and in order
01984         while (pos)
01985         {
01986             CSlice * pSlice = pMosaicList->GetNext(pos);
01987 
01988             if (pSlice->colm == shimcolm)
01989             {
01990                 // add the shim row if required and we found something to put in it
01991                 if (!AddedShimRow)
01992                 {
01993                     f << "<!-- shim row--><tr>";
01994                     AddedShimRow = TRUE;
01995                 }
01996 
01997                 // output the HTML for the shim
01998                 f << "<td><img src=\"shim.gif\" width=\"" << pSlice->colmwidth/750 << "\" height=\"1\" border=\"0\"></td>\n";
01999                 shimcolm++;
02000                 m_UsedShimGraphic = TRUE;
02001                 // start looking for the next colm width from the begining of the list
02002                 // since the x co-ord is not ordered directly through the list
02003                 pos = pMosaicList->GetHeadPosition();