refactor fonthost_tables into wrapper (fonthost) and impl (fontstream)
authorreed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Mon, 4 Mar 2013 15:16:06 +0000 (15:16 +0000)
committerreed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Mon, 4 Mar 2013 15:16:06 +0000 (15:16 +0000)
git-svn-id: http://skia.googlecode.com/svn/trunk@7958 2bbb7eff-a529-9590-31e7-b0007b416f81

gyp/core.gypi
src/core/SkFontStream.cpp [new file with mode: 0644]
src/core/SkFontStream.h [new file with mode: 0644]
src/ports/SkFontHost_tables.cpp

index 590cac2..e6f917f 100644 (file)
@@ -88,6 +88,8 @@
         '<(skia_src_path)/core/SkFontHost.cpp',
         '<(skia_src_path)/core/SkFontDescriptor.cpp',
         '<(skia_src_path)/core/SkFontDescriptor.h',
+        '<(skia_src_path)/core/SkFontStream.cpp',
+        '<(skia_src_path)/core/SkFontStream.h',
         '<(skia_src_path)/core/SkGeometry.cpp',
         '<(skia_src_path)/core/SkGlyphCache.cpp',
         '<(skia_src_path)/core/SkGlyphCache.h',
diff --git a/src/core/SkFontStream.cpp b/src/core/SkFontStream.cpp
new file mode 100644 (file)
index 0000000..0b37fb1
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkEndian.h"
+#include "SkFontStream.h"
+#include "SkStream.h"
+
+struct SkSFNTHeader {
+    uint32_t    fVersion;
+    uint16_t    fNumTables;
+    uint16_t    fSearchRange;
+    uint16_t    fEntrySelector;
+    uint16_t    fRangeShift;
+};
+
+struct SkTTCFHeader {
+    uint32_t    fTag;
+    uint32_t    fVersion;
+    uint32_t    fNumOffsets;
+    uint32_t    fOffset0;   // the first of N (fNumOffsets)
+};
+
+union SkSharedTTHeader {
+    SkSFNTHeader    fSingle;
+    SkTTCFHeader    fCollection;
+};
+
+struct SkSFNTDirEntry {
+    uint32_t    fTag;
+    uint32_t    fChecksum;
+    uint32_t    fOffset;
+    uint32_t    fLength;
+};
+
+/** Return the number of tables, or if this is a TTC (collection), return the
+    number of tables in the first element of the collection. In either case,
+    if offsetToDir is not-null, set it to the offset to the beginning of the
+    table headers (SkSFNTDirEntry), relative to the start of the stream.
+
+    On an error, return 0 for number of tables, and ignore offsetToDir
+ */
+static int count_tables(SkStream* stream, size_t* offsetToDir = NULL) {
+    SkSharedTTHeader shared;
+    if (stream->read(&shared, sizeof(shared)) != sizeof(shared)) {
+        return 0;
+    }
+
+    // by default, SkSFNTHeader is at the start of the stream
+    size_t offset = 0;
+
+    // if we're really a collection, the first 4-bytes will be 'ttcf'
+    uint32_t tag = SkEndian_SwapBE32(shared.fCollection.fTag);
+    if (SkSetFourByteTag('t', 't', 'c', 'f') == tag) {
+        if (shared.fCollection.fNumOffsets == 0) {
+            return 0;
+        }
+        // this is the offset to the first local SkSFNTHeader
+        offset = SkEndian_SwapBE32(shared.fCollection.fOffset0);
+        stream->rewind();
+        if (stream->skip(offset) != offset) {
+            return 0;
+        }
+        if (stream->read(&shared, sizeof(shared)) != sizeof(shared)) {
+            return 0;
+        }
+    }
+
+    if (offsetToDir) {
+        // add the size of the header, so we will point to the DirEntries
+        *offsetToDir = offset + sizeof(SkSFNTHeader);
+    }
+    return SkEndian_SwapBE16(shared.fSingle.fNumTables);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+struct SfntHeader {
+    SfntHeader() : fCount(0), fDir(NULL) {}
+    ~SfntHeader() { sk_free(fDir); }
+
+    /** If it returns true, then fCount and fDir are properly initialized.
+        Note: fDir will point to the raw array of SkSFNTDirEntry values,
+        meaning they will still be in the file's native endianness (BE).
+
+        fDir will be automatically freed when this object is destroyed
+     */
+    bool init(SkStream* stream) {
+        size_t offsetToDir;
+        fCount = count_tables(stream, &offsetToDir);
+        if (0 == fCount) {
+            return false;
+        }
+
+        stream->rewind();
+        if (stream->skip(offsetToDir) != offsetToDir) {
+            return false;
+        }
+
+        size_t size = fCount * sizeof(SkSFNTDirEntry);
+        fDir = reinterpret_cast<SkSFNTDirEntry*>(sk_malloc_throw(size));
+        return stream->read(fDir, size) == size;
+    }
+
+    int             fCount;
+    SkSFNTDirEntry* fDir;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+int SkFontStream::GetTableTags(SkStream* stream, SkFontTableTag tags[]) {
+    SfntHeader  header;
+    if (!header.init(stream)) {
+        return 0;
+    }
+
+    if (tags) {
+        for (int i = 0; i < header.fCount; i++) {
+            tags[i] = SkEndian_SwapBE32(header.fDir[i].fTag);
+        }
+    }
+    return header.fCount;
+}
+
+size_t SkFontStream::GetTableData(SkStream* stream, SkFontTableTag tag,
+                                  size_t offset, size_t length, void* data) {
+    SfntHeader  header;
+    if (!header.init(stream)) {
+        return 0;
+    }
+
+    for (int i = 0; i < header.fCount; i++) {
+        if (SkEndian_SwapBE32(header.fDir[i].fTag) == tag) {
+            size_t realOffset = SkEndian_SwapBE32(header.fDir[i].fOffset);
+            size_t realLength = SkEndian_SwapBE32(header.fDir[i].fLength);
+            // now sanity check the caller's offset/length
+            if (offset >= realLength) {
+                return 0;
+            }
+            // if the caller is trusting the length from the file, then a
+            // hostile file might choose a value which would overflow offset +
+            // length.
+            if (offset + length < offset) {
+                return 0;
+            }
+            if (length > realLength - offset) {
+                length = realLength - offset;
+            }
+            if (data) {
+                // skip the stream to the part of the table we want to copy from
+                stream->rewind();
+                size_t bytesToSkip = realOffset + offset;
+                if (stream->skip(bytesToSkip) != bytesToSkip) {
+                    return 0;
+                }
+                if (stream->read(data, length) != length) {
+                    return 0;
+                }
+            }
+            return length;
+        }
+    }
+    return 0;
+}
+
+
diff --git a/src/core/SkFontStream.h b/src/core/SkFontStream.h
new file mode 100644 (file)
index 0000000..787a986
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkFontStream_DEFINED
+#define SkFontStream_DEFINED
+
+class SkStream;
+
+#include "SkTypeface.h"
+
+class SkFontStream {
+public:
+    static int GetTableTags(SkStream*, SkFontTableTag tags[]);
+    static size_t GetTableData(SkStream*, SkFontTableTag tag,
+                               size_t offset, size_t length, void* data);
+};
+
+#endif
+
+
index 38d2e60..bd767f8 100644 (file)
-
 /*
  * Copyright 2011 Google Inc.
  *
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
+
 #include "SkEndian.h"
 #include "SkFontHost.h"
+#include "SkFontStream.h"
 #include "SkStream.h"
 
-struct SkSFNTHeader {
-    uint32_t    fVersion;
-    uint16_t    fNumTables;
-    uint16_t    fSearchRange;
-    uint16_t    fEntrySelector;
-    uint16_t    fRangeShift;
-};
-
-struct SkTTCFHeader {
-    uint32_t    fTag;
-    uint32_t    fVersion;
-    uint32_t    fNumOffsets;
-    uint32_t    fOffset0;   // the first of N (fNumOffsets)
-};
-
-union SkSharedTTHeader {
-    SkSFNTHeader    fSingle;
-    SkTTCFHeader    fCollection;
-};
-
-struct SkSFNTDirEntry {
-    uint32_t    fTag;
-    uint32_t    fChecksum;
-    uint32_t    fOffset;
-    uint32_t    fLength;
-};
-
-/** Return the number of tables, or if this is a TTC (collection), return the
-    number of tables in the first element of the collection. In either case,
-    if offsetToDir is not-null, set it to the offset to the beginning of the
-    table headers (SkSFNTDirEntry), relative to the start of the stream.
-
-    On an error, return 0 for number of tables, and ignore offsetToDir
- */
-static int count_tables(SkStream* stream, size_t* offsetToDir = NULL) {
-    SkSharedTTHeader shared;
-    if (stream->read(&shared, sizeof(shared)) != sizeof(shared)) {
-        return 0;
-    }
-
-    // by default, SkSFNTHeader is at the start of the stream
-    size_t offset = 0;
-
-    // if we're really a collection, the first 4-bytes will be 'ttcf'
-    uint32_t tag = SkEndian_SwapBE32(shared.fCollection.fTag);
-    if (SkSetFourByteTag('t', 't', 'c', 'f') == tag) {
-        if (shared.fCollection.fNumOffsets == 0) {
-            return 0;
-        }
-        // this is the offset to the first local SkSFNTHeader
-        offset = SkEndian_SwapBE32(shared.fCollection.fOffset0);
-        stream->rewind();
-        if (stream->skip(offset) != offset) {
-            return 0;
-        }
-        if (stream->read(&shared, sizeof(shared)) != sizeof(shared)) {
-            return 0;
-        }
-    }
-
-    if (offsetToDir) {
-        // add the size of the header, so we will point to the DirEntries
-        *offsetToDir = offset + sizeof(SkSFNTHeader);
-    }
-    return SkEndian_SwapBE16(shared.fSingle.fNumTables);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-struct SfntHeader {
-    SfntHeader() : fCount(0), fDir(NULL) {}
-    ~SfntHeader() { sk_free(fDir); }
-
-    /** If it returns true, then fCount and fDir are properly initialized.
-        Note: fDir will point to the raw array of SkSFNTDirEntry values,
-        meaning they will still be in the file's native endianness (BE).
-
-        fDir will be automatically freed when this object is destroyed
-     */
-    bool init(SkStream* stream) {
-        size_t offsetToDir;
-        fCount = count_tables(stream, &offsetToDir);
-        if (0 == fCount) {
-            return false;
-        }
-
-        stream->rewind();
-        if (stream->skip(offsetToDir) != offsetToDir) {
-            return false;
-        }
-
-        size_t size = fCount * sizeof(SkSFNTDirEntry);
-        fDir = reinterpret_cast<SkSFNTDirEntry*>(sk_malloc_throw(size));
-        return stream->read(fDir, size) == size;
-    }
-
-    int             fCount;
-    SkSFNTDirEntry* fDir;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
 int SkFontHost::CountTables(SkFontID fontID) {
     SkStream* stream = SkFontHost::OpenStream(fontID);
     if (NULL == stream) {
@@ -118,7 +17,7 @@ int SkFontHost::CountTables(SkFontID fontID) {
     }
 
     SkAutoUnref au(stream);
-    return count_tables(stream);
+    return SkFontStream::GetTableTags(stream, NULL);
 }
 
 int SkFontHost::GetTableTags(SkFontID fontID, SkFontTableTag tags[]) {
@@ -128,15 +27,7 @@ int SkFontHost::GetTableTags(SkFontID fontID, SkFontTableTag tags[]) {
     }
 
     SkAutoUnref au(stream);
-    SfntHeader  header;
-    if (!header.init(stream)) {
-        return 0;
-    }
-
-    for (int i = 0; i < header.fCount; i++) {
-        tags[i] = SkEndian_SwapBE32(header.fDir[i].fTag);
-    }
-    return header.fCount;
+    return SkFontStream::GetTableTags(stream, tags);
 }
 
 size_t SkFontHost::GetTableSize(SkFontID fontID, SkFontTableTag tag) {
@@ -146,17 +37,7 @@ size_t SkFontHost::GetTableSize(SkFontID fontID, SkFontTableTag tag) {
     }
 
     SkAutoUnref au(stream);
-    SfntHeader  header;
-    if (!header.init(stream)) {
-        return 0;
-    }
-
-    for (int i = 0; i < header.fCount; i++) {
-        if (SkEndian_SwapBE32(header.fDir[i].fTag) == tag) {
-            return SkEndian_SwapBE32(header.fDir[i].fLength);
-        }
-    }
-    return 0;
+    return SkFontStream::GetTableData(stream, tag, 0, ~0U, NULL);
 }
 
 size_t SkFontHost::GetTableData(SkFontID fontID, SkFontTableTag tag,
@@ -167,39 +48,7 @@ size_t SkFontHost::GetTableData(SkFontID fontID, SkFontTableTag tag,
     }
 
     SkAutoUnref au(stream);
-    SfntHeader  header;
-    if (!header.init(stream)) {
-        return 0;
-    }
-
-    for (int i = 0; i < header.fCount; i++) {
-        if (SkEndian_SwapBE32(header.fDir[i].fTag) == tag) {
-            size_t realOffset = SkEndian_SwapBE32(header.fDir[i].fOffset);
-            size_t realLength = SkEndian_SwapBE32(header.fDir[i].fLength);
-            // now sanity check the caller's offset/length
-            if (offset >= realLength) {
-                return 0;
-            }
-            // if the caller is trusting the length from the file, then a
-            // hostile file might choose a value which would overflow offset +
-            // length.
-            if (offset + length < offset) {
-                return 0;
-            }
-            if (offset + length > realLength) {
-                length = realLength - offset;
-            }
-            // skip the stream to the part of the table we want to copy from
-            stream->rewind();
-            size_t bytesToSkip = realOffset + offset;
-            if (stream->skip(bytesToSkip) != bytesToSkip) {
-                return 0;
-            }
-            if (stream->read(data, length) != length) {
-                return 0;
-            }
-            return length;
-        }
-    }
-    return 0;
+    return SkFontStream::GetTableData(stream, tag, offset, length, data);
 }
+
+