我正在为移动设备编写位图编辑器(即 Photoshop 的简化版本)。用户的文档由 ~4 个大小约为 1000x500 的位图组成。
我想要一个尽可能简单的、健壮且高效的撤销/重做系统。我希望每次撤销或重做编辑所需时间大约为 ~0.2 秒。我正在寻求对我的当前方法的反馈或一些新的想法。我认为我现在的方法过于复杂了,所以我很谨慎地进行下一步操作,只要知道这是我能做到的最好的就可以了。
我已经尝试了使用命令模式和备忘录模式的组合来实现我的撤销/重做系统。我得出了一些结论:
在许多情况下,我没有足够的内存,也无法快速将内存写入磁盘来支持“取消上一个命令”操作,例如如果用户非常快地进行了几个单独的绘画笔划,则我将无法存储代表用户绘制的位图而不使用户等待它们被保存。
如果要还原文档到其初始状态,并重放除最后一个命令之外的所有命令以实现撤销,则即使有少量命令,如重新播放 10 次绘画笔划或 5 次涂抹笔划,也会变得非常缓慢(大约需要 1 秒钟)。
我可以通过定期在后台将整个文档保存到磁盘中并在播放命令之前还原到此检查点来解决前一个问题。要向更远处撤销,我们会在当前检查点之前重新加载检查点并重放命令。
第二种方法和第三种方法相结合效果还不错,但随着添加的图层数越来越多,保存整个文档所需的时间也会越来越长,即使只有 4 个位图,等待时间也要 5-10 秒钟。因此,我需要修改第三步,以便仅保存自上次检查点以来发生了哪些更改。
由于许多命令仅对一层进行操作,所以只保存自上次检查点以来已被修改的层是有意义的。例如,如果我有 3 个初始层,并指示可能保存检查点的位置,则我的命令堆栈可能如下所示。
(Checkpoint1: Save layer 1, 2 and 3.)
Paint on layer 1
Paint on layer 1
(Checkpoint2: Save layer 1. Reuse saved layers 2 and 3 from Checkpoint1.)
Paint on layer 2
Paint on layer 2
(Checkpoint3: Save layer 2. Reuse saved layers 1 and 3 from Checkpoint2.)
Paint on layer 3
Paint on layer 3
Flip layer 3 horizontally.
(Checkpoint4: Save layer 3. Reuse saved layers 1 and 2 from Checkpoint3.)
Resize layer 1, 2 and 3.
(Checkpoint5: Save layer 1, 2, 3.)
在编辑过程中,我会跟踪哪些层自上一个检查点以来已被修改。当我恢复检查点时,我只恢复已更改的层,例如,在修改了第2和第3层后恢复Checkpoint4,我会从磁盘重新加载第2和第3层的备份。添加检查点时,我仅保存到目前为止已被修改的层。我可以使这一切大部分自动化,但必须在我的界面中有需要等待检查点保存的位置,因为我一次只能在内存中保留1个图层的临时副本。
你认为呢?这比我想象的要复杂得多,但我看不到其他办法。是否还有其他有用的模式可以让我的生活变得更轻松?