From 1da96e0dbe95f5078623e2b0469152692833a096 Mon Sep 17 00:00:00 2001 From: Fox Caminiti Date: Tue, 22 Nov 2022 23:02:54 -0500 Subject: file io, compression --- undo.cpp | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) (limited to 'undo.cpp') diff --git a/undo.cpp b/undo.cpp index d985cee..16349d2 100644 --- a/undo.cpp +++ b/undo.cpp @@ -58,6 +58,38 @@ History_GetTreeInfo(history_entry_list *History, uint16 SampleIndex) return Info; } +// This function works exactly the same whether we're in undo/redo, pretty neat. +void History_Action_DoSwapBitmap(memory *Memory, history_action *ActionPointer, uint8 *Address_HistoryTree_Start, uint8 *Address_HistoryTree_End, uint8 *Address_Data) +{ + history_action Action = *ActionPointer; + + uint64 FullSize = Action.ShiftAmount; + uint64 CompressedSize = Action.Size; + + uint32 BytesForCompressedPart = (uint32)100 * 1024 * 1024; + void *UncompressedTempBuffer = Memory_PushScratch(Memory, FullSize); + void *CompressedTempBuffer = Memory_PushScratch(Memory, BytesForCompressedPart); + + // First we decompress and swap the saved pixels with the newer ones... + Data_Decompress(Memory, Address_HistoryTree_Start, CompressedSize, UncompressedTempBuffer, FullSize); + Bitmap_SwapData((uint8 *)UncompressedTempBuffer, (uint8 *)Address_Data, FullSize, Action.Direction); + + // Then we recompress the old pixels and evaluate its size, and since the size can be different... + uint64 NewSize = Data_Compress(Memory, UncompressedTempBuffer, FullSize, CompressedTempBuffer, BytesForCompressedPart, Z_BEST_SPEED); + + // we have to shift the undo stack. + if (NewSize != CompressedSize) { + int16 ShiftDirection = (NewSize > CompressedSize) ? 1 : -1; + uint64 ShiftAmount = (NewSize > CompressedSize) ? NewSize - CompressedSize : CompressedSize - NewSize; + Arbitrary_ShiftData(Address_HistoryTree_Start + CompressedSize, Address_HistoryTree_End, ShiftAmount, ShiftDirection); + } + Memory_Copy(Address_HistoryTree_Start, (uint8 *)CompressedTempBuffer, NewSize); + + ActionPointer->Size = NewSize; + Memory_PopScratch(Memory, BytesForCompressedPart); + Memory_PopScratch(Memory, FullSize); +} + void History_Action_Undo(memory *Memory, history_info Info, history_action *ActionPointer, uint64 Action_Offset) { history_entry_list *History = &Memory->History; @@ -71,6 +103,8 @@ void History_Action_Undo(memory *Memory, history_info Info, history_action *Acti if (Action.Type == action_type_swap) { Arbitrary_SwapData(Memory, Address_HistoryTree_Start, Address_Data, Action.Size); + } else if (Action.Type == action_type_swap_bitmap) { + History_Action_DoSwapBitmap(Memory, ActionPointer, Address_HistoryTree_Start, Address_HistoryTree_End, Address_Data); } else if (Action.Type == action_type_shift) { // In order to shift back we have to start the address at where the // shifted chunk is _now_, not when we called the function. @@ -97,6 +131,8 @@ void History_Action_Redo(memory *Memory, history_info Info, history_action *Acti if (Action.Type == action_type_swap) { Arbitrary_SwapData(Memory, Address_HistoryTree_Start, Address_Data, Action.Size); + } else if (Action.Type == action_type_swap_bitmap) { + History_Action_DoSwapBitmap(Memory, ActionPointer, Address_HistoryTree_Start, Address_HistoryTree_End, Address_Data); } else if (Action.Type == action_type_shift) { void *Address_Start = Memory_AddressAtOffset(Memory, Action.TableName, Action.ByteOffset); uint8 *Address_End = (uint8 *)Address_Start + Action.Size; @@ -204,6 +240,21 @@ static void History_Action_Add(memory *Memory, history_action ActionData, void * void *Address_HistoryTree = Memory_AddressAtOffset(Memory, P_UndoBuffer, Info.ActionOffset_Total); void *Address_Data = Memory_AddressAtOffset(Memory, Action->TableName, Action->ByteOffset); Memory_Copy((uint8 *)Address_HistoryTree, (uint8 *)Address_Data, Action->Size); + } else if (Action->Type == action_type_swap_bitmap) + { + // The address of data to be stored in the undo tree is not the same as + // the address to be recorded, so we have to pass it manually. + void *Address_HistoryTree = Memory_AddressAtOffset(Memory, P_UndoBuffer, Info.ActionOffset_Total); + void *Address_Data = ReferenceData; + + // Libz/miniz requires passing an amount of available space, and it + // returns how much space the compressed data actually is. + // We don't need to alloc any more memory since we can just use the + // history tree as the destination. + // ShiftAmount is also being used to save the uncompressed size. + uint32 BytesForCompressedPart = (uint32)100 * 1024 * 1024; + Action->Size = Data_Compress(Memory, Address_Data, Action->ShiftAmount, Address_HistoryTree, BytesForCompressedPart, Z_BEST_SPEED); + } else if (Action->Type == action_type_shift) { void *Address_Start = Memory_AddressAtOffset(Memory, Action->TableName, Action->ByteOffset); @@ -216,6 +267,14 @@ static void History_Action_Add(memory *Memory, history_action ActionData, void * // Helper functions for different tables. +static void History_Action_BitmapPaint(memory *Memory, uint64 Size_Uncompressed, + void *SourceBitmapAddress, void *CachedPaintAddress, int16 BytesPerPixel) +{ + void *Address_Start = Memory->Slot[F_PrincipalBitmaps].Address; + uint64 ByteOffset = (ptrsize)SourceBitmapAddress - (ptrsize)Address_Start; + history_action Action = { F_PrincipalBitmaps, action_type_swap_bitmap, 0, ByteOffset, Size_Uncompressed, BytesPerPixel }; + History_Action_Add(Memory, Action, CachedPaintAddress); +} static void History_Action_Shift(memory *Memory, memory_table_list TableName, void *Address0, void *Address1, uint64 Amount, int16 Direction) -- cgit v1.2.3