BOOL FreeHandEPSFilter::PrepareToImport() { if(!EPSFilter::PrepareToImport()) return FALSE; // set some nice variables HadhToken = FALSE; DoingGradFill = FALSE; OldFill = 0; InColours = FALSE; InText = FALSE; ComplexPathMode = FALSE; pLastPathSeen = 0; // set the clipping flags ClipRegion.SetClippingFlags(2); // get an importedcolours object pNewColours = new ImportedColours(pColours, FALSE); if(pNewColours == 0 || !pNewColours->Init()) return FALSE; // get a colour array ColourArray = (IndexedColour **)CCMalloc(FHEF_COLOURARRAY_INITIALSIZE * sizeof(IndexedColour *)); if(ColourArray == 0) { delete pNewColours; pNewColours = 0; return FALSE; } ColourArrayEntries = 0; ColourArraySize = FHEF_COLOURARRAY_INITIALSIZE; return TRUE; }
BOOL TrapsList::ExpandArray(void) { // Work out how many entries to allocate. // Each item is small, so we allocate a reasonably large number // Note that potential implementation of dashed lines could create a lot of // TrapEdgeLists (one per dash), so we need lots of spare capacity to cope // with this situation. I've therefore erred on the generous side. const INT32 AllocSize = CurrentSize + 64; if (pTraps == NULL) { // We have no array yet, so allocate one pTraps = (TrapEdgeList **) CCMalloc(AllocSize * sizeof(TrapEdgeList *)); if (pTraps == NULL) return(FALSE); } else { // We have an array - we must make it larger TrapEdgeList **pNewBuf = (TrapEdgeList **) CCRealloc(pTraps, AllocSize * sizeof(TrapEdgeList *)); if (pNewBuf == NULL) return(FALSE); pTraps = pNewBuf; } // Success. Update the current size value CurrentSize = AllocSize; // Initialise the pointers to safe values for (UINT32 Index = Used; Index < CurrentSize; Index++) pTraps[Index] = NULL; return(TRUE); }
BOOL GuidesPropertiesTab::DeleteClicked() { INT32* pIndexList = pPropertiesDlg->GetSelectedItems(_R(IDC_GUIDETAB_GUIDELINELIST)); INT32 Count = GuidelineList.GetCount(); INT32 i; BOOL ok = (pIndexList != NULL && Count > 0); NodeGuideline** pGuidelineList = NULL; if (ok) { pGuidelineList = (NodeGuideline**)CCMalloc(sizeof(NodeGuideline*)*(Count+1)); ok = (pGuidelineList != NULL); if (ok) { for (i=0; (pIndexList[i] >= 0) && (i < Count);i++) { GuidelineListItem* pItem = (GuidelineListItem*)GuidelineList.FindItem(pIndexList[i]); if (pItem != NULL) pGuidelineList[i] = pItem->pGuideline; else { pGuidelineList[i] = NULL; ERROR3_PF(("List item at index [%d] is NULL",i)); } } pGuidelineList[i] = NULL; } } else ok = FALSE; if (ok) { OpDescriptor* pOpDesc = OpDescriptor::FindOpDescriptor(OPTOKEN_GUIDELINE); ERROR3IF(pOpDesc == NULL,"FindOpDescriptor(OPTOKEN_GUIDELINE) failed"); if (pOpDesc != NULL) { OpGuidelineParam GuidelineParam; GuidelineParam.Method = GUIDELINEOPMETHOD_DELETE; GuidelineParam.pGuidelineList = pGuidelineList; pOpDesc->Invoke(&GuidelineParam); } } if (pGuidelineList != NULL) CCFree(pGuidelineList); if (pIndexList != NULL) delete [] pIndexList; return ok; }
BOOL SGThumbs::InitThumbnails(SGLibType Type, SGThumbSize Size) { // Read in value for MaxThumbnails here // MaxThumbnails = 10; // GetApplication()->DeclareSection(TEXT("Libraries"), 6); // GetApplication()->DeclarePref(TEXT("Libraries"), TEXT("Thumbnails"), &MaxThumbnails, 1, 100); Entries = MaxThumbnails; Thumbnails = (struct TN*)CCMalloc(sizeof(struct TN) * Entries); if(Thumbnails != NULL) { INT32 i; ThumbnailsLibType = Type; ThumbnailsSize = Size; for(i=0; i<Entries; i++) { Thumbnails[i].ID = 0; Thumbnails[i].Usage = 0; Thumbnails[i].Valid = FALSE; Thumbnails[i].Size = ThumbnailsSize; Thumbnails[i].buffer = NULL; } ThumbnailsInitialised = TRUE; return TRUE; } else { ThumbnailsInitialised = TRUE; return FALSE; } }
BOOL RIFFFile::GetListContents(ADDR *Block, INT32 *Size) { ERROR2IF(ObjType != RIFFOBJECTTYPE_LISTSTART, FALSE, "Tried an GetListContents on a non-list start RIFF object\n"); // OK, first thing we need to do is to get the list's header... where is it? INT32 StartLocation = Location - sizeof(RIFFck) - sizeof(RIFFFile_List); // seek there if(File->seek(StartLocation).bad()) { RIFFFILE_RETURNERR; } // OK, get the chunk header (not the list header which gives it's type RIFFck ChunkHeader; if(File->read(&ChunkHeader, sizeof(ChunkHeader)).bad()) { RIFFFILE_RETURNERR; } // right then, we now know how much data we need to extract from the file... INT32 ContentsSize = RIFFDATA_DWORD(ChunkHeader.ckSize) + sizeof(RIFFck); // now we need a block of data to get it into ADDR Contents = (ADDR)CCMalloc(ContentsSize); if(Contents == 0) return FALSE; // and getting it would be a cunning plan! seek to the beginning if(File->seek(StartLocation).bad()) { RIFFFILE_RETURNERR; } // grab the data if(File->read(Contents, ContentsSize).bad()) { RIFFFILE_RETURNERR; } // seek back to the location we were at the beginning if(File->seek(Location).bad()) { RIFFFILE_RETURNERR; } // and set up the return values *Block = Contents; *Size = ContentsSize; return TRUE; }
BOOL BlendHelpers::ReallocTempBuffers(UINT32 Size) { DeallocTempBuffers(); // Allocate the arrays m_TempArraySize = Size; m_pTempCoords = (DocCoord*) CCMalloc(Size*sizeof(DocCoord)); m_pTempVerbs = (PathVerb*) CCMalloc(Size*sizeof(PathVerb)); m_pTempFlags = (PathFlags*) CCMalloc(Size*sizeof(PathFlags)); // If any of the arrays are not allocated, dealloc the alloced ones, and return FALSE if (m_pTempCoords == NULL || m_pTempVerbs == NULL || m_pTempFlags == NULL) { DeallocTempBuffers(); return FALSE; } // It's all OK, so return TRUE return TRUE; }
BOOL RenderStack::GrowStack() { INT32 FirstNewItem = 0; if (TheStack == NULL) { // Try to allocate initial memory block for the stack. TheStack = (AttributeRec *) CCMalloc(InitialStackSize * ITEM_SIZE); // Complain and return if it didn't work. if (TheStack == NULL) return FALSE; // Update stack limit to reflect new size StackLimit = InitialStackSize; } else { // if (IsUserName("Tim")) // TRACE( _T("Growing heap from %d to %d entries\n"), // StackLimit, StackLimit + StackGranularity); // Increase the stack allocation AttributeRec *NewStack = (AttributeRec *) CCRealloc(TheStack, (StackLimit + StackGranularity) * ITEM_SIZE); // Complain if no more memory if (NewStack == NULL) return FALSE; // Otherwise use this new block TheStack = NewStack; // Make sure only new items are initialised FirstNewItem = StackLimit; // Update stack limit to reflect new size StackLimit += StackGranularity; } // Initialise the stack elements for (UINT32 i = FirstNewItem; i < StackLimit; i++) { TheStack[i].pAttrValue = NULL; TheStack[i].ContextLevel = 0; TheStack[i].Temporary = FALSE; } // Return success return TRUE; }
LPVOID TunedMemory::LimitedCCMalloc(size_t Size) { // Get some ram LPVOID Memory = CCMalloc(Size); // if we got it, make a note of its allocation if ((Memory!=NULL) && (!IsInfinite)) { AvailableRAM -= Size; } // return what we got return Memory; }
UINT32* BlendHelpers::GetGBlendBuff(UINT32 MinSize) { MinSize++; if (m_GBlendBuffSize >= MinSize) return m_pGBlendBuff; if (m_pGBlendBuff != NULL) CCFree(m_pGBlendBuff); m_pGBlendBuff = (UINT32*) CCMalloc(MinSize*sizeof(UINT32)); if (m_pGBlendBuff != NULL) m_GBlendBuffSize = MinSize; else m_GBlendBuffSize = 0; return m_pGBlendBuff; }
BOOL RIFFFile::EnsureAquiredSizeIsAtLeast(INT32 Size) { if(AquiredData == 0 || AquiredDataSize < Size) { if(AquiredData != 0) { CCFree(AquiredData); AquiredData = 0; } if((AquiredData = (BYTE *)CCMalloc(Size)) == 0) RIFFFILE_RETURNERR; AquiredDataSize = Size; } return TRUE; }
BOOL TrapEdgeList::ExpandArray(void) { // Work out how many entries to allocate. Note that I use a fairly large number // so that we don't have to reallocate the array very often. Each structure is // small, so the memory usage is fairly low, although it must be noted that // a dashed line could potentially generate quite a pile of these lists! INT32 AllocSize = CurrentSize + 512; if (pParentList != NULL && pParentList->GetRepeatLength() > 0) { // If it's a repeating stroke, then we must be far more careful about memory usage! // (i.e. if there are 1000 repeats along a stroke, each taking 15kB, we'll eat 15MB!) // We assume that repeats are small and hence will not need very many entries, and // then if (and only if) we find we have to realloc to make the array bigger, we jump // in bigger steps. if (CurrentSize == 0) AllocSize = CurrentSize + 4; else AllocSize = CurrentSize + 16; } if (pEdges == NULL) { // We have no array yet, so allocate one pEdges = (TrapEdge *) CCMalloc(AllocSize * sizeof(TrapEdge)); if (pEdges == NULL) return(FALSE); } else { // We have an array - we must make it larger TrapEdge *pNewBuf = (TrapEdge *) CCRealloc(pEdges, AllocSize * sizeof(TrapEdge)); if (pNewBuf == NULL) return(FALSE); pEdges = pNewBuf; } // Success. Update the current size value CurrentSize = AllocSize; return(TRUE); }
LPVOID MemoryBlock::Init( INT32 InitSize, BOOL bAutoZero, MemoryBlockType Type ) { #if USE_STD_ALLOC m_RoundedSize = GetRoundedSize( InitSize ); // now physically grab the starting size LPVOID pNewPtr; if( bAutoZero ) { pNewPtr = CCMalloc( m_RoundedSize ); memset(pNewPtr, 0, m_RoundedSize); } else { pNewPtr = CCMalloc( m_RoundedSize ); } if( pNewPtr == NULL ) { TRACEUSER( "Andy", wxT("malloc() failed because %lx\n"), errno ); return NULL; } TRACEUSER( "Andy", wxT("malloc OK at %p\n"), pNewPtr ); m_pMemBlk = pNewPtr; return pNewPtr; #elif USE_VM_BLOCKS // first time we are called get the page size if (PageSize==0L) { SYSTEM_INFO SysInfo; GetSystemInfo( &SysInfo ); PageSize = SysInfo.dwPageSize; } // Note that the Virtual API always gives us zeroed memory whether we want it or not // calculate a suitable maximum size for the type of block INT32 LargestSize; switch (Type) { case MEMORYBLOCK_HANDLETABLE: LargestSize = 0x01000000; // 16M of handles is enough break; case MEMORYBLOCK_RELOCHEAP: LargestSize = 0x10000000; // 256M of reloc heap break; case MEMORYBLOCK_SCREENBUFFER: LargestSize = 0x01000000; // 1024x768x32bits x4 for good measure break; default: ENSURE( FALSE, "Bad type in MemoryBlock::Init"); return NULL; } // firstly reserve a gratuitously large chunk of address space MemBase = VirtualAlloc( NULL, LargestSize, MEM_RESERVE, PAGE_NOACCESS ); if (MemBase==NULL) { TRACEUSER( "Andy", wxT("VirtualAlloc(reserve) failed because %lx\n"), GetLastError() ); return NULL; } RoundedSize = GetRoundedSize( InitSize ); // now physically grab the starting size LPVOID NewPtr = VirtualAlloc( MemBase, RoundedSize, MEM_COMMIT, PAGE_READWRITE ); if (NewPtr==NULL) { TRACEUSER( "Andy", wxT("VirtualAlloc(commit) failed because %lx\n"), GetLastError() ); VirtualFree(MemBase, 0L, MEM_RELEASE ); MemBase = NULL; return NULL; } TRACEUSER( "Andy", wxT("VirtualAlloced OK at %lx from %lx\n"), NewPtr, MemBase ); return NewPtr; #else #ifndef WIN32 if (InitSize > MAX_BLOCK) return NULL; #endif AutoZero = bAutoZero; // remember flag in struct UINT32 Flags = GMEM_MOVEABLE; if (AutoZero) Flags |= GMEM_ZEROINIT; MemHandle = GlobalAlloc( Flags, InitSize ); TRACE( wxT("GlobalAlloc %u %lx returned %x\n"), Flags, InitSize, (INT32)MemHandle); if (MemHandle==NULL) return NULL; LPVOID Ptr = GlobalLock( MemHandle ); if (Ptr == NULL) { GlobalFree( MemHandle ); MemHandle = 0; return NULL; } return Ptr; #endif }
void OpAlign::DoWithParam(OpDescriptor* pOp, OpParam* pAlignParam) { // DMc alterations so that this works with compound nodes SelRange Selection(*(GetApplication()->FindSelection())); RangeControl rg = Selection.GetRangeControlFlags(); rg.PromoteToParent = TRUE; Selection.Range::SetRangeControl(rg); DocRect SelRect = Selection.GetBoundingRect(); DocRect TargetRect; TargetRect.MakeEmpty(); INT32 NumObjs = Selection.Count(); AlignParam* pAlign =(AlignParam*)pAlignParam; BOOL moved=FALSE; // set to TRUE if any object is moved BeginSlowJob(-1,FALSE); BOOL OK=DoStartTransOp(FALSE); // find parent spread of first object in selection Node* pFirstNode=NULL; Spread* pSpread =NULL; if (OK) { pFirstNode=Selection.FindFirst(); if (pFirstNode!=NULL) pSpread=pFirstNode->FindParentSpread(); OK=(pSpread!=NULL); if (!OK) ERROR2RAW("OpAlign::DoWithParam() - could not find parent spread"); } // Find the size of the target rectangle if (pAlign->target==ToSelection) TargetRect=SelRect; else { Page* pPage=pSpread->FindFirstPageInSpread(); while (pPage) { DocRect PageRect=pPage->GetPageRect(); if (pAlign->target==ToSpread || SelRect.IsIntersectedWith(PageRect)) TargetRect=TargetRect.Union(PageRect); pPage=pPage->FindNextPage(); } } // allocate all dynamic memory required Node** pObj=NULL; ObjInfo* x =NULL; ObjInfo* y =NULL; INT32* dx =NULL; INT32* dy =NULL; if (OK) ALLOC_WITH_FAIL(pObj,(Node**) CCMalloc(NumObjs*sizeof(Node*)), this); if (pObj!=NULL) ALLOC_WITH_FAIL(x, (ObjInfo*)CCMalloc(NumObjs*sizeof(ObjInfo)),this); if ( x!=NULL) ALLOC_WITH_FAIL(y, (ObjInfo*)CCMalloc(NumObjs*sizeof(ObjInfo)),this); if ( y!=NULL) ALLOC_WITH_FAIL(dx, (INT32*) CCMalloc(NumObjs*sizeof(INT32)), this); if ( dx!=NULL) ALLOC_WITH_FAIL(dy, (INT32*) CCMalloc(NumObjs*sizeof(INT32)), this); OK=(dy!=NULL); // if memory claimed OK and target rect not empty proceed with op // (ie. do nothing if 'within page(s)' when no object on a page) DocRect EmptyRect; if (OK && TargetRect!=EmptyRect) { // create an array of pointers to objects (nodes) to be affected Node* pNode=Selection.FindFirst(); INT32 i=0; while (pNode!=NULL) { if (pNode->IsBounded() && !((NodeRenderableBounded*)pNode)->GetBoundingRect(TRUE).IsEmpty()) pObj[i++]=pNode; pNode=Selection.FindNext(pNode); } NumObjs=i; // cache x & y info in separate arrays so they can be sorted separately XLONG SumObjWidths =0; XLONG SumObjHeights=0; for (i=0; i<NumObjs; i++) { DocRect ObjRect=((NodeRenderableBounded*)pObj[i])->GetBoundingRect(); x[i].i=i; x[i].lo=ObjRect.lo.x; x[i].hi=ObjRect.hi.x; SumObjWidths+=ObjRect.hi.x-ObjRect.lo.x; y[i].i=i; y[i].lo=ObjRect.lo.y; y[i].hi=ObjRect.hi.y; SumObjHeights+=ObjRect.hi.y-ObjRect.lo.y; } // for each object, calculate the x and y displacements independently AlignOneAxis(pAlign->h,NumObjs,SumObjWidths, TargetRect.lo.x,TargetRect.hi.x,x,dx); AlignOneAxis(pAlign->v,NumObjs,SumObjHeights,TargetRect.lo.y,TargetRect.hi.y,y,dy); // apply the x and y displacements simultaneously to each object for (i=0; i<NumObjs; i++) if (dx[i]!=0 || dy[i]!=0) { moved=TRUE; Trans2DMatrix* pMatrix=new Trans2DMatrix(dx[i],dy[i]); DoTransformNode((NodeRenderableInk*)pObj[i],pMatrix); } } // free up any memory which was allocated CCFree(dx); CCFree(dy); CCFree(x); CCFree(y); CCFree(pObj); if (moved) { Document::GetSelected()->ForceRedraw(pSpread, TargetRect); GetApplication()->UpdateSelection(); } else FailAndExecute(); End(); EndSlowJob(); }
void *camelot_png_malloc(png_structp png_ptr, png_size_t size) { return (CCMalloc(size)); }
BOOL OutputPNG::StartFile( LPBITMAPINFOHEADER lpHeader, LPLOGPALETTE Palette, UINT32 OutputDepth, DWORD CompressionType, UINT32 FinalHeight, INT32 ExportSize, UINT32 DitherType ) { TRACEUSER( "Jonathan", _T("PNG write: Start\n")); ERROR2IF( lpHeader==NULL , FALSE, "OutputPNG::StartFile NULL lpHeader"); // Set up memory pointers to NULL if (DestBitmapInfo && DestBitmapBytes) { FreeDIB( DestBitmapInfo, DestBitmapBytes ); DestBitmapInfo = NULL; DestBitmapBytes = NULL; } // DestBitmapInfo = NULL; // DestBitmapBytes = NULL; if (OutputPalette) { CCFree(OutputPalette); OutputPalette = NULL; } // OutputPalette = NULL; IsFirstStrip = TRUE; HeightWritten = 0; // remember input args BitmapInfo = *lpHeader; // take a copy of user's header CurrentExportSize = ExportSize; // size set up for the progress bar HeightWanted = FinalHeight; // the actual height of the export required Dither = DitherType; // We will need to have the entire image present before writing out so that we can // cope with interlacing and transparency, so create that DIB // Set up the information header for the dib which we hold during export UINT32 LineWidth = DIBUtil::ScanlineSize( BitmapInfo.biWidth, OutputDepth ); INT32 PalSize = 0; BOOL ok = SetUpInfoHeader(lpHeader, OutputDepth, CompressionType, LineWidth, FinalHeight, &PalSize); // Claim memory for the bitmap if (ok) { DestBitmapInfo = AllocDIB( BitmapInfo.biWidth, FinalHeight, OutputDepth, &DestBitmapBytes ); ok = (DestBitmapInfo != NULL) && (DestBitmapBytes != NULL); } // Transfer across the required other bits of info if (ok) { DestBitmapInfo->bmiHeader.biXPelsPerMeter = BitmapInfo.biXPelsPerMeter; DestBitmapInfo->bmiHeader.biYPelsPerMeter = BitmapInfo.biYPelsPerMeter; DestBitmapInfo->bmiHeader.biClrUsed = PalSize; } // Point the place to put the next strip of data at the start ready for the first strip pNextStrip = DestBitmapBytes; // Take a copy of the palette if (ok && PalSize && Palette) { const size_t TotalPal = sizeof(LOGPALETTE) + ( sizeof(PALETTEENTRY) * PalSize ); OutputPalette = (LPLOGPALETTE)CCMalloc( TotalPal ); if (OutputPalette != NULL) memcpy( OutputPalette, Palette, TotalPal ); else ok = FALSE; } // Clean up if an error happened if (!ok) { // Free up the DIB that we have just created FreeDIB( DestBitmapInfo, DestBitmapBytes ); DestBitmapInfo = NULL; DestBitmapBytes = NULL; if (OutputPalette != NULL) { CCFree(OutputPalette); OutputPalette = NULL; } } return ok; }
BOOL OutputPNG::WriteBlock( UINT32 YPos, UINT32 Height, LPBYTE BlockStart, UINT32 InputBPP, INT32 ProgressOffset) { ERROR2IF(DestBitmapInfo == NULL, FALSE,"OutputPNG::WriteBlock destination bitmap info null"); ERROR2IF(DestBitmapBytes == NULL, FALSE,"OutputPNG::WriteBlock destination bitmap bits null"); ERROR2IF(pNextStrip == NULL, FALSE,"OutputPNG::WriteBlock next strip pointer is null"); FNPTR_SCANLINE ConvertFn = NULL; LPBYTE Buffer = NULL; size_t BufSize = 0L; size_t ChunkHeight = 1; DIBConvert *DoConvert = NULL; // Set up the size and other information for the dib block that we require. This is // dependent on the export depth or bpp required. if ( !SetUpBlock( &BufSize, &ChunkHeight, &DoConvert, &ConvertFn ) ) return FALSE; // Error details already set up if (BufSize) { Buffer = (LPBYTE)CCMalloc( BufSize ); if (Buffer==NULL) return FALSE; } if ( DoConvert ) { // use new classes to do it // 8bpp, 4bpp and 1bpp conversion INT32 h = Height; INT32 count = 0; LPBYTE Data = BlockStart; const size_t SourceWidth = DIBUtil::ScanlineSize( BitmapInfo.biWidth, InputBPP ) * ChunkHeight; const size_t DestWidth = DIBUtil::ScanlineSize( BitmapInfo.biWidth, BitmapInfo.biBitCount ); while (h) { ENSURE(h >= 0, "bad looping"); const size_t ThisBit = min( h, (INT32)ChunkHeight ); if (!DoConvert->Convert( Data, Buffer, ThisBit, IsFirstStrip )) break; // stop if conversion failed IsFirstStrip = FALSE; // Copy this block to our destination bitmap // pNextStrip should be pointing at the next place to copy the data to memcpy(pNextStrip, Buffer, ThisBit * DestWidth); Data += SourceWidth; h -= ThisBit; pNextStrip += ThisBit * DestWidth; // now update the progress display, started with CurrentExportSize // CurrentExport size is now the point to go from in the export count++; ContinueSlowJob( (INT32)(ProgressOffset + count) ); //ContinueSlowJob( (INT32)(100*count/(Height)) ); } } else if ( ConvertFn && Buffer ) { // Write via conversion function // 24 bpp convert UINT32 h = Height; INT32 count = 0; LPBYTE Data = BlockStart; const size_t SourceWidth = DIBUtil::ScanlineSize( BitmapInfo.biWidth, InputBPP ); while (h) { ConvertFn( BitmapInfo.biWidth, Data, Buffer ); // Copy this block to our destination bitmap // pNextStrip should be pointing at the next place to copy the data to memcpy(pNextStrip, Buffer, BufSize); Data += SourceWidth; h -= ChunkHeight; pNextStrip += BufSize; // now update the progress display, started with CurrentExportSize // ProgressOffset size is now the point to go from in the export count++; ContinueSlowJob( (INT32)( ProgressOffset + count )); //ContinueSlowJob( (INT32)((CurrentExportSize * count)/Height) ); } } else { // Write the actual bytes out to file. Used to do it in one go but we really // require some progress bar indication so we will do it in chunks. DWORD BitsSize = BitmapInfo.biSizeImage; if (BitsSize > 0) { if (BitsSize < 1024) { // File very small or no progress bar required, so load in one go // Copy this block to our destination bitmap // pNextStrip should be pointing at the next place to copy the data to memcpy(pNextStrip, BlockStart, BitsSize); pNextStrip += BitsSize; } else { // Load in chunks, for present split into 100 chunks DWORD ChunkSize = BitsSize/100; DWORD Position = 0; LPBYTE pBitInfo = BlockStart; while (Position < BitsSize) { if ( (BitsSize - Position) > ChunkSize) { // Copy this block to our destination bitmap // pNextStrip should be pointing at the next place to copy the data to memcpy(pNextStrip, pBitInfo, ChunkSize); } else { ChunkSize = BitsSize - Position; // Copy this block to our destination bitmap // pNextStrip should be pointing at the next place to copy the data to memcpy(pNextStrip, pBitInfo, ChunkSize); } // Increment our counters/pointers Position+=ChunkSize; pBitInfo+=ChunkSize; pNextStrip += ChunkSize; // Progress bar started with height of bitmap ContinueSlowJob( (INT32)(ProgressOffset + (Height * Position)/BitsSize) ); //ContinueSlowJob( (INT32)((CurrentExportSize * Position)/BitsSize) ); } } } } // If present, get rid of our export function if (DoConvert) { delete DoConvert; DoConvert = NULL; } CCFree( Buffer ); HeightWritten += Height; // remember we wrote this lot return TRUE; }
BOOL OutputDIB::StartFile( CCLexFile *File, LPBITMAPINFOHEADER lpHeader, LPLOGPALETTE Palette, UINT32 OutputDepth, DWORD CompressionType, UINT32 FinalHeight, INT32 ExportSize, BOOL SecondPass, UINT32 DitherType ) { // remember input args OutputFile = File; StartPos = OutputFile->tell(); // remember where in the file this starts BitmapInfo = *lpHeader; // take a copy of user's header OutputPalette = NULL; // our form of the palette, if required HeightWritten = 0; // our count of the bitmap lines written CurrentExportSize = ExportSize; // size set up for the progress bar HeightWanted = FinalHeight; // the actual height of the export required INT32 PalSize = 0; // how many entries in palette // Remember which dithering type to use Dither = DitherType; IsFirstStrip = TRUE; // Set up the information header for the dib if ( !SetUpInfoHeader(lpHeader, OutputDepth, CompressionType, FinalHeight, &PalSize) ) return FALSE; // SetError already called // BITMAPFILEHEADER goes first BITMAPFILEHEADER Header; Header.bfType = ('M'<<8) | 'B'; Header.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*PalSize + BitmapInfo.biSizeImage; Header.bfReserved1 = 0; Header.bfReserved2 = 0; Header.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*PalSize; OutputFile->write( &Header, sizeof(Header) ); // then a local BITMAPINFOHEADER OutputFile->write( &BitmapInfo, sizeof(BITMAPINFOHEADER) ); // then the RGBQUAD palette if (PalSize) { ERROR2IF(Palette == NULL,FALSE,"StartFile has a NULL Palette when one is required"); // make a copy of the palette for possible later use const size_t TotalPal = sizeof(LOGPALETTE) + ( sizeof(PALETTEENTRY) * PalSize ); OutputPalette = (LPLOGPALETTE)CCMalloc( TotalPal ); if (OutputPalette==NULL) return FALSE; // Take a copy of that palette memcpy( OutputPalette, Palette, TotalPal ); // write it to disk in RGBQUAD format RGBQUAD TempRGB; TempRGB.rgbReserved = 0; for (INT32 i=0; i<PalSize; i++) { TempRGB.rgbRed = OutputPalette->palPalEntry[i].peRed; TempRGB.rgbGreen = OutputPalette->palPalEntry[i].peGreen; TempRGB.rgbBlue = OutputPalette->palPalEntry[i].peBlue; OutputFile->write( &TempRGB, sizeof(RGBQUAD) ); } } return !OutputFile->bad(); }
BOOL GIFUtil::ReadFromFile( CCLexFile *File, LPBITMAPINFO *Info, LPBYTE *Bits, int *TransColour, int& nBitmapToRead, String_64 *ProgressString, BaseCamelotFilter *pFilter, UINT32* Delay, GIFDisposalMethod *Restore, UINT32 * pLeftOffset, UINT32 * pTopOffset, BOOL * pLocalPalette) { if ((nBitmapToRead > 1 && nBitmapToRead == m_nCurrentBitmap) || nBitmapToRead < 1) { ERROR3("GIFUtil::ReadFromFile() - can't read that bitmap"); return FALSE; } *Info = NULL; // in case of early exit *Bits = NULL; Transparent = -1; *TransColour = -1; // in case of early exit set to none int Background = 0; // background colour number !!! not used !!! Interlace = FALSE; // set interlace to false by default // Must set the exception throwing flag to True and force reporting of errors to False. // This means that the caller must report an error if the function returns False. // Any calls to CCLexFile::GotError will now throw a file exception and should fall into // the catch handler at the end of the function. BOOL OldThrowingState = File->SetThrowExceptions( TRUE ); BOOL OldReportingState = File->SetReportErrors( FALSE ); // If the caller has specified a string then assume they require a progress bar // Start it up. if (ProgressString != NULL) BeginSlowJob(100, FALSE, ProgressString); try { // If we want the first bitmap we'll assume we're at the start of the file & read the header if (nBitmapToRead == 1) { // place to store the global palette, if present, for later use lpGlobalPalette = NULL; // pointer to temporary palette store GlobalPaletteSize = 0; // size of the global palette found GIFINFOHEADER Header; // This is really sizeof(GIFINFOHEADER) but this returns 14 instead of 13 // as it rounds to the nearest word boundary const size_t HeaderSize = sizeof(char)* 6 + sizeof(WORD) * 2 + sizeof(BYTE) * 3; File->read( &Header, HeaderSize ); if (File->bad()) File->GotError( _R(IDE_FORMATNOTSUPPORTED) ); // Just double check that the signature is correct, if not then fail immediately if ( (strncmp(Header.giName, "GIF89a", 6) != 0) && (strncmp(Header.giName, "GIF87a", 6) != 0) ) File->GotError( _R(IDE_BADFORMAT) ); // Note the overall size of the GIF from the header, may be the animation size m_GlobalWidth = Header.giWidth; m_GlobalHeight = Header.giHeight; // flags word consists of:- // - bit 7 colour table flag = set if global colour table follows // - bits 6-4 colour resolution = bpps - 1 // - bit 3 sort flag = set global colour table sorted // - bits 3-0 size of global colour table = size is 2^(value+1) int ColorResolution = (((Header.giFlags >> 4) & 0x07) + 1); GlobalPaletteSize = 2 << (Header.giFlags & 0x07); Background = Header.giBackground; // int AspectRatio = Header.giAspect; TRACEUSER("Neville",_T("Gif Global Width = %d Height = %d\n"), m_GlobalWidth, m_GlobalHeight); TRACEUSER("Neville",_T("Gif ColorResolution = %d\n"), ColorResolution); // Check if we have a global colour map present or not, if so then read it in. if (BitSet(Header.giFlags, GLOBALCOLOURMAP)) { TRACEUSER("Neville",_T("Gif read global colour table size = %d\n"), GlobalPaletteSize); // Read in the global colour map into a palette structure for possible later use const size_t TotalPal = sizeof(RGBQUAD) * GlobalPaletteSize; lpGlobalPalette = (LPRGBQUAD)CCMalloc( TotalPal ); if (lpGlobalPalette==NULL) return FALSE; ReadColourMap(File, GlobalPaletteSize, lpGlobalPalette); } m_nCurrentBitmap = 0; m_NextImageStartPosition = 0; } // We now need to go through and process the data in this file which // should now consist off GIF blocks until we hit the end of file or // we have processed the lot. BOOL FileProcessed = FALSE; m_bImageRead = FALSE; unsigned char c; // Set up bad values so that the DIB alloc claim will fail if there // has been no GIFIMAGEBLOCK found // int Width = 0; // Width of bitmap // int Height = 0; // Height of bitmap // int BitsPerPixel = 0; //ColorResolution; // Colour depth required if (m_NextImageStartPosition != 0) { File->seekIn(m_NextImageStartPosition, ios::beg); m_NextImageStartPosition = 0; } while (!File->eof() && !File->bad() && !FileProcessed) { // Get the next character in the stream and see what it indicates // comes next in the file // Use Get as this will read the EOF character (255) and exit via the // File->eof() test rather than Read which will throw an exception. //File->read( &c, 1 ); File->get( (char&)c ); switch (c) { case ';': { // GIF terminator // Cannot assume that the terminator immediately follows the image data // Might have some extensions following the image data. FileProcessed = TRUE; nBitmapToRead = -1; break; } case '!': //EXTENSIONBLOCK: { // Extension ProcessExtension(File); break; } case ',': { // start of image character if (m_bImageRead) // another bitmap - save it for the next call to ReadFromFile() { if (m_NextImageStartPosition == 0) { // No transparency info for the next one so start here m_NextImageStartPosition = File->tellIn() - 1; } ++nBitmapToRead; FileProcessed = TRUE; break; } UINT32 LeftOffset = 0; UINT32 TopOffset = 0; BOOL LocalPalette = FALSE; // Should be followed by a GIFIMAGE BLOCK ProcessImageBlock(File, Info, Bits, &LeftOffset, &TopOffset, &LocalPalette); ++m_nCurrentBitmap; if (nBitmapToRead == m_nCurrentBitmap) { m_bImageRead = TRUE; } // return the values back to the caller if it desired them if (pLeftOffset) *pLeftOffset = LeftOffset; if (pTopOffset) *pTopOffset = TopOffset; if (pLocalPalette) *pLocalPalette = LocalPalette; break; } default: // We have found something other than what we are expecting // so fail with an error //File->GotError( IDE_BADFORMAT ); // Cannot do this as some files have random bits // e.g. galileo.gif has a random zero before the ; // colsec.gif has a rampant > at the end instead of ; if (m_bImageRead) { // We've already got something so ignore anything else in case it goes // completely wrong. FileProcessed = TRUE; nBitmapToRead = -1; } TRACE( _T("Unrecognized Character %x at %d\n"), (int)c, File->tellIn()); break; } } // If we reach here and the bitmap allocations are still null then no valid image // was found and so we should error now. // Might have just been a GIF file with extension tags in and no images! if (*Info == NULL || *Bits == NULL) File->GotError( _R(IDE_BADFORMAT) ); // We read the desired bitmap but the EOF came along before we could try anything else // Signal this is the last bitmap if (m_bImageRead && File->eof()) { TRACE( _T("GIF: Premature end of file") ); nBitmapToRead = -1; } // Return the transparency/delay/restore found to the caller. *TransColour = Transparent; if (Delay) { *Delay = m_Delay; } if (Restore) { *Restore = m_Restore; } // Free up the bit of memory for a palette we grabbed, if present & no more images to read if (lpGlobalPalette && nBitmapToRead == -1) { CCFree(lpGlobalPalette); lpGlobalPalette = NULL; } // If started, then stop then progress bar if (ProgressString != NULL) EndSlowJob(); // Must set the exception throwing and reporting flags back to their entry states File->SetThrowExceptions( OldThrowingState ); File->SetReportErrors( OldReportingState ); // er, we seem to have finished OK so say so return TRUE; }
BOOL OutputDIB::SetUpExport( CCLexFile *File, LPBITMAPINFOHEADER lpHeader, LPLOGPALETTE Palette, UINT32 DitherType, UINT32 OutputDepth, DWORD CompressionType, UINT32 FinalHeight, LPBYTE BlockStart, UINT32 StripSize, INT32 ExportSize, BOOL Forward ) { ERROR2IF(File==NULL, FALSE, "OutputDIB::SetUpExport null File specified"); ERROR2IF(lpHeader==NULL, FALSE, "OutputDIB::SetUpExport null lpHeader specified"); ERROR2IF(BlockStart==NULL, FALSE, "OutputDIB::SetUpExport null BlockStart specified"); // remember input args OutputFile = File; StartPos = OutputFile->tell(); // remember where in the file this starts BitmapInfo = *lpHeader; // take a copy of user's header OutputPalette = NULL; // No palette to start with HeightWritten = 0; // zero height OutputForward = Forward; // Note the output direction CurrentStripSize = StripSize; // Note size of first strip CurrentExportSize = ExportSize; // size set up for the progress bar HeightWanted = FinalHeight; // the actual height of the export required // Remember which dithering type to use Dither = DitherType; IsFirstStrip = TRUE; ExportBuffer = NULL; // Just in case of early random exit set this to NULL INT32 PalSize = 0; // how many entries in palette // Set up the information header for the dib if ( !SetUpInfoHeader(lpHeader, OutputDepth, CompressionType, FinalHeight, &PalSize) ) return FALSE; // SetError already called // then the RGBQUAD palette, if required if (PalSize) { ERROR2IF(Palette == NULL,FALSE,"SetUpExport has a NULL Palette when one is required"); // If we are creating a palette then the Accusoft code requires that we specify an // bitmap info header which is followed immediately in memory by the palette. // if we just created a Palette then this would not be true so we must create a // new copy of the Bitmapinfo and then create the palette next. // This will not work in debug builds due to memory tracking information stored // in the allocation so we must allocate one big block and do the info header and // Palette from these. const size_t TotalHeader = sizeof(BITMAPINFOHEADER); const size_t TotalPalSize = (sizeof(RGBQUAD) * PalSize ); lpBitmap = (LPBITMAPINFO)CCMalloc( TotalHeader + TotalPalSize ); if (lpBitmap==NULL) return FALSE; // make a copy of the palette for possible later use const size_t TotalPal = sizeof(LOGPALETTE) + ( sizeof(PALETTEENTRY) * PalSize ); OutputPalette = (LPLOGPALETTE)CCMalloc( TotalPal ); if (OutputPalette==NULL) return FALSE; memcpy( OutputPalette, Palette, TotalPal ); // These are all freed in the TidyUp call. // Take a copy of the bitmap info header lpBitmapInfo = &(lpBitmap->bmiHeader); // pointer to info header memcpy( lpBitmapInfo, &BitmapInfo, TotalHeader ); // copy header info across // Now get a pointer to the palette LPRGBQUAD lpPalette = NULL; lpPalette = &(lpBitmap->bmiColors[0]); // pointer to colours table // Now copy the palette across into the bitmap info structure in RGQUAD form // OutputPalette should be set up by now so use this instead of Palette so if // we have bodged it, it will be the correct bodged palette that is put into the file // and not the 256 entry palette that seems to be supplied always. // We might want to use the existing palette - e.g. when we are altering the value // of a single colour. // Don't want to use the existing palette. for (INT32 i = 0; i < PalSize; i++) { lpPalette->rgbRed = OutputPalette->palPalEntry[i].peRed; lpPalette->rgbGreen = OutputPalette->palPalEntry[i].peGreen; lpPalette->rgbBlue = OutputPalette->palPalEntry[i].peBlue; lpPalette++; } } // Now lets grab the memory and then set up the first block of data ready for output size_t BufSize = 0L; ExportChunkHeight = 1; DoExportConvert = NULL; // Just in case the SetUpBlock fails ExportConvertFn = NULL; // Just in case the SetUpBlock fails // Set up the size and other information for the dib block that we require. This is // dependent on the export depth or bpp required. if ( !SetUpBlock( &BufSize, &ExportChunkHeight, &DoExportConvert, &ExportConvertFn ) ) return FALSE; // Error details already set up //TRACEUSER( "Neville", _T("SetUpExport BufSize = %d\n"),BufSize); //TRACEUSER( "Neville", _T("SetUpExport ExportChunkHeight = %d\n"),ExportChunkHeight); //TRACEUSER( "Neville", _T("SetUpExport FinalHeight = %d\n"),FinalHeight); //TRACEUSER( "Neville", _T("SetUpExport CurrentStripSize = %d\n"),CurrentStripSize); //TRACEUSER( "Neville", _T("SetUpExport DoExportConvert = %d\n"),DoExportConvert); //TRACEUSER( "Neville", _T("SetUpExport ExportConvertFn = %d\n"),ExportConvertFn); // Check for the case where we are exporting a small thin strip which is smaller // than our normal strip if (CurrentStripSize < ExportChunkHeight) { ExportChunkHeight = CurrentStripSize; //TRACEUSER( "Neville", _T("New ExportChunkHeight = %d\n"),ExportChunkHeight); } if (BufSize) { ExportBuffer = (LPBYTE)CCMalloc( BufSize ); if (ExportBuffer==NULL) return FALSE; } // Now get the actual class variables set up ready for this data SetUpForNextStrip(BlockStart, CurrentStripSize); // Now lets start the whole export process off by calling the StartSaveBitmap function // which will start the actual exporting process off with the supplied information. // This will then request blocks of data from the DestDIB in its call back routine // get_dib_data. // If we have created a palette then use the special header which has a valid palette // following immediately after it in memory LPBITMAPINFOHEADER lpSpBitmapInfo = NULL; if (PalSize) lpSpBitmapInfo = lpBitmapInfo; // Use our specially create header followed by palette else lpSpBitmapInfo = &BitmapInfo; // Use the proper header defined in the class #ifndef WEBSTER //WEBSTER-Martin-07/01/97 // no Accusoft stuff in WEBSTER, and I'm not sure it ever gets used in Camelot any // more (the DIB bits of Accusoft that is) // TRACEUSER( "Martin", _T("Not allowed to use Accusoft save bitmap\n")); if (!AccusoftFilters::StartSaveBitmap( OutputFile, // File to use lpSpBitmapInfo, // pointer to info header OutputPalette, // pointer to the palette OutputDepth, // actual file depth BI_RGB, // compression (BI_RGB = none) FinalHeight, // all of it StripSize, // size of the strip, might be FinalHeight OutputForward) // direction we were told on entry ) #endif //WEBSTER { return FALSE; //always for WEBSTER } return TRUE; }