add SkCreateDataProviderFromStream to SkCGUtils
authorreed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Fri, 24 Feb 2012 15:29:00 +0000 (15:29 +0000)
committerreed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Fri, 24 Feb 2012 15:29:00 +0000 (15:29 +0000)
implement SkFontHost create_from_file/stream using SkCGUtils

git-svn-id: http://skia.googlecode.com/svn/trunk@3249 2bbb7eff-a529-9590-31e7-b0007b416f81

gyp/ports.gyp
include/utils/mac/SkCGUtils.h
src/ports/SkFontHost_mac_coretext.cpp
src/utils/mac/SkStream_mac.cpp [new file with mode: 0644]

index 148197d..5dc88d5 100644 (file)
@@ -48,6 +48,7 @@
           ],
           'sources': [
             '../src/ports/SkFontHost_mac_coretext.cpp',
+            '../src/utils/mac/SkStream_mac.cpp',
 #            '../src/ports/SkFontHost_FreeType.cpp',
 #            '../src/ports/SkFontHost_freetype_mac.cpp',
 #            '../src/ports/SkFontHost_gamma_none.cpp',
index 9848d22..46f8996 100644 (file)
@@ -46,4 +46,19 @@ void SkCGDrawBitmap(CGContextRef, const SkBitmap&, float x, float y);
 
 bool SkPDFDocumentToBitmap(SkStream* stream, SkBitmap* output);
 
+/**
+ *  Return a provider that wraps the specified stream. It will become an
+ *  owner of the stream, so the caller must still manage its ownership.
+ *
+ *  To hand-off ownership of the stream to the provider, the caller must do
+ *  something like the following:
+ *
+ *  SkStream* stream = new ...;
+ *  CGDataProviderRef provider = SkStreamToDataProvider(stream);
+ *  stream->unref();
+ *
+ *  Now when the provider is finally deleted, it will delete the stream.
+ */
+CGDataProviderRef SkCreateDataProviderFromStream(SkStream*);
+
 #endif
index 914ceb0..cd2dbf6 100644 (file)
@@ -18,6 +18,7 @@
 #endif
 
 #include "SkFontHost.h"
+#include "SkCGUtils.h"
 #include "SkDescriptor.h"
 #include "SkEndian.h"
 #include "SkFloatingPoint.h"
@@ -1487,16 +1488,43 @@ void SkScalerContext_Mac::CTPathElement(void *info, const CGPathElement *element
 
 ///////////////////////////////////////////////////////////////////////////////
 
-SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream)
-{
-//    SkDEBUGFAIL("SkFontHost::CreateTypefaceFromStream unimplemented");
-    return SkFontHost::CreateTypeface(NULL, NULL, NULL, NULL, SkTypeface::kNormal);
+// Returns NULL on failure
+// Call must still manage its ownership of provider
+static SkTypeface* create_from_dataProvider(CGDataProviderRef provider) {
+    CGFontRef cg = CGFontCreateWithDataProvider(provider);
+    if (NULL == cg) {
+        return NULL;
+    }
+    CTFontRef ct = CTFontCreateWithGraphicsFont(cg, 0, NULL, NULL);
+    CGFontRelease(cg);
+    return cg ? SkCreateTypefaceFromCTFont(ct) : NULL;
 }
 
-SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[])
-{
-//    SkDEBUGFAIL("SkFontHost::CreateTypefaceFromFile unimplemented");
-    return SkFontHost::CreateTypeface(NULL, NULL, NULL, NULL, SkTypeface::kNormal);
+class AutoCGDataProviderRelease : SkNoncopyable {
+public:
+    AutoCGDataProviderRelease(CGDataProviderRef provider) : fProvider(provider) {}
+    ~AutoCGDataProviderRelease() { CGDataProviderRelease(fProvider); }
+    
+private:
+    CGDataProviderRef fProvider;
+};
+
+SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
+    CGDataProviderRef provider = SkCreateDataProviderFromStream(stream);
+    if (NULL == provider) {
+        return NULL;
+    }
+    AutoCGDataProviderRelease ar(provider);
+    return create_from_dataProvider(provider);
+}
+
+SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
+    CGDataProviderRef provider = CGDataProviderCreateWithFilename(path);
+    if (NULL == provider) {
+        return NULL;
+    }
+    AutoCGDataProviderRelease ar(provider);
+    return create_from_dataProvider(provider);
 }
 
 // Web fonts added to the the CTFont registry do not return their character set.
diff --git a/src/utils/mac/SkStream_mac.cpp b/src/utils/mac/SkStream_mac.cpp
new file mode 100644 (file)
index 0000000..97df430
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkCGUtils.h"
+#include "SkStream.h"
+
+// This is used by CGDataProviderCreateWithData
+
+static void unref_data_proc(void* info, const void* addr, size_t size) {
+    SkASSERT(info);
+    ((SkRefCnt*)info)->unref();
+}
+
+// These are used by CGDataProviderSequentialCallbacks
+
+size_t get_bytes_proc(void* info, void* buffer, size_t bytes) {
+    SkASSERT(info);
+    return ((SkStream*)info)->read(buffer, bytes);
+}
+
+static off_t skip_forward_proc(void* info, off_t bytes) {
+    return ((SkStream*)info)->skip(bytes);
+}
+
+static void rewind_proc(void* info) {
+    SkASSERT(info);
+    ((SkStream*)info)->rewind();
+}
+
+static void release_info_proc(void* info) {
+    SkASSERT(info);
+    ((SkStream*)info)->unref();
+}
+
+CGDataProviderRef SkCreateDataProviderFromStream(SkStream* stream) {
+    stream->ref();  // unref will be called when the provider is deleted
+
+    const void* addr = stream->getMemoryBase();
+    if (addr) {
+        // special-case when the stream is just a block of ram
+        return CGDataProviderCreateWithData(stream, addr, stream->getLength(),
+                                            unref_data_proc);
+    }
+
+    CGDataProviderSequentialCallbacks rec;
+    sk_bzero(&rec, sizeof(rec));
+    rec.version = 0;
+    rec.getBytes = get_bytes_proc;
+    rec.skipForward = skip_forward_proc;
+    rec.rewind = rewind_proc;
+    rec.releaseInfo = release_info_proc;
+    return CGDataProviderCreateSequential(stream, &rec);
+}
+
+