aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rwxr-xr-xinclude/utils/ios/SkStream_NSData.h34
-rwxr-xr-xinclude/views/SkOSWindow_iOS.h35
-rwxr-xr-xsrc/utils/ios/SkFontHost_iOS.mm266
-rwxr-xr-xsrc/utils/ios/SkImageDecoder_iOS.mm65
-rwxr-xr-xsrc/utils/ios/SkOSFile_iOS.mm94
-rwxr-xr-xsrc/utils/ios/SkOSWindow_iOS.mm208
-rwxr-xr-xsrc/utils/ios/SkStream_NSData.mm41
7 files changed, 743 insertions, 0 deletions
diff --git a/include/utils/ios/SkStream_NSData.h b/include/utils/ios/SkStream_NSData.h
new file mode 100755
index 0000000000..af0004f991
--- /dev/null
+++ b/include/utils/ios/SkStream_NSData.h
@@ -0,0 +1,34 @@
+#ifndef SkStream_NSData_DEFINED
+#define SkStream_NSData_DEFINED
+
+#import <UIKit/UIKit.h>
+#include "SkStream.h"
+
+/** Returns an NSData with a copy of the stream's data. The caller must call
+ retain if it intends to keep the data object beyond the current stack-frame
+ (i.e. internally we're calling [NSData dataWithBytes...]
+ */
+NSData* NSData_dataWithStream(SkStream* stream);
+
+/** Returns an NSData from the named resource (from main bundle).
+ The caller must call retain if it intends to keep the data object beyond
+ the current stack-frame
+ (i.e. internally we're calling [NSData dataWithContentsOfMappedFile...]
+ */
+NSData* NSData_dataFromResource(const char name[], const char suffix[]);
+
+/** Wrap a stream around NSData.
+ */
+class SkStream_NSData : public SkMemoryStream {
+public:
+ SkStream_NSData(NSData* data);
+ virtual ~SkStream_NSData();
+
+ static SkStream_NSData* CreateFromResource(const char name[],
+ const char suffix[]);
+
+private:
+ NSData* fNSData;
+};
+
+#endif
diff --git a/include/views/SkOSWindow_iOS.h b/include/views/SkOSWindow_iOS.h
new file mode 100755
index 0000000000..4f4205b592
--- /dev/null
+++ b/include/views/SkOSWindow_iOS.h
@@ -0,0 +1,35 @@
+#ifndef SkOSWindow_iOS_DEFINED
+#define SkOSWindow_iOS_DEFINED
+
+#include "SkWindow.h"
+#include "SkMatrix.h"
+class SkOSWindow : public SkWindow {
+public:
+ SkOSWindow(void* hwnd);
+ ~SkOSWindow();
+ void* getHWND() const { return fHWND; }
+
+ static bool PostEvent(SkEvent* evt, SkEventSinkID, SkMSec delay);
+
+ void detachGL();
+ bool attachGL();
+ void presentGL();
+
+protected:
+ // overrides from SkEventSink
+ virtual bool onEvent(const SkEvent& evt);
+ // overrides from SkWindow
+ virtual void onHandleInval(const SkIRect&);
+ // overrides from SkView
+ virtual void onAddMenu(const SkOSMenu*);
+ virtual void onSetTitle(const char[]);
+
+private:
+ void* fHWND;
+ bool fInvalEventIsPending;
+ void* fNotifier;
+ typedef SkWindow INHERITED;
+};
+
+#endif
+
diff --git a/src/utils/ios/SkFontHost_iOS.mm b/src/utils/ios/SkFontHost_iOS.mm
new file mode 100755
index 0000000000..0cde81e741
--- /dev/null
+++ b/src/utils/ios/SkFontHost_iOS.mm
@@ -0,0 +1,266 @@
+#import <UIKit/UIKit.h>
+
+#include "SkStream_NSData.h"
+#include "SkTypeface.h"
+#include "SkFontHost.h"
+#include "SkThread.h"
+#include "SkTemplates.h"
+
+enum FontDesign {
+ kUnknown_Design,
+ kSans_FontDesign,
+ kSerif_FontDesign,
+
+ kIllegal_FontDesign, // never use with a real font
+};
+
+// returns kIllegal_FontDesign if not found
+static FontDesign find_design_from_name(const char name[]) {
+ static const struct {
+ const char* fName;
+ FontDesign fDesign;
+ } gRec[] = {
+ { "sans-serif", kSans_FontDesign },
+ { "serif", kSerif_FontDesign },
+ };
+
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); i++) {
+ if (!strcasecmp(name, gRec[i].fName)) {
+ return gRec[i].fDesign;
+ }
+ }
+ return kIllegal_FontDesign;
+}
+
+struct FontRes {
+ const char* fName;
+ SkTypeface::Style fStyle;
+ FontDesign fDesign;
+};
+
+static const FontRes gFontRes[] = {
+ { "DroidSans", SkTypeface::kNormal, kSans_FontDesign },
+ { "DroidSans", SkTypeface::kBold, kSans_FontDesign },
+ { "DroidSerif-Regular", SkTypeface::kNormal, kSerif_FontDesign },
+ { "DroidSerif-Bold", SkTypeface::kBold, kSerif_FontDesign },
+// { "PescaderoPro", SkTypeface::kNormal, kSerif_FontDesign },
+// { "PescaderoPro-Bold", SkTypeface::kBold, kSerif_FontDesign },
+};
+#define FONTRES_COUNT SK_ARRAY_COUNT(gFontRes)
+
+#define DEFAULT_INDEX_REGULAR 1
+#define DEFAULT_INDEX_BOLD 2
+
+///////////////////////////////////////////////////////////////////////////////
+
+class SkTypeface_Stream : public SkTypeface {
+public:
+ SkTypeface_Stream(SkStream* stream, Style style);
+ virtual ~SkTypeface_Stream();
+
+ SkStream* refStream() {
+ fStream->ref();
+ return fStream;
+ }
+
+private:
+ SkStream* fStream;
+};
+
+static int32_t gUniqueFontID;
+
+SkTypeface_Stream::SkTypeface_Stream(SkStream* stream, Style style)
+: SkTypeface(style, sk_atomic_inc(&gUniqueFontID) + 1) {
+ fStream = stream;
+ fStream->ref();
+}
+
+SkTypeface_Stream::~SkTypeface_Stream() {
+ fStream->unref();
+}
+
+static SkTypeface_Stream* create_from_fontres(const FontRes& res) {
+ SkStream* stream = SkStream_NSData::CreateFromResource(res.fName, "ttf");
+ SkAutoUnref aur(stream);
+
+ return SkNEW_ARGS(SkTypeface_Stream, (stream, res.fStyle));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static int compute_style_distance(SkTypeface::Style a, SkTypeface::Style b) {
+ int dist = 0;
+ int diff = a ^ b;
+ if (diff & SkTypeface::kBold) {
+ dist += 2;
+ }
+ if (diff & SkTypeface::kItalic) {
+ dist += 1;
+ }
+ return dist;
+}
+
+static SkTypeface_Stream* gFonts[FONTRES_COUNT];
+
+static void assure_init_fonts() {
+ static bool gOnce;
+ if (!gOnce) {
+ for (size_t i = 0; i < FONTRES_COUNT; i++) {
+ gFonts[i] = create_from_fontres(gFontRes[i]);
+ gOnce = true;
+ }
+ }
+}
+
+static SkTypeface_Stream* get_default_font(SkTypeface::Style style) {
+ assure_init_fonts();
+
+ if (style & SkTypeface::kBold) {
+ return gFonts[DEFAULT_INDEX_BOLD];
+ } else {
+ return gFonts[DEFAULT_INDEX_REGULAR];
+ }
+}
+
+static SkTypeface_Stream* find_by_id(SkFontID fontID) {
+ assure_init_fonts();
+
+ for (size_t i = 0; i < FONTRES_COUNT; i++) {
+ if (gFonts[i]->uniqueID() == fontID) {
+ return gFonts[i];
+ }
+ }
+ return NULL;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+template <typename T> T* ref_and_return(T* obj) {
+ obj->ref();
+ return obj;
+}
+
+SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
+ const char familyName[],
+ const void* data, size_t bytelength,
+ SkTypeface::Style style) {
+ assure_init_fonts();
+
+ if (familyName) {
+ FontDesign design = find_design_from_name(familyName);
+ if (kIllegal_FontDesign != design) {
+ familyName = "$#@*&%*#$@ never match any name";
+ }
+
+ int bestDistance = 999;
+ int bestIndex = -1;
+ for (size_t i = 0; i < FONTRES_COUNT; i++) {
+ if (design == gFontRes[i].fDesign || !strcmp(gFontRes[i].fName, familyName)) {
+ int dist = compute_style_distance(style, gFontRes[i].fStyle);
+ if (dist < bestDistance) {
+ bestDistance = dist;
+ bestIndex = i;
+ }
+ }
+ }
+ if (bestIndex >= 0) {
+ return ref_and_return(gFonts[bestIndex]);
+ }
+ }
+
+ return ref_and_return(get_default_font(style));
+}
+
+SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
+ SkASSERT(!"SkFontHost::CreateTypeface unimplemented");
+ return NULL;
+}
+
+SkTypeface* SkFontHost::CreateTypefaceFromFile(char const*) {
+// SkASSERT(!"SkFontHost::CreateTypefaceFromFile unimplemented");
+ return NULL;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool SkFontHost::ValidFontID(uint32_t uniqueID) {
+ return true;
+}
+
+SkStream* SkFontHost::OpenStream(uint32_t uniqueID) {
+ SkTypeface_Stream* tf = find_by_id(uniqueID);
+ SkASSERT(tf);
+ return tf->refStream();
+}
+
+size_t SkFontHost::GetFileName(SkFontID fontID, char path[], size_t length,
+ int32_t* index) {
+ SkDebugf("SkFontHost::GetFileName unimplemented\n");
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) {
+ SkASSERT(!"SkFontHost::Serialize unimplemented");
+}
+
+SkTypeface* SkFontHost::Deserialize(SkStream* stream) {
+ int style = stream->readU8();
+ int len = stream->readPackedUInt();
+ const char* name = NULL;
+ if (len > 0) {
+ SkString str;
+ str.resize(len);
+ stream->read(str.writable_str(), len);
+
+ if (str.startsWith("DroidSans")) {
+ name = "sans-serif";
+ } else if (str.startsWith("DroidSerif")) {
+ name = "serif";
+ }
+ SkDebugf("---- deserialize typeface <%s> %d %s\n", str.c_str(), style, name);
+ }
+// name = NULL; style = 0;
+ return SkFontHost::CreateTypeface(NULL, name, NULL, NULL,
+ (SkTypeface::Style)style);
+}
+
+SkFontID SkFontHost::NextLogicalFont(SkFontID currFontID, SkFontID origFontID) {
+ return 0;
+}
+
+#define FONT_CACHE_MEMORY_BUDGET 1 * 1024 * 1024
+
+size_t SkFontHost::ShouldPurgeFontCache(size_t sizeAllocatedSoFar) {
+ if (sizeAllocatedSoFar > FONT_CACHE_MEMORY_BUDGET)
+ return sizeAllocatedSoFar - FONT_CACHE_MEMORY_BUDGET;
+ else
+ return 0; // nothing to do
+}
+
+///////////////////////////////////////////////////////////////////////////////
+int SkFontHost::ComputeGammaFlag(const SkPaint& paint) {
+ return 0;
+}
+
+void SkFontHost::GetGammaTables(const uint8_t* tables[2]) {
+ tables[0] = NULL; // black gamma (e.g. exp=1.4)
+ tables[1] = NULL; // white gamma (e.g. exp= 1/1.4)
+}
+
+// static
+SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
+ uint32_t fontID,
+ SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo) {
+ SkASSERT(!"SkFontHost::GetAdvancedTypefaceMetrics unimplemented");
+ return NULL;
+}
+
+void SkFontHost::FilterRec(SkScalerContext::Rec* rec) {
+}
+
+SkScalerContext* SkFontHost::CreateScalerContext(const SkDescriptor* desc) {
+ SkASSERT(!"SkFontHost::CreateScalarContext unimplemented");
+ return NULL;
+} \ No newline at end of file
diff --git a/src/utils/ios/SkImageDecoder_iOS.mm b/src/utils/ios/SkImageDecoder_iOS.mm
new file mode 100755
index 0000000000..fc4316a56e
--- /dev/null
+++ b/src/utils/ios/SkImageDecoder_iOS.mm
@@ -0,0 +1,65 @@
+/*
+ Copyright 2010, Tetrark Inc.
+*/
+
+#import <CoreGraphics/CoreGraphics.h>
+#include <CoreGraphics/CGColorSpace.h>
+#import <UIKit/UIKit.h>
+
+#include "SkImageDecoder.h"
+#include "SkImageEncoder.h"
+#include "SkMovie.h"
+#include "SkStream_NSData.h"
+
+class SkImageDecoder_iOS : public SkImageDecoder {
+protected:
+ virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode);
+};
+
+#define BITMAP_INFO (kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast)
+
+bool SkImageDecoder_iOS::onDecode(SkStream* stream, SkBitmap* bm, Mode mode) {
+
+ NSData* data = NSData_dataWithStream(stream);
+
+ UIImage* uimage = [UIImage imageWithData:data];
+
+ const int width = uimage.size.width;
+ const int height = uimage.size.height;
+ bm->setConfig(SkBitmap::kARGB_8888_Config, width, height);
+ if (SkImageDecoder::kDecodeBounds_Mode == mode) {
+ return true;
+ }
+
+ if (!this->allocPixelRef(bm, NULL)) {
+ return false;
+ }
+
+ bm->lockPixels();
+ bm->eraseColor(0);
+
+ CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
+ CGContextRef cg = CGBitmapContextCreate(bm->getPixels(), width, height,
+ 8, bm->rowBytes(), cs, BITMAP_INFO);
+ CGContextDrawImage(cg, CGRectMake(0, 0, width, height), uimage.CGImage);
+ CGContextRelease(cg);
+ CGColorSpaceRelease(cs);
+
+ bm->unlockPixels();
+ return true;
+}
+
+/////////////////////////////////////////////////////////////////////////
+
+SkImageDecoder* SkImageDecoder::Factory(SkStream* stream) {
+ return new SkImageDecoder_iOS;
+}
+
+SkMovie* SkMovie::DecodeStream(SkStream* stream) {
+ return NULL;
+}
+
+SkImageEncoder* SkImageEncoder::Create(Type t) {
+ return NULL;
+}
+
diff --git a/src/utils/ios/SkOSFile_iOS.mm b/src/utils/ios/SkOSFile_iOS.mm
new file mode 100755
index 0000000000..33c572ac3a
--- /dev/null
+++ b/src/utils/ios/SkOSFile_iOS.mm
@@ -0,0 +1,94 @@
+/*
+ Copyright 2010, Tetrark Inc.
+*/
+
+#include "SkOSFile.h"
+#include "SkString.h"
+
+struct SkFILE {
+ NSData* fData;
+ size_t fOffset;
+ size_t fLength;
+};
+
+SkFILE* sk_fopen(const char cpath[], SkFILE_Flags flags) {
+ if (flags & kWrite_SkFILE_Flag) {
+ return NULL;
+ }
+
+ SkString cname, csuffix;
+
+ const char* start = strrchr(cpath, '/');
+ if (NULL == start) {
+ start = cpath;
+ } else {
+ start += 1;
+ }
+ const char* stop = strrchr(cpath, '.');
+ if (NULL == stop) {
+ return NULL;
+ } else {
+ stop += 1;
+ }
+
+ cname.set(start, stop - start - 1);
+ csuffix.set(stop);
+
+ NSBundle* bundle = [NSBundle mainBundle];
+ NSString* name = [NSString stringWithUTF8String:cname.c_str()];
+ NSString* suffix = [NSString stringWithUTF8String:csuffix.c_str()];
+ NSString* path = [bundle pathForResource:name ofType:suffix];
+ NSData* data = [NSData dataWithContentsOfMappedFile:path];
+
+ if (data) {
+ [data retain];
+ SkFILE* rec = new SkFILE;
+ rec->fData = data;
+ rec->fOffset = 0;
+ rec->fLength = [data length];
+ return reinterpret_cast<SkFILE*>(rec);
+ }
+ return NULL;
+}
+
+size_t sk_fgetsize(SkFILE* rec) {
+ SkASSERT(rec);
+ return rec->fLength;
+}
+
+bool sk_frewind(SkFILE* rec) {
+ SkASSERT(rec);
+ rec->fOffset = 0;
+ return true;
+}
+
+size_t sk_fread(void* buffer, size_t byteCount, SkFILE* rec) {
+ if (NULL == buffer) {
+ return rec->fLength;
+ } else {
+ size_t remaining = rec->fLength - rec->fOffset;
+ if (byteCount > remaining) {
+ byteCount = remaining;
+ }
+ memcpy(buffer, (char*)[rec->fData bytes] + rec->fOffset, byteCount);
+ rec->fOffset += byteCount;
+ SkASSERT(rec->fOffset <= rec->fLength);
+ return byteCount;
+ }
+}
+
+size_t sk_fwrite(const void* buffer, size_t byteCount, SkFILE* f) {
+ SkASSERT(!"Not supported yet");
+ return 0;
+}
+
+void sk_fflush(SkFILE* f) {
+ SkASSERT(!"Not supported yet");
+}
+
+void sk_fclose(SkFILE* rec) {
+ SkASSERT(rec);
+ [rec->fData release];
+ delete rec;
+}
+
diff --git a/src/utils/ios/SkOSWindow_iOS.mm b/src/utils/ios/SkOSWindow_iOS.mm
new file mode 100755
index 0000000000..3611ba6377
--- /dev/null
+++ b/src/utils/ios/SkOSWindow_iOS.mm
@@ -0,0 +1,208 @@
+#import <UIKit/UIKit.h>
+#import <OpenGLES/EAGL.h>
+#import <OpenGLES/ES1/gl.h>
+#include "SkTypes.h"
+#include "SkWindow.h"
+#include "SkCanvas.h"
+#include "SkOSMenu.h"
+#include "SkTime.h"
+#include "SkGraphics.h"
+
+#define kINVAL_UIVIEW_EventType "inval-uiview"
+#include "SkIOSNotifier.h"
+#import "SkUIView_shell.h"
+
+SkOSWindow::SkOSWindow(void* hWnd) : fHWND(hWnd) {
+ fInvalEventIsPending = false;
+ fNotifier = [[SkIOSNotifier alloc] init];
+}
+SkOSWindow::~SkOSWindow() {
+ [(SkIOSNotifier*)fNotifier release];
+}
+
+void SkOSWindow::onHandleInval(const SkIRect& r) {
+ if (!fInvalEventIsPending) {
+ fInvalEventIsPending = true;
+ (new SkEvent(kINVAL_UIVIEW_EventType))->post(this->getSinkID());
+ }
+}
+
+bool SkOSWindow::onEvent(const SkEvent& evt) {
+ if (evt.isType(kINVAL_UIVIEW_EventType)) {
+ fInvalEventIsPending = false;
+ const SkIRect& r = this->getDirtyBounds();
+ [(SkUIView_shell*)fHWND postInvalWithRect:&r];
+ return true;
+ }
+ if ([(SkUIView_shell*)fHWND onHandleEvent:evt]) {
+ return true;
+ }
+ return INHERITED::onEvent(evt);
+}
+
+void SkOSWindow::onSetTitle(const char title[]) {
+ [(SkUIView_shell*)fHWND setSkTitle:title];
+}
+
+void SkOSWindow::onAddMenu(const SkOSMenu* sk_menu)
+{
+
+}
+
+///////////////////////////////////////////////////////////////////////////////////////
+/*
+ #if 1
+ static void NonEmptyCallback(CFRunLoopTimerRef timer, void*) {
+ // printf("------- event queue depth = %d\n", SkEvent::CountEventsOnQueue());
+
+ if (!SkEvent::ProcessEvent()) {
+ CFRunLoopTimerInvalidate(timer);
+ }
+ }
+
+ void SkEvent::SignalNonEmptyQueue() {
+ double tinyDelay = 1.0 / 60;
+ CFRunLoopTimerRef timer;
+
+ timer = CFRunLoopTimerCreate(NULL,
+ CACurrentMediaTime() + tinyDelay,
+ tinyDelay,
+ 0,
+ 0,
+ NonEmptyCallback,
+ NULL);
+ CFRunLoopAddTimer(CFRunLoopGetCurrent(),
+ timer,
+ kCFRunLoopCommonModes);
+ CFRelease(timer);
+ }
+ #elif 1
+ #if 0
+ #define NONE_EMPTY_CODE(code) code
+ #else
+ #define NONE_EMPTY_CODE(code)
+ #endif
+ static CFRunLoopSourceRef gNonEmptySource;
+ static CFRunLoopRef gNoneEmptyRunLoop;
+ static bool gAlreadySignaled;
+
+ static void signal_nonempty() {
+ if (!gAlreadySignaled) {
+ NONE_EMPTY_CODE(printf("--- before resignal\n");)
+ gAlreadySignaled = true;
+ CFRunLoopSourceSignal(gNonEmptySource);
+ CFRunLoopWakeUp(gNoneEmptyRunLoop);
+ NONE_EMPTY_CODE(printf("--- after resignal\n");)
+ }
+ }
+
+ static void NonEmptySourceCallback(void*) {
+ gAlreadySignaled = false;
+ NONE_EMPTY_CODE(printf("---- service NonEmptySourceCallback %d\n", SkEvent::CountEventsOnQueue());)
+ if (SkEvent::ProcessEvent()) {
+ signal_nonempty();
+ }
+ NONE_EMPTY_CODE(printf("----- after service\n");)
+ }
+
+ void SkEvent::SignalNonEmptyQueue() {
+ if (NULL == gNonEmptySource) {
+ gNoneEmptyRunLoop = CFRunLoopGetMain();
+
+ CFIndex order = 0; // should this be lower, to not start UIEvents?
+ CFRunLoopSourceContext context;
+ sk_bzero(&context, sizeof(context));
+ // give it a "unique" info, for the default Hash function
+ context.info = (void*)NonEmptySourceCallback;
+ // our perform callback
+ context.perform = NonEmptySourceCallback;
+ gNonEmptySource = CFRunLoopSourceCreate(NULL, order, &context);
+
+ CFRunLoopAddSource(gNoneEmptyRunLoop,
+ gNonEmptySource,
+ kCFRunLoopCommonModes);
+ }
+ signal_nonempty();
+ }
+ #elif 1
+ @interface NonEmptyHandler : NSObject {}
+ - (void)signalNonEmptyQ;
+ @end
+
+ @implementation NonEmptyHandler
+
+ - (void)callProccessEvent {
+ // printf("----- callProcessEvent\n");
+ if (SkEvent::ProcessEvent()) {
+ [self signalNonEmptyQ];
+ }
+ }
+
+ - (void)signalNonEmptyQ {
+ [self performSelectorOnMainThread:@selector(callProccessEvent) withObject:nil waitUntilDone:NO];
+ }
+
+ void SkEvent::SignalNonEmptyQueue() {
+ static id gNonEmptyQueueObject;
+ if (nil == gNonEmptyQueueObject) {
+ gNonEmptyQueueObject = [[NonEmptyHandler alloc] init];
+ }
+ [gNonEmptyQueueObject signalNonEmptyQ];
+ }
+
+ @end
+
+ #endif
+
+ ///////////////////////////////////////////////////////////////////////////////
+
+ static CFRunLoopTimerRef gTimer;
+
+ static void TimerCallback(CFRunLoopTimerRef timer, void* info) {
+ gTimer = NULL;
+ SkEvent::ServiceQueueTimer();
+ }
+
+ void SkEvent::SignalQueueTimer(SkMSec delay)
+ {
+ //We always release the timer right after we've added it to our RunLoop,
+ //thus we don't worry about freeing it later: if it fires our callback,
+ //it gets automatically freed, as it does if we call invalidate()
+
+ if (gTimer) {
+ // our callback wasn't called, so invalidate it
+ CFRunLoopTimerInvalidate(gTimer);
+ gTimer = NULL;
+ }
+
+ if (delay) {
+ gTimer = CFRunLoopTimerCreate(NULL,
+ CACurrentMediaTime() + delay/1000.0,
+ // CFAbsoluteTimeGetCurrent() + delay/1000.0,
+ 0,
+ 0,
+ 0,
+ TimerCallback,
+ NULL);
+ CFRunLoopAddTimer(CFRunLoopGetCurrent(),
+ gTimer,
+ kCFRunLoopCommonModes);
+ CFRelease(gTimer);
+ }
+ }
+ */
+///////////////////////////////////////////////////////////////////////////////////////
+
+bool SkOSWindow::attachGL()
+{
+ bool success = true;
+ return success;
+}
+
+void SkOSWindow::detachGL() {
+}
+
+void SkOSWindow::presentGL() {
+ glFlush();
+}
+
diff --git a/src/utils/ios/SkStream_NSData.mm b/src/utils/ios/SkStream_NSData.mm
new file mode 100755
index 0000000000..0586cd6fd2
--- /dev/null
+++ b/src/utils/ios/SkStream_NSData.mm
@@ -0,0 +1,41 @@
+/*
+ Copyright 2010, Tetrark Inc.
+ */
+
+#include "SkStream_NSData.h"
+
+NSData* NSData_dataWithStream(SkStream* stream) {
+ size_t length = stream->getLength();
+ void* src = malloc(length);
+ size_t bytes = stream->read(src, length);
+ SkASSERT(bytes == length);
+ return [NSData dataWithBytesNoCopy:src length:length freeWhenDone:YES];
+}
+
+NSData* NSData_dataFromResource(const char cname[], const char csuffix[]) {
+ NSBundle* bundle = [NSBundle mainBundle];
+ NSString* name = [NSString stringWithUTF8String:cname];
+ NSString* suffix = [NSString stringWithUTF8String:csuffix];
+ NSString* path = [bundle pathForResource:name ofType:suffix];
+ return [NSData dataWithContentsOfMappedFile:path];
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+SkStream_NSData::SkStream_NSData(NSData* data) {
+ fNSData = data;
+ [fNSData retain];
+
+ this->setMemory([fNSData bytes], [fNSData length], false);
+}
+
+SkStream_NSData::~SkStream_NSData() {
+ [fNSData release];
+}
+
+SkStream_NSData* SkStream_NSData::CreateFromResource(const char name[],
+ const char suffix[]) {
+ NSData* data = NSData_dataFromResource(name, suffix);
+ return SkNEW_ARGS(SkStream_NSData, (data));
+}
+