add mac image-encoding
add 'f' to sampleapp, which writes a png file for the currnet screen
git-svn-id: http://skia.googlecode.com/svn/trunk@47 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/views/SkWindow.h b/include/views/SkWindow.h
index 96262ee..da3912e 100644
--- a/include/views/SkWindow.h
+++ b/include/views/SkWindow.h
@@ -52,6 +52,8 @@
bool handleMenu(uint32_t os_cmd);
void addMenu(SkOSMenu*);
+
+ const char* getTitle() const { return fTitle.c_str(); }
void setTitle(const char title[]);
protected:
@@ -80,6 +82,8 @@
SkView* fFocusView;
bool fWaitingOnInval;
+
+ SkString fTitle;
typedef SkView INHERITED;
};
diff --git a/samplecode/SampleApp.cpp b/samplecode/SampleApp.cpp
index 365f558..df0723f 100644
--- a/samplecode/SampleApp.cpp
+++ b/samplecode/SampleApp.cpp
@@ -2,6 +2,7 @@
#include "SkDevice.h"
#include "SkGLCanvas.h"
#include "SkGraphics.h"
+#include "SkImageDecoder.h"
#include "SkPaint.h"
#include "SkPicture.h"
#include "SkStream.h"
@@ -380,6 +381,17 @@
return this->INHERITED::onEvent(evt);
}
+static void cleanup_for_filename(SkString* name) {
+ char* str = name->writable_str();
+ for (int i = 0; i < name->size(); i++) {
+ switch (str[i]) {
+ case ':': str[i] = '-'; break;
+ case '/': str[i] = '-'; break;
+ case ' ': str[i] = '_'; break;
+ default: break;
+ }
+ }
+}
bool SampleWindow::onHandleChar(SkUnichar uni) {
int dx = 0xFF;
@@ -411,10 +423,28 @@
return true;
}
- if ('a' == uni) {
- fAnimating = !fAnimating;
- this->postAnimatingEvent();
- this->updateTitle();
+ switch (uni) {
+ case 'a':
+ fAnimating = !fAnimating;
+ this->postAnimatingEvent();
+ this->updateTitle();
+ return true;
+ case 'f': {
+ const char* title = this->getTitle();
+ if (title[0] == 0) {
+ title = "sampleapp";
+ }
+ SkString name(title);
+ cleanup_for_filename(&name);
+ name.append(".png");
+ if (SkImageEncoder::EncodeFile(name.c_str(), this->getBitmap(),
+ SkImageEncoder::kPNG_Type)) {
+ SkDebugf("Created %s\n", name.c_str());
+ }
+ return true;
+ }
+ default:
+ break;
}
return this->INHERITED::onHandleChar(uni);
diff --git a/src/ports/SkImageDecoder_CG.cpp b/src/ports/SkImageDecoder_CG.cpp
index da8bf15..74ff112 100644
--- a/src/ports/SkImageDecoder_CG.cpp
+++ b/src/ports/SkImageDecoder_CG.cpp
@@ -54,14 +54,12 @@
if (NULL == imageSrc) {
return false;
}
-
SkAutoTCallVProc<const void, CFRelease> arsrc(imageSrc);
CGImageRef image = CGImageSourceCreateImageAtIndex(imageSrc, 0, NULL);
if (NULL == image) {
return false;
}
-
SkAutoTCallVProc<CGImage, CGImageRelease> arimage(image);
const int width = CGImageGetWidth(image);
@@ -109,19 +107,92 @@
#ifdef SK_SUPPORT_IMAGE_ENCODE
+static size_t consumer_put(void* info, const void* buffer, size_t count) {
+ SkWStream* stream = reinterpret_cast<SkWStream*>(info);
+ return stream->write(buffer, count) ? count : 0;
+}
+
+static void consumer_release(void* info) {
+ // we do nothing, since by design we don't "own" the stream (i.e. info)
+}
+
+static CGDataConsumerRef SkStreamToCGDataConsumer(SkWStream* stream) {
+ CGDataConsumerCallbacks procs;
+ procs.putBytes = consumer_put;
+ procs.releaseConsumer = consumer_release;
+ // we don't own/reference the stream, so it our consumer must not live
+ // longer that our caller's ownership of the stream
+ return CGDataConsumerCreate(stream, &procs);
+}
+
+static CGImageDestinationRef SkStreamToImageDestination(SkWStream* stream,
+ CFStringRef type) {
+ CGDataConsumerRef consumer = SkStreamToCGDataConsumer(stream);
+ if (NULL == consumer) {
+ return NULL;
+ }
+ SkAutoTCallVProc<const void, CFRelease> arconsumer(consumer);
+
+ return CGImageDestinationCreateWithDataConsumer(consumer, type, 1, NULL);
+}
+
+class SkImageEncoder_CG : public SkImageEncoder {
+public:
+ SkImageEncoder_CG(Type t) : fType(t) {}
+
+protected:
+ virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality);
+
+private:
+ Type fType;
+};
+
+extern CGImageRef SkCreateCGImageRef(const SkBitmap&);
+
+/* Encode bitmaps via CGImageDestination. We setup a DataConsumer which writes
+ to our SkWStream. Since we don't reference/own the SkWStream, our consumer
+ must only live for the duration of the onEncode() method.
+ */
+bool SkImageEncoder_CG::onEncode(SkWStream* stream, const SkBitmap& bm,
+ int quality) {
+ CFStringRef type;
+ switch (fType) {
+ case kJPEG_Type:
+ type = kUTTypeJPEG;
+ break;
+ case kPNG_Type:
+ type = kUTTypePNG;
+ break;
+ default:
+ return false;
+ }
+
+ CGImageDestinationRef dst = SkStreamToImageDestination(stream, type);
+ if (NULL == dst) {
+ return false;
+ }
+ SkAutoTCallVProc<const void, CFRelease> ardst(dst);
+
+ CGImageRef image = SkCreateCGImageRef(bm);
+ if (NULL == image) {
+ return false;
+ }
+ SkAutoTCallVProc<CGImage, CGImageRelease> agimage(image);
+
+ CGImageDestinationAddImage(dst, image, NULL);
+ CGImageDestinationFinalize(dst);
+ return true;
+}
+
SkImageEncoder* SkImageEncoder::Create(Type t) {
-#if 0
switch (t) {
case kJPEG_Type:
- return SkImageEncoder_JPEG_Factory();
case kPNG_Type:
- return SkImageEncoder_PNG_Factory();
+ break;
default:
return NULL;
}
-#else
- return NULL;
-#endif
+ return SkNEW_ARGS(SkImageEncoder_CG, (t));
}
#endif
diff --git a/src/views/SkWindow.cpp b/src/views/SkWindow.cpp
index ae03b81..c8403d4 100644
--- a/src/views/SkWindow.cpp
+++ b/src/views/SkWindow.cpp
@@ -248,10 +248,11 @@
this->onAddMenu(menu);
}
-void SkWindow::setTitle(const char title[])
-{
- if (NULL == title)
+void SkWindow::setTitle(const char title[]) {
+ if (NULL == title) {
title = "";
+ }
+ fTitle.set(title);
this->onSetTitle(title);
}