How to design undo function in Core-Graphics Framework? - core-graphics

Many pepole recommended that I save the image which I've just drawn, and load it when I need undo in the current picture.
But I think that may not be a good way to do this:
save and load to disk will cause lagging.
You cant erase after you undo, because you cant erase the image (not fill with backGroundColor).
So, I'm seeking for a way to restore the CGLayer's or context's data which is to cover the current one as "draw resource", when you need undo. I've used NSMutableData to do this, but its doesn't work at all, because only the pointer has been saved.
And I don't understand how to use CGContextSaveState,CGContextRestoreState. When you save it, you have to restore it before the drawRect has been done, you can't save it and restore when you need undo, because the context will be destroyed or reset when drawRect has done, and with all that I've tried, nothing happens.
Could somebody help me here? Thx!

Related

Is there a way to have moveable, protected elements in powerpoint?

Let's say I have a powerpoint with a circle, and a square. The circle has an animation attached to it, which is triggered by the clicking on the square.
Can I flatten the circle, so no-one can move it/click on it, whilst keeping the animation?
I've tried the flat pack add in, with no success. I can't find any code that does it.
Can anyone point me in the right direction/tell me I'm wasting my time?
Thanks
Sorry, that's not possible. You can lock objects, but then the animation will not be able to run. VBA is unable to change the XML to lock or unlock objects.
Here's more info about object locking: OOXML Hacking: Locking Graphics

Freezing OS X Screen in Cocoa

I have two methods that modify the display of the screen. Is there a way to freeze the screen until the second method is called?
// I want to freeze the screen here
updateDisplay1(); // Change in display doesn't take effect until screen is unfrozen
updateDisplay2();
// Unfreeze screen here
In Excel VBA this would be something like screenUpdating = FALSE. Is there a similar function in Cocoa?
One possible way is to take screenshot:
// Take screenshot of the screen
// Display the screenshot image in front of the screen
updateDisplay1(); // Change is not visible
updateDisplay2();
// Remove screenshot image
But I'm afraid this is slow and takes up a lot of memory. Is there a more efficient method?
What screen are you talking about?
Standard Cocoa behaviour is:
you update the properties of the various views you are interested in;
each of those will make a call to its own setNeedsDisplayInRect. As a result of those calls, a redraw will be scheduled on the run loop;
once you've finished doing all of your updates, the run loop will be able to move onto its next item;
eventually it'll reach the redraw it scheduled and will make appropriate drawRect calls to appropriate views.
So all view changes that you make in response to an action are automatically atomic. You have to go significantly out of your own way to create a partial update.
taking screenshots with CGWindowListCreateImage takes a few milliseconds and uses roughly any memory. it's usually done directly in the graphic card.
give it a try and measure before doing any performance assumptions:-)

it there any way to reset device in (slimdx, dx9) without disposing all device-related objects?

