summaryrefslogtreecommitdiff
path: root/undo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'undo.cpp')
-rw-r--r--undo.cpp59
1 files changed, 59 insertions, 0 deletions
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)