I am rendering using SlimDX to a control in a form. Since the size of that control might change very often, and there are lots of complex meshes, the traditional free-reset-construct method may be too slow to my taste. Any way to boost it up?
create an additional SwapChain linked to your current window using IDirect3DDevice9::CreateAdditionalSwapChain Method,
then, get the back buffer of the new SwapChain, and, use IDirect3DDevice9::SetRenderTarget method
to set the back buffer of the new SwapChain as the render target,
when you finished your drawings, call the present method of the new SwapChain instead of the IDirect3DDevice9::present,
when your window is resized, just release the additional SwapChain and re-create it with new back buffer sizes and do the render target setting thing again, now, you don`t have to do the device reset which is very slow.
if you have any more questions, email me : xux660#hotmail.com
I am a chinese so my english is not so good, forgive me.

Repeating NSTimer locks UI thread

First of all, I know there are a few other StackOverflow questions about this subject, but I have read them all and I still am confused about what to do for my situation. I'm probably missing something obvious here, if you could help clarify that would be much appreciated!
I have a app which is doing a lot of work to animate images within a view - mainly comprised of a number of images moving in straight lines for a second or two at a time. I considered at first making them all simple, once off animations using UIView animateWithDuration for the whole duration of the movement. But I found that didn't give me a lot of power to intercept the movement or stop it or check where it was up to, so I scrapped that. My new approach is to use an NSTimer, firing 20 times per second, doing incremental movements. This way I also can intervene (almost) instantly to change the animation or stop it or update a status label based on how far through it is, etc, etc.
First of all...there probably is a better way than this. Feel free to suggest something better!
Assuming this is acceptable though, my issue now is that while these animations are happening, I can't click any of the other controls on the UI. I get no response. It's not like it's just slow or delayed either - the click never comes through. It seems that the NSTimer processing totally locks the UI - but only from new interactions. Changes I make to the UI within the timer processing method happen just fine, and are very snappy.
From what I've read this shouldn't happen. However I also saw a comment on this question saying that if the timer processing is intensive then it could lock the UI thread. I don't see my processing to be that intensive here - certainly no resource requests, just a bit of data manipulating and animating some objects - but I could be underplaying it.
What are my options here? At first I thought I might create a new thread to kick off the timer. But I remember reading that the UI updates have to happen on the main thread anyway. Why is this? And plus, would that really solve the issue? Am I just asking too much of the device to process this timer as well as UI interactions? Is there something else I'm missing?
Any and all advice would be appreciated.
Edit:
I've just found the cause of my UI blocking problem. I was using the animateWithDuration with blocks, but was not setting the options. Therefore UIViewAnimationOptionAllowUserInteraction was not set. I changed it to set this option and my UI is happily responding now.
That said, I'll still leave this question open for specific suggestions regarding my overall approach. Thanks.
I would consider using CADisplayLink. From the documentation:
A CADisplayLink object is a timer object that allows your application to synchronize its drawing to the refresh rate of the display.
Your application creates a new display link, providing a target object and a selector to be called when the screen is updated. Next, your application adds the display link to a run loop.
Once the display link is associated with a run loop, the selector on the target is called when the screen’s contents need to be updated. The target can read the display link’s timestamp property to retrieve the time that the previous frame was displayed. For example, an application that displays movies might use the timestamp to calculate which video frame will be displayed next. An application that performs its own animations might use the timestamp to determine where and how displayed objects appear in the upcoming frame. The duration property provides the amount of time between frames. You can use this value in your application to calculate the frame rate of the display, the approximate time that the next frame will be displayed, and to adjust the drawing behavior so that the next frame is prepared in time to be displayed.
Your application can disable notifications by setting the paused property to YES. Also, if your application cannot provide frames in the time provided, you may want to choose a slower frame rate. An application with a slower but consistent frame rate appears smoother to the user than an application that skips frames. You can increase the time between frames (and decrease the apparent frame rate) by changing the frameInterval property.
When your application finishes with a display link, it should call invalidate to remove it from all run loops and to disassociate it from the target.
CADisplayLink should not be subclassed.
I'm not totally sure how everything is handled in your program, but you might want to just consider having one thread/timer that controls all of the objects and their movements. There's really no need to create a separate thread/timer for every single object, as that will easily cause problems.
You can just create a class for your moving items with some variables that contain information about their direction, speed, duration, etc, and then have a controlling thread/timer calculate and move the objects. You can then intervene onto the one main controller object instead of having to deal with many other objects.
I think you'll find that even if you optimize this, timer based animation like this is not going to perform well.
You might want to ask about the specific things that you think you couldn't do with CoreAnimation. If you solve those issues, you'll end up with a much better result than trying to roll your own.

How to avoid a NSCachedImageRep

I'm working with an NSImage which comes from a PDF. When I initially create the image, it has only one NSImageRep and that is NSPDFImageRep. This is good. I can work with it. I can find out how many pages it has, and go to a specified page, and draw it, etc.
The problem is that as soon as I turn my back, it gets turned into a NSCachedImageRep, which doesn't seem to have multiple pages. Now, if I keep the PDFImageRep in a separate variable, it is kept track of, but it isn't associated with the image anymore, so when I draw the image, it's still on the same page.
What am I missing?
thanks.
You need to call [image setDataRetained:YES] on the image, so that your original PDF data is kept around, otherwise it will be cached to a bitmap.
If you're still having problems you could turn off caching altogether by using [image setCacheMode:NSImageCacheNever].
Try it on 10.6. The problem has probably evaporated.
Please see the AppKit release notes for details of the NSImage changes.