diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-11 12:11:56 -0700 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-11 12:11:56 -0700 |
commit | 5956d1c224aadf1d2712b46b32d3fc69a19915bd (patch) | |
tree | 5ab68a461e0f60a8c80b2f9f4cc1798271849283 | |
parent | 4b86a58dcecc030f2220cb91f4744f8099e7dfe6 (diff) | |
download | external_skia-5956d1c224aadf1d2712b46b32d3fc69a19915bd.zip external_skia-5956d1c224aadf1d2712b46b32d3fc69a19915bd.tar.gz external_skia-5956d1c224aadf1d2712b46b32d3fc69a19915bd.tar.bz2 |
auto import from //branches/cupcake/...@137873
-rw-r--r-- | include/core/SkGraphics.h | 2 | ||||
-rw-r--r-- | include/core/SkPathMeasure.h | 1 | ||||
-rw-r--r-- | include/core/SkStream.h | 4 | ||||
-rw-r--r-- | include/core/SkTSearch.h | 2 | ||||
-rw-r--r-- | include/core/SkTypeface.h | 6 | ||||
-rw-r--r-- | samplecode/SampleApp.cpp | 2 | ||||
-rw-r--r-- | src/core/SkGraphics.cpp | 29 | ||||
-rw-r--r-- | src/core/SkPathMeasure.cpp | 37 | ||||
-rw-r--r-- | src/core/SkStream.cpp | 118 | ||||
-rw-r--r-- | src/core/SkTSearch.cpp | 32 | ||||
-rw-r--r-- | src/core/SkTypeface.cpp | 24 | ||||
-rw-r--r-- | src/ports/SkFontHost_FONTPATH.cpp | 324 | ||||
-rw-r--r-- | src/ports/SkFontHost_ascender.cpp | 211 | ||||
-rw-r--r-- | src/ports/SkFontHost_linux.cpp | 594 | ||||
-rwxr-xr-x | src/ports/SkFontHost_mac.cpp | 572 | ||||
-rw-r--r-- | src/ports/SkFontHost_none.cpp | 86 | ||||
-rw-r--r-- | src/ports/SkFontHost_win.cpp | 602 | ||||
-rw-r--r-- | src/ports/SkImageDecoder_CG.cpp | 192 |
18 files changed, 10 insertions, 2828 deletions
diff --git a/include/core/SkGraphics.h b/include/core/SkGraphics.h index cb06128..1862a2b 100644 --- a/include/core/SkGraphics.h +++ b/include/core/SkGraphics.h @@ -21,7 +21,7 @@ class SkGraphics { public: - static void Init(bool runUnitTests); + static void Init(); static void Term(); /** Return the (approximate) number of bytes used by the font cache. diff --git a/include/core/SkPathMeasure.h b/include/core/SkPathMeasure.h index 5ab97ca..2d94ae2 100644 --- a/include/core/SkPathMeasure.h +++ b/include/core/SkPathMeasure.h @@ -80,7 +80,6 @@ public: #ifdef SK_DEBUG void dump(); - static void UnitTest(); #endif private: diff --git a/include/core/SkStream.h b/include/core/SkStream.h index 26ef43f..3a82991 100644 --- a/include/core/SkStream.h +++ b/include/core/SkStream.h @@ -68,8 +68,6 @@ public: bool readBool() { return this->readU8() != 0; } SkScalar readScalar(); size_t readPackedUInt(); - - static void UnitTest(); }; class SkWStream : SkNoncopyable { @@ -101,8 +99,6 @@ public: bool writePackedUInt(size_t); bool writeStream(SkStream* input, size_t length); - - static void UnitTest(); }; //////////////////////////////////////////////////////////////////////////////////////// diff --git a/include/core/SkTSearch.h b/include/core/SkTSearch.h index f29e6f5..e208071 100644 --- a/include/core/SkTSearch.h +++ b/include/core/SkTSearch.h @@ -161,7 +161,5 @@ extern "C" { void SkQSort(void* base, size_t count, size_t elemSize, SkQSortCompareProc); } -SkDEBUGCODE(void SkQSort_UnitTest();) - #endif diff --git a/include/core/SkTypeface.h b/include/core/SkTypeface.h index ed45c03..bf783a3 100644 --- a/include/core/SkTypeface.h +++ b/include/core/SkTypeface.h @@ -110,7 +110,7 @@ public: typeface referencing the same font when Deserialize is called. */ void serialize(SkWStream*) const; - + /** Given the data previously written by serialize(), return a new instance to a typeface referring to the same font. If that font is not available, return null. If an instance is returned, the caller is responsible for @@ -121,8 +121,8 @@ public: protected: /** uniqueID must be unique (please!) and non-zero */ - SkTypeface(Style style, uint32_t uniqueID); - virtual ~SkTypeface(); + SkTypeface(Style style, uint32_t uniqueID) + : fUniqueID(uniqueID), fStyle(style) {} private: uint32_t fUniqueID; diff --git a/samplecode/SampleApp.cpp b/samplecode/SampleApp.cpp index 0d2bbbc..3a81902 100644 --- a/samplecode/SampleApp.cpp +++ b/samplecode/SampleApp.cpp @@ -597,7 +597,7 @@ void get_preferred_size(int* x, int* y, int* width, int* height) { void application_init() { // setenv("ANDROID_ROOT", "../../../data", 0); setenv("ANDROID_ROOT", "/android/device/data", 0); - SkGraphics::Init(true); + SkGraphics::Init(); SkEvent::Init(); } diff --git a/src/core/SkGraphics.cpp b/src/core/SkGraphics.cpp index ff41f0c..7e72c3f 100644 --- a/src/core/SkGraphics.cpp +++ b/src/core/SkGraphics.cpp @@ -27,7 +27,6 @@ #include "SkMatrix.h" #include "SkPath.h" #include "SkPathEffect.h" -#include "SkPathMeasure.h" #include "SkRandom.h" #include "SkRefCnt.h" #include "SkScalerContext.h" @@ -78,7 +77,6 @@ static void test_sort() #define SPEED_TESTx #define typesizeline(type) { #type , sizeof(type) } -#define unittestline(type) { #type , type::UnitTest } #ifdef BUILD_EMBOSS_TABLE @@ -271,7 +269,7 @@ static float time_intToFloat() { #endif #endif -void SkGraphics::Init(bool runUnitTests) +void SkGraphics::Init() { SkGlobals::Init(); @@ -287,9 +285,7 @@ void SkGraphics::Init(bool runUnitTests) SkRadialGradient_BuildTable(); #endif -#ifdef SK_SUPPORT_UNITTEST - if (runUnitTests == false) - return; +#ifdef SK_DEBUGx int i; static const struct { @@ -337,25 +333,10 @@ void SkGraphics::Init(bool runUnitTests) else SkDebugf("SkGraphics: char is unsigned\n"); } - for (i = 0; i < (int)SK_ARRAY_COUNT(gTypeSize); i++) - SkDebugf("SkGraphics: sizeof(%s) = %d\n", gTypeSize[i].fTypeName, gTypeSize[i].fSizeOf); - - static const struct { - const char* fTypeName; - void (*fUnitTest)(); - } gUnitTests[] = { - unittestline(SkPathMeasure), - unittestline(SkStream), - unittestline(SkWStream), - }; - - for (i = 0; i < (int)SK_ARRAY_COUNT(gUnitTests); i++) - { - SkDebugf("SkGraphics: Running UnitTest for %s\n", gUnitTests[i].fTypeName); - gUnitTests[i].fUnitTest(); - SkDebugf("SkGraphics: End UnitTest for %s\n", gUnitTests[i].fTypeName); + for (i = 0; i < (int)SK_ARRAY_COUNT(gTypeSize); i++) { + SkDebugf("SkGraphics: sizeof(%s) = %d\n", + gTypeSize[i].fTypeName, gTypeSize[i].fSizeOf); } - SkQSort_UnitTest(); #endif diff --git a/src/core/SkPathMeasure.cpp b/src/core/SkPathMeasure.cpp index ec1510d..99bdece 100644 --- a/src/core/SkPathMeasure.cpp +++ b/src/core/SkPathMeasure.cpp @@ -558,41 +558,4 @@ void SkPathMeasure::dump() { } } -void SkPathMeasure::UnitTest() { -#ifdef SK_SUPPORT_UNITTEST - SkPath path; - - path.moveTo(0, 0); - path.lineTo(SK_Scalar1, 0); - path.lineTo(SK_Scalar1, SK_Scalar1); - path.lineTo(0, SK_Scalar1); - - SkPathMeasure meas(path, true); - SkScalar length = meas.getLength(); - SkASSERT(length == SK_Scalar1*4); - - path.reset(); - path.moveTo(0, 0); - path.lineTo(SK_Scalar1*3, SK_Scalar1*4); - meas.setPath(&path, false); - length = meas.getLength(); - SkASSERT(length == SK_Scalar1*5); - - path.reset(); - path.addCircle(0, 0, SK_Scalar1); - meas.setPath(&path, true); - length = meas.getLength(); - SkDebugf("circle arc-length = %g\n", length); - - for (int i = 0; i < 8; i++) { - SkScalar d = length * i / 8; - SkPoint p; - SkVector v; - meas.getPosTan(d, &p, &v); - SkDebugf("circle arc-length=%g, pos[%g %g] tan[%g %g]\n", - d, p.fX, p.fY, v.fX, v.fY); - } -#endif -} - #endif diff --git a/src/core/SkStream.cpp b/src/core/SkStream.cpp index b199a1b..6571328 100644 --- a/src/core/SkStream.cpp +++ b/src/core/SkStream.cpp @@ -736,121 +736,3 @@ bool SkDebugWStream::write(const void* buffer, size_t size) return true; } -///////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////// - -#ifdef SK_DEBUG - -#include "SkRandom.h" - -#ifdef SK_SUPPORT_UNITTEST -#define MAX_SIZE (256 * 1024) - -static void random_fill(SkRandom& rand, void* buffer, size_t size) { - char* p = (char*)buffer; - char* stop = p + size; - while (p < stop) { - *p++ = (char)(rand.nextU() >> 8); - } -} - -static void test_buffer() { - SkRandom rand; - SkAutoMalloc am(MAX_SIZE * 2); - char* storage = (char*)am.get(); - char* storage2 = storage + MAX_SIZE; - - random_fill(rand, storage, MAX_SIZE); - - for (int sizeTimes = 0; sizeTimes < 100; sizeTimes++) { - int size = rand.nextU() % MAX_SIZE; - if (size == 0) { - size = MAX_SIZE; - } - for (int times = 0; times < 100; times++) { - int bufferSize = 1 + (rand.nextU() & 0xFFFF); - SkMemoryStream mstream(storage, size); - SkBufferStream bstream(&mstream, bufferSize); - - int bytesRead = 0; - while (bytesRead < size) { - int s = 17 + (rand.nextU() & 0xFFFF); - int ss = bstream.read(storage2, s); - SkASSERT(ss > 0 && ss <= s); - SkASSERT(bytesRead + ss <= size); - SkASSERT(memcmp(storage + bytesRead, storage2, ss) == 0); - bytesRead += ss; - } - SkASSERT(bytesRead == size); - } - } -} -#endif - -void SkStream::UnitTest() { -#ifdef SK_SUPPORT_UNITTEST - { - static const char s[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - char copy[sizeof(s)]; - SkRandom rand; - - for (int i = 0; i < 65; i++) - { - char* copyPtr = copy; - SkMemoryStream mem(s, sizeof(s)); - SkBufferStream buff(&mem, i); - - do { - copyPtr += buff.read(copyPtr, rand.nextU() & 15); - } while (copyPtr < copy + sizeof(s)); - SkASSERT(copyPtr == copy + sizeof(s)); - SkASSERT(memcmp(s, copy, sizeof(s)) == 0); - } - } - test_buffer(); -#endif -} - -void SkWStream::UnitTest() -{ -#ifdef SK_SUPPORT_UNITTEST - { - SkDebugWStream s; - - s.writeText("testing wstream helpers\n"); - s.writeText("compare: 0 "); s.writeDecAsText(0); s.newline(); - s.writeText("compare: 591 "); s.writeDecAsText(591); s.newline(); - s.writeText("compare: -9125 "); s.writeDecAsText(-9125); s.newline(); - s.writeText("compare: 0 "); s.writeHexAsText(0, 0); s.newline(); - s.writeText("compare: 03FA "); s.writeHexAsText(0x3FA, 4); s.newline(); - s.writeText("compare: DEADBEEF "); s.writeHexAsText(0xDEADBEEF, 4); s.newline(); - s.writeText("compare: 0 "); s.writeScalarAsText(SkIntToScalar(0)); s.newline(); - s.writeText("compare: 27 "); s.writeScalarAsText(SkIntToScalar(27)); s.newline(); - s.writeText("compare: -119 "); s.writeScalarAsText(SkIntToScalar(-119)); s.newline(); - s.writeText("compare: 851.3333 "); s.writeScalarAsText(SkIntToScalar(851) + SK_Scalar1/3); s.newline(); - s.writeText("compare: -0.08 "); s.writeScalarAsText(-SK_Scalar1*8/100); s.newline(); - } - - { - SkDynamicMemoryWStream ds; - const char s[] = "abcdefghijklmnopqrstuvwxyz"; - int i; - for (i = 0; i < 100; i++) { - bool result = ds.write(s, 26); - SkASSERT(result); - } - SkASSERT(ds.getOffset() == 100 * 26); - char* dst = new char[100 * 26 + 1]; - dst[100*26] = '*'; - ds.copyTo(dst); - SkASSERT(dst[100*26] == '*'); - // char* p = dst; - for (i = 0; i < 100; i++) - SkASSERT(memcmp(&dst[i * 26], s, 26) == 0); - SkASSERT(memcmp(dst, ds.getStream(), 100*26) == 0); - delete[] dst; - } -#endif -} - -#endif diff --git a/src/core/SkTSearch.cpp b/src/core/SkTSearch.cpp index bab348f..6d9ff81 100644 --- a/src/core/SkTSearch.cpp +++ b/src/core/SkTSearch.cpp @@ -185,35 +185,3 @@ void SkQSort(void* base, size_t count, size_t elemSize, SkQSortCompareProc compa SkQSort_Partition((char*)base, (char*)base + (count - 1) * elemSize, elemSize, compare); } -#ifdef SK_DEBUG - -#include "SkRandom.h" - -#ifdef SK_SUPPORT_UNITTEST -extern "C" { - int compare_int(const void* a, const void* b) - { - return *(const int*)a - *(const int*)b; - } -} -#endif - -void SkQSort_UnitTest() -{ -#ifdef SK_SUPPORT_UNITTEST - int array[100]; - SkRandom rand; - - for (int i = 0; i < 1000; i++) - { - int j, count = rand.nextRangeU(1, SK_ARRAY_COUNT(array)); - for (j = 0; j < count; j++) - array[j] = rand.nextS() & 0xFF; - SkQSort(array, count, sizeof(int), compare_int); - for (j = 1; j < count; j++) - SkASSERT(array[j-1] <= array[j]); - } -#endif -} - -#endif diff --git a/src/core/SkTypeface.cpp b/src/core/SkTypeface.cpp index b87db6b..65052c1 100644 --- a/src/core/SkTypeface.cpp +++ b/src/core/SkTypeface.cpp @@ -1,30 +1,6 @@ #include "SkTypeface.h" #include "SkFontHost.h" -//#define TRACK_TYPEFACE_ALLOCS - -#ifdef TRACK_TYPEFACE_ALLOCS - static int32_t gTypefaceAllocCount; -#endif - -SkTypeface::SkTypeface(Style style, uint32_t uniqueID) - : fUniqueID(uniqueID), fStyle(style) { -#ifdef TRACK_TYPEFACE_ALLOCS - sk_atomic_inc(&gTypefaceAllocCount); - SkDebugf("+++ [%d] typeface %p [style=%d uniqueID=%d]\n", - gTypefaceAllocCount, this, style, uniqueID); -#endif -} - -SkTypeface::~SkTypeface() { -#ifdef TRACK_TYPEFACE_ALLOCS - SkDebugf("--- [%d] typeface %p\n", gTypefaceAllocCount, this); - sk_atomic_inc(&gTypefaceAllocCount); -#endif -} - -/////////////////////////////////////////////////////////////////////////////// - uint32_t SkTypeface::UniqueID(const SkTypeface* face) { if (face) { return face->uniqueID(); diff --git a/src/ports/SkFontHost_FONTPATH.cpp b/src/ports/SkFontHost_FONTPATH.cpp deleted file mode 100644 index ceab395..0000000 --- a/src/ports/SkFontHost_FONTPATH.cpp +++ /dev/null @@ -1,324 +0,0 @@ -/* libs/graphics/ports/SkFontHost_android.cpp -** -** Copyright 2006, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#include "SkFontHost.h" -#include "SkDescriptor.h" -#include "SkString.h" -#include "SkStream.h" -#include <stdio.h> - -/* define this if we can use mmap() to access fonts from the filesystem */ -#define SK_CAN_USE_MMAP - -#ifndef SK_FONTPATH - #define SK_FONTPATH "the complete path for a font file" -#endif - -struct FontFaceRec { - const char* fFileName; - uint8_t fFamilyIndex; - SkBool8 fBold; - SkBool8 fItalic; - - static const FontFaceRec& FindFace(const FontFaceRec rec[], int count, - int isBold, int isItalic); -}; - -struct FontFamilyRec { - const FontFaceRec* fFaces; - int fFaceCount; -}; - -const FontFaceRec& FontFaceRec::FindFace(const FontFaceRec rec[], int count, - int isBold, int isItalic) -{ - SkASSERT(count > 0); - - int i; - - // look for an exact match - for (i = 0; i < count; i++) { - if (rec[i].fBold == isBold && rec[i].fItalic == isItalic) - return rec[i]; - } - // look for a match in the bold field - for (i = 0; i < count; i++) { - if (rec[i].fBold == isBold) - return rec[i]; - } - // look for a normal/regular face - for (i = 0; i < count; i++) { - if (!rec[i].fBold && !rec[i].fItalic) - return rec[i]; - } - // give up - return rec[0]; -} - -enum { - DEFAULT_FAMILY_INDEX, - - FAMILY_INDEX_COUNT -}; - -static const FontFaceRec gDefaultFaces[] = { - { SK_FONTPATH, DEFAULT_FAMILY_INDEX, 0, 0 } -}; - -// This table must be in the same order as the ..._FAMILY_INDEX enum specifies -static const FontFamilyRec gFamilies[] = { - { gDefaultFaces, SK_ARRAY_COUNT(gDefaultFaces) } -}; - -#define DEFAULT_FAMILY_INDEX DEFAULT_FAMILY_INDEX -#define DEFAULT_FAMILY_FACE_INDEX 0 - -/////////////////////////////////////////////////////////////////////////////// - -/* map common "web" font names to our font list */ - -struct FontFamilyMatchRec { - const char* fLCName; - int fFamilyIndex; -}; - -/* This is a table of synonyms for collapsing font names - down to their pseudo-equivalents (i.e. in terms of fonts - we actually have.) - Keep this sorted by the first field so we can do a binary search. - If this gets big, we could switch to a hash... -*/ -static const FontFamilyMatchRec gMatches[] = { -#if 0 - { "Ahem", Ahem_FAMILY_INDEX }, - { "arial", SANS_FAMILY_INDEX }, - { "courier", MONO_FAMILY_INDEX }, - { "courier new", MONO_FAMILY_INDEX }, - { "cursive", SERIF_FAMILY_INDEX }, - { "fantasy", SERIF_FAMILY_INDEX }, - { "georgia", SERIF_FAMILY_INDEX }, - { "goudy", SERIF_FAMILY_INDEX }, - { "helvetica", SANS_FAMILY_INDEX }, - { "palatino", SERIF_FAMILY_INDEX }, - { "tahoma", SANS_FAMILY_INDEX }, - { "sans-serif", SANS_FAMILY_INDEX }, - { "serif", SERIF_FAMILY_INDEX }, - { "times", SERIF_FAMILY_INDEX }, - { "times new roman", SERIF_FAMILY_INDEX }, - { "verdana", SANS_FAMILY_INDEX } -#endif -}; - -/////////////////////////////////////////////////////////////////////////////// - -#include "SkTSearch.h" - -static bool contains_only_ascii(const char s[]) -{ - for (;;) - { - int c = *s++; - if (c == 0) - break; - if ((c >> 7) != 0) - return false; - } - return true; -} - -#define TRACE_FONT_NAME(code) -//#define TRACE_FONT_NAME(code) code - -const FontFamilyRec* find_family_rec(const char target[]) -{ - int index; - - // If we're asked for a font name that contains non-ascii, - // 1) SkStrLCSearch can't handle it - // 2) All of our fonts are have ascii names, so... - -TRACE_FONT_NAME(printf("----------------- font request <%s>", target);) - - if (contains_only_ascii(target)) - { - // Search for the font by matching the entire name - index = SkStrLCSearch(&gMatches[0].fLCName, SK_ARRAY_COUNT(gMatches), - target, sizeof(gMatches[0])); - if (index >= 0) - { - TRACE_FONT_NAME(printf(" found %d\n", index);) - return &gFamilies[gMatches[index].fFamilyIndex]; - } - } - - // Sniff for key words... - -#if 0 - if (strstr(target, "sans") || strstr(target, "Sans")) - { - TRACE_FONT_NAME(printf(" found sans\n");) - return &gFamilies[SANS_FAMILY_INDEX]; - } - if (strstr(target, "serif") || strstr(target, "Serif")) - { - TRACE_FONT_NAME(printf(" found serif\n");) - return &gFamilies[SERIF_FAMILY_INDEX]; - } - if (strstr(target, "mono") || strstr(target, "Mono")) - { - TRACE_FONT_NAME(printf(" found mono\n");) - return &gFamilies[MONO_FAMILY_INDEX]; - } -#endif - - TRACE_FONT_NAME(printf(" use default\n");) - // we give up, just give them the default font - return &gFamilies[DEFAULT_FAMILY_INDEX]; -} - -/////////////////////////////////////////////////////////////////////////////// - -static const FontFaceRec* get_default_face() -{ - return &gFamilies[DEFAULT_FAMILY_INDEX].fFaces[DEFAULT_FAMILY_FACE_INDEX]; -} - -static SkTypeface::Style get_style(const FontFaceRec& face) { - int style = 0; - if (face.fBold) { - style |= SkTypeface::kBold; - } - if (face.fItalic) { - style |= SkTypeface::kItalic; - } - return static_cast<SkTypeface::Style>(style); -} - -// This global const reference completely identifies the face -static uint32_t get_id(const FontFaceRec& face) { - uintptr_t id = reinterpret_cast<uintptr_t>(&face); - return static_cast<uint32_t>(id); -} - -class FontFaceRec_Typeface : public SkTypeface { -public: - FontFaceRec_Typeface(const FontFaceRec& face) : - SkTypeface(get_style(face), get_id(face)), - fFace(face) - { - } - - // This global const reference completely identifies the face - const FontFaceRec& fFace; -}; - -static const FontFaceRec* get_typeface_rec(const SkTypeface* face) -{ - const FontFaceRec_Typeface* f = (FontFaceRec_Typeface*)face; - return f ? &f->fFace : get_default_face(); -} - -static uint32_t ptr2uint32(const void* p) -{ - // cast so we avoid warnings on 64bit machines that a ptr difference - // which might be 64bits is being trucated from 64 to 32 - return (uint32_t)((char*)p - (char*)0); -} - -SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace, - const char familyName[], - SkTypeface::Style style) -{ - const FontFamilyRec* family; - - if (familyFace) - family = &gFamilies[ - ((FontFaceRec_Typeface*)familyFace)->fFace.fFamilyIndex]; - else if (familyName) - family = find_family_rec(familyName); - else - family = &gFamilies[DEFAULT_FAMILY_INDEX]; - - const FontFaceRec& face = FontFaceRec::FindFace(family->fFaces, - family->fFaceCount, - (style & SkTypeface::kBold) != 0, - (style & SkTypeface::kItalic) != 0); - - // if we're returning our input parameter, no need to create a new instance - if (familyFace != NULL && - &((FontFaceRec_Typeface*)familyFace)->fFace == &face) - { - familyFace->ref(); - return (SkTypeface*)familyFace; - } - return SkNEW_ARGS(FontFaceRec_Typeface, (face)); -} - -SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) { - sk_throw(); // not implemented - return NULL; -} - -SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) { - sk_throw(); // not implemented - return NULL; -} - -bool SkFontHost::ValidFontID(uint32_t fontID) { - return get_id(*get_default_face()) == fontID; -} - -SkStream* SkFontHost::OpenStream(uint32_t fontID) { - sk_throw(); // not implemented - return NULL; -} - -void SkFontHost::Serialize(const SkTypeface* tface, SkWStream* stream) { - const FontFaceRec* face = &((const FontFaceRec_Typeface*)tface)->fFace; - stream->write(face, sizeof(face)); -} - -SkTypeface* SkFontHost::Deserialize(SkStream* stream) { - const FontFaceRec* face; - stream->read(&face, sizeof(face)); - return new FontFaceRec_Typeface(*face); -} - -SkScalerContext* SkFontHost::CreateFallbackScalerContext( - const SkScalerContext::Rec& rec) -{ - const FontFaceRec* face = get_default_face(); - - SkAutoDescriptor ad(sizeof(rec) + sizeof(face) + - SkDescriptor::ComputeOverhead(2)); - SkDescriptor* desc = ad.getDesc(); - SkScalerContext::Rec* newRec; - - desc->init(); - newRec = reinterpret_cast<SkScalerContext::Rec*>( - desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec)); - newRec->fFontID = get_id(*face); - desc->computeChecksum(); - - return SkFontHost::CreateScalerContext(desc); -} - -size_t SkFontHost::ShouldPurgeFontCache(size_t sizeAllocatedSoFar) -{ - return 0; // nothing to do (change me if you want to limit the font cache) -} - diff --git a/src/ports/SkFontHost_ascender.cpp b/src/ports/SkFontHost_ascender.cpp deleted file mode 100644 index 2148850..0000000 --- a/src/ports/SkFontHost_ascender.cpp +++ /dev/null @@ -1,211 +0,0 @@ -#include "SkScalerContext.h" -#include "SkBitmap.h" -#include "SkCanvas.h" -#include "SkDescriptor.h" -#include "SkFDot6.h" -#include "SkFontHost.h" -#include "SkMask.h" -#include "SkStream.h" -#include "SkString.h" -#include "SkThread.h" -#include "SkTemplates.h" - -#include <acaapi.h> - -////////////////////////////////////////////////////////////////////////// - -#include "SkMMapStream.h" - -class SkScalerContext_Ascender : public SkScalerContext { -public: - SkScalerContext_Ascender(const SkDescriptor* desc); - virtual ~SkScalerContext_Ascender(); - -protected: - virtual unsigned generateGlyphCount() const; - virtual uint16_t generateCharToGlyph(SkUnichar uni); - virtual void generateMetrics(SkGlyph* glyph); - virtual void generateImage(const SkGlyph& glyph); - virtual void generatePath(const SkGlyph& glyph, SkPath* path); - virtual void generateFontMetrics(SkPaint::FontMetrics* mx, SkPaint::FontMetrics* my); - -private: - aca_FontHandle fHandle; - void* fWorkspace; - void* fGlyphWorkspace; - SkStream* fFontStream; - SkStream* fHintStream; -}; - -/////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////// - -SkScalerContext_Ascender::SkScalerContext_Ascender(const SkDescriptor* desc) - : SkScalerContext(desc) -{ - int size = aca_Get_FontHandleRec_Size(); - fHandle = (aca_FontHandle)sk_malloc_throw(size); - - // get the pointer to the font - - fFontStream = new SkMMAPStream("/UcsGB2312-Hei-H.FDL"); - fHintStream = new SkMMAPStream("/genv6-23.bin"); - - void* hints = sk_malloc_throw(fHintStream->getLength()); - memcpy(hints, fHintStream->getMemoryBase(), fHintStream->getLength()); - - aca_Create_Font_Handle(fHandle, - (void*)fFontStream->getMemoryBase(), fFontStream->getLength(), - "fred", - hints, fHintStream->getLength()); - - // compute our factors from the record - - SkMatrix m; - - fRec.getSingleMatrix(&m); - - // now compute our scale factors - SkScalar sx = m.getScaleX(); - SkScalar sy = m.getScaleY(); - - int ppemX = SkScalarRound(sx); - int ppemY = SkScalarRound(sy); - - size = aca_Find_Font_Memory_Required(fHandle, ppemX, ppemY); - size *= 8; // Jeff suggests this :) - fWorkspace = sk_malloc_throw(size); - aca_Set_Font_Memory(fHandle, (uint8_t*)fWorkspace, size); - - aca_GlyphAttribsRec rec; - - memset(&rec, 0, sizeof(rec)); - rec.xSize = ppemX; - rec.ySize = ppemY; - rec.doAdjust = true; - rec.doExceptions = true; - rec.doGlyphHints = true; - rec.doInterpolate = true; - rec.grayMode = 2; - aca_Set_Font_Attributes(fHandle, &rec, &size); - - fGlyphWorkspace = sk_malloc_throw(size); - aca_Set_Glyph_Memory(fHandle, fGlyphWorkspace); -} - -SkScalerContext_Ascender::~SkScalerContext_Ascender() -{ - delete fHintStream; - delete fFontStream; - sk_free(fGlyphWorkspace); - sk_free(fWorkspace); - sk_free(fHandle); -} - -unsigned SkScalerContext_Ascender::generateGlyphCount() const -{ - return 1000; -} - -uint16_t SkScalerContext_Ascender::generateCharToGlyph(SkUnichar uni) -{ - return (uint16_t)(uni & 0xFFFF); -} - -void SkScalerContext_Ascender::generateMetrics(SkGlyph* glyph) -{ - glyph->fRsbDelta = 0; - glyph->fLsbDelta = 0; - - aca_GlyphImageRec rec; - aca_Vector topLeft; - - int adv = aca_Get_Adv_Width(fHandle, glyph->getGlyphID()); - if (aca_GLYPH_NOT_PRESENT == adv) - goto ERROR; - - aca_Rasterize(glyph->getGlyphID(), fHandle, &rec, &topLeft); - - if (false) // error - { -ERROR: - glyph->fWidth = 0; - glyph->fHeight = 0; - glyph->fTop = 0; - glyph->fLeft = 0; - glyph->fAdvanceX = 0; - glyph->fAdvanceY = 0; - return; - } - - glyph->fWidth = rec.width; - glyph->fHeight = rec.rows; - glyph->fRowBytes = rec.width; - glyph->fTop = -topLeft.y; - glyph->fLeft = topLeft.x; - glyph->fAdvanceX = SkIntToFixed(adv); - glyph->fAdvanceY = SkIntToFixed(0); -} - -void SkScalerContext_Ascender::generateImage(const SkGlyph& glyph) -{ - aca_GlyphImageRec rec; - aca_Vector topLeft; - - aca_Rasterize(glyph.getGlyphID(), fHandle, &rec, &topLeft); - - const uint8_t* src = (const uint8_t*)rec.buffer; - uint8_t* dst = (uint8_t*)glyph.fImage; - int height = glyph.fHeight; - - src += rec.y0 * rec.pitch + rec.x0; - while (--height >= 0) - { - memcpy(dst, src, glyph.fWidth); - src += rec.pitch; - dst += glyph.fRowBytes; - } -} - -/////////////////////////////////////////////////////////////////////////////////////////// - -void SkScalerContext_Ascender::generatePath(const SkGlyph& glyph, SkPath* path) -{ - SkRect r; - - r.set(0, 0, SkIntToScalar(4), SkIntToScalar(4)); - path->reset(); - path->addRect(r); -} - -void SkScalerContext_Ascender::generateFontMetrics(SkPaint::FontMetrics* mx, SkPaint::FontMetrics* my) -{ - if (NULL == mx && NULL == my) - return; - - if (mx) - { - mx->fTop = SkIntToScalar(-16); - mx->fAscent = SkIntToScalar(-16); - mx->fDescent = SkIntToScalar(4); - mx->fBottom = SkIntToScalar(4); - mx->fLeading = 0; - } - if (my) - { - my->fTop = SkIntToScalar(-16); - my->fAscent = SkIntToScalar(-16); - my->fDescent = SkIntToScalar(4); - my->fBottom = SkIntToScalar(4); - my->fLeading = 0; - } -} - -//////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////// - -SkScalerContext* SkFontHost::CreateScalerContext(const SkDescriptor* desc) -{ - return SkNEW_ARGS(SkScalerContext_Ascender, (desc)); -} - diff --git a/src/ports/SkFontHost_linux.cpp b/src/ports/SkFontHost_linux.cpp deleted file mode 100644 index 0c69126..0000000 --- a/src/ports/SkFontHost_linux.cpp +++ /dev/null @@ -1,594 +0,0 @@ -/* libs/graphics/ports/SkFontHost_android.cpp - ** - ** Copyright 2006, The Android Open Source Project - ** - ** Licensed under the Apache License, Version 2.0 (the "License"); - ** you may not use this file except in compliance with the License. - ** You may obtain a copy of the License at - ** - ** http://www.apache.org/licenses/LICENSE-2.0 - ** - ** Unless required by applicable law or agreed to in writing, software - ** distributed under the License is distributed on an "AS IS" BASIS, - ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - ** See the License for the specific language governing permissions and - ** limitations under the License. - */ - -#include "SkFontHost.h" -#include "SkDescriptor.h" -#include "SkMMapStream.h" -#include "SkOSFile.h" -#include "SkPaint.h" -#include "SkString.h" -#include "SkStream.h" -#include "SkThread.h" -#include "SkTSearch.h" -#include <stdio.h> - -#define FONT_CACHE_MEMORY_BUDGET (1 * 1024 * 1024) - -#ifndef SK_FONT_FILE_PREFIX - #define SK_FONT_FILE_PREFIX "/usr/share/fonts/truetype/msttcorefonts/" -#endif - -SkTypeface::Style find_name_and_style(SkStream* stream, SkString* name); - -static void GetFullPathForSysFonts(SkString* full, const char name[]) -{ - full->append(SK_FONT_FILE_PREFIX); - full->append(name); -} - -/////////////////////////////////////////////////////////////////////////////// - -struct FamilyRec; - -/* This guy holds a mapping of a name -> family, used for looking up fonts. - Since it is stored in a stretchy array that doesn't preserve object - semantics, we don't use constructor/destructors, but just have explicit - helpers to manage our internal bookkeeping. - */ -struct NameFamilyPair { - const char* fName; // we own this - FamilyRec* fFamily; // we don't own this, we just reference it - - void construct(const char name[], FamilyRec* family) - { - fName = strdup(name); - fFamily = family; // we don't own this, so just record the referene - } - void destruct() - { - free((char*)fName); - // we don't own family, so just ignore our reference - } -}; - -// we use atomic_inc to grow this for each typeface we create -static int32_t gUniqueFontID; - -// this is the mutex that protects these globals -static SkMutex gFamilyMutex; -static FamilyRec* gFamilyHead; -static SkTDArray<NameFamilyPair> gNameList; - -struct FamilyRec { - FamilyRec* fNext; - SkTypeface* fFaces[4]; - - FamilyRec() - { - fNext = gFamilyHead; - memset(fFaces, 0, sizeof(fFaces)); - gFamilyHead = this; - } -}; - -static SkTypeface* find_best_face(const FamilyRec* family, - SkTypeface::Style style) { - SkTypeface* const* faces = family->fFaces; - - if (faces[style] != NULL) { // exact match - return faces[style]; - } - // look for a matching bold - style = (SkTypeface::Style)(style ^ SkTypeface::kItalic); - if (faces[style] != NULL) { - return faces[style]; - } - // look for the plain - if (faces[SkTypeface::kNormal] != NULL) { - return faces[SkTypeface::kNormal]; - } - // look for anything - for (int i = 0; i < 4; i++) { - if (faces[i] != NULL) { - return faces[i]; - } - } - // should never get here, since the faces list should not be empty - SkASSERT(!"faces list is empty"); - return NULL; -} - -static FamilyRec* find_family(const SkTypeface* member) { - FamilyRec* curr = gFamilyHead; - while (curr != NULL) { - for (int i = 0; i < 4; i++) { - if (curr->fFaces[i] == member) { - return curr; - } - } - curr = curr->fNext; - } - return NULL; -} - -static bool valid_uniqueID(uint32_t uniqueID) { - FamilyRec* curr = gFamilyHead; - while (curr != NULL) { - for (int i = 0; i < 4; i++) { - SkTypeface* face = curr->fFaces[i]; - if (face != NULL && face->uniqueID() == uniqueID) { - return true; - } - } - curr = curr->fNext; - } - return false; -} - -/* Remove reference to this face from its family. If the resulting family - is empty (has no faces), return that family, otherwise return NULL - */ -static FamilyRec* remove_from_family(const SkTypeface* face) { - FamilyRec* family = find_family(face); - SkASSERT(family->fFaces[face->style()] == face); - family->fFaces[face->style()] = NULL; - - for (int i = 0; i < 4; i++) { - if (family->fFaces[i] != NULL) { // family is non-empty - return NULL; - } - } - return family; // return the empty family -} - -// maybe we should make FamilyRec be doubly-linked -static void detach_and_delete_family(FamilyRec* family) { - FamilyRec* curr = gFamilyHead; - FamilyRec* prev = NULL; - - while (curr != NULL) { - FamilyRec* next = curr->fNext; - if (curr == family) { - if (prev == NULL) { - gFamilyHead = next; - } else { - prev->fNext = next; - } - SkDELETE(family); - return; - } - prev = curr; - curr = next; - } - SkASSERT(!"Yikes, couldn't find family in our list to remove/delete"); -} - -static FamilyRec* find_familyrec(const char name[]) { - const NameFamilyPair* list = gNameList.begin(); - int index = SkStrLCSearch(&list[0].fName, gNameList.count(), name, - sizeof(list[0])); - return index >= 0 ? list[index].fFamily : NULL; -} - -static SkTypeface* find_typeface(const char name[], SkTypeface::Style style) { - FamilyRec* rec = find_familyrec(name); - return rec ? find_best_face(rec, style) : NULL; -} - -static SkTypeface* find_typeface(const SkTypeface* familyMember, - SkTypeface::Style style) { - const FamilyRec* family = find_family(familyMember); - return family ? find_best_face(family, style) : NULL; -} - -static void add_name(const char name[], FamilyRec* family) { - SkAutoAsciiToLC tolc(name); - name = tolc.lc(); - - NameFamilyPair* list = gNameList.begin(); - int count = gNameList.count(); - - int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0])); - - if (index < 0) { - list = gNameList.insert(~index); - list->construct(name, family); - } -} - -static void remove_from_names(FamilyRec* emptyFamily) { -#ifdef SK_DEBUG - for (int i = 0; i < 4; i++) { - SkASSERT(emptyFamily->fFaces[i] == NULL); - } -#endif - - SkTDArray<NameFamilyPair>& list = gNameList; - - // must go backwards when removing - for (int i = list.count() - 1; i >= 0; --i) { - NameFamilyPair* pair = &list[i]; - if (pair->fFamily == emptyFamily) { - pair->destruct(); - list.remove(i); - } - } -} - -/////////////////////////////////////////////////////////////////////////////// - -class FamilyTypeface : public SkTypeface { -public: - FamilyTypeface(Style style, bool sysFont, FamilyRec* family) - : SkTypeface(style, sk_atomic_inc(&gUniqueFontID) + 1) { - fIsSysFont = sysFont; - - SkAutoMutexAcquire ac(gFamilyMutex); - - if (NULL == family) { - family = SkNEW(FamilyRec); - } - family->fFaces[style] = this; - fFamilyRec = family; // just record it so we can return it if asked - } - - virtual ~FamilyTypeface() { - SkAutoMutexAcquire ac(gFamilyMutex); - - // remove us from our family. If the family is now empty, we return - // that and then remove that family from the name list - FamilyRec* family = remove_from_family(this); - if (NULL != family) { - remove_from_names(family); - detach_and_delete_family(family); - } - } - - bool isSysFont() const { return fIsSysFont; } - FamilyRec* getFamily() const { return fFamilyRec; } - - virtual SkStream* openStream() = 0; - virtual void closeStream(SkStream*) = 0; - virtual const char* getUniqueString() const = 0; - -private: - FamilyRec* fFamilyRec; // we don't own this, just point to it - bool fIsSysFont; - - typedef SkTypeface INHERITED; -}; - -/////////////////////////////////////////////////////////////////////////////// - -class StreamTypeface : public FamilyTypeface { -public: - StreamTypeface(Style style, bool sysFont, FamilyRec* family, - SkStream* stream) - : INHERITED(style, sysFont, family) { - fStream = stream; - } - virtual ~StreamTypeface() { - SkDELETE(fStream); - } - - // overrides - virtual SkStream* openStream() { return fStream; } - virtual void closeStream(SkStream*) {} - virtual const char* getUniqueString() const { return NULL; } - -private: - SkStream* fStream; - - typedef FamilyTypeface INHERITED; -}; - -class FileTypeface : public FamilyTypeface { -public: - FileTypeface(Style style, bool sysFont, FamilyRec* family, - const char path[]) - : INHERITED(style, sysFont, family) { - fPath.set(path); - } - - // overrides - virtual SkStream* openStream() - { - SkStream* stream = SkNEW_ARGS(SkMMAPStream, (fPath.c_str())); - - // check for failure - if (stream->getLength() <= 0) { - SkDELETE(stream); - // maybe MMAP isn't supported. try FILE - stream = SkNEW_ARGS(SkFILEStream, (fPath.c_str())); - if (stream->getLength() <= 0) { - SkDELETE(stream); - stream = NULL; - } - } - return stream; - } - virtual void closeStream(SkStream* stream) - { - SkDELETE(stream); - } - virtual const char* getUniqueString() const { - const char* str = strrchr(fPath.c_str(), '/'); - if (str) { - str += 1; // skip the '/' - } - return str; - } - -private: - SkString fPath; - - typedef FamilyTypeface INHERITED; -}; - -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// - -static bool get_name_and_style(const char path[], SkString* name, - SkTypeface::Style* style) { - SkMMAPStream stream(path); - if (stream.getLength() > 0) { - *style = find_name_and_style(&stream, name); - return true; - } - else { - SkFILEStream stream(path); - if (stream.getLength() > 0) { - *style = find_name_and_style(&stream, name); - return true; - } - } - - SkDebugf("---- failed to open <%s> as a font\n", path); - return false; -} - -// these globals are assigned (once) by load_system_fonts() -static SkTypeface* gFallBackTypeface; -static FamilyRec* gDefaultFamily; -static SkTypeface* gDefaultNormal; - -static void load_system_fonts() { - // check if we've already be called - if (NULL != gDefaultNormal) { - return; - } - - SkOSFile::Iter iter(SK_FONT_FILE_PREFIX, ".ttf"); - SkString name; - - while (iter.next(&name, false)) { - SkString filename; - GetFullPathForSysFonts(&filename, name.c_str()); -// while (filename.size() == 0) { filename.set("/usr/share/fonts/truetype/msttcorefonts/Arial.ttf"); - - SkString realname; - SkTypeface::Style style; - - if (!get_name_and_style(filename.c_str(), &realname, &style)) { - SkDebugf("------ can't load <%s> as a font\n", filename.c_str()); - continue; - } - -// SkDebugf("font: <%s> %d <%s>\n", realname.c_str(), style, filename.c_str()); - - FamilyRec* family = find_familyrec(realname.c_str()); - // this constructor puts us into the global gFamilyHead llist - FamilyTypeface* tf = SkNEW_ARGS(FileTypeface, - (style, - true, // system-font (cannot delete) - family, // what family to join - filename.c_str()) // filename - ); - - if (NULL == family) { - add_name(realname.c_str(), tf->getFamily()); - } - } - - // do this after all fonts are loaded. This is our default font, and it - // acts as a sentinel so we only execute load_system_fonts() once - static const char* gDefaultNames[] = { - "Arial", "Verdana", "Times New Roman", NULL - }; - const char** names = gDefaultNames; - while (*names) { - SkTypeface* tf = find_typeface(*names++, SkTypeface::kNormal); - if (tf) { - gDefaultNormal = tf; - break; - } - } - // check if we found *something* - if (NULL == gDefaultNormal) { - if (NULL == gFamilyHead) { - sk_throw(); - } - for (int i = 0; i < 4; i++) { - if ((gDefaultNormal = gFamilyHead->fFaces[i]) != NULL) { - break; - } - } - } - if (NULL == gDefaultNormal) { - sk_throw(); - } - gFallBackTypeface = gDefaultNormal; - gDefaultFamily = find_family(gDefaultNormal); - -// SkDebugf("---- default %p head %p family %p\n", gDefaultNormal, gFamilyHead, gDefaultFamily); -} - -/////////////////////////////////////////////////////////////////////////////// - -void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) { -#if 0 - const char* name = ((FamilyTypeface*)face)->getUniqueString(); - - stream->write8((uint8_t)face->getStyle()); - - if (NULL == name || 0 == *name) { - stream->writePackedUInt(0); - // SkDebugf("--- fonthost serialize null\n"); - } else { - uint32_t len = strlen(name); - stream->writePackedUInt(len); - stream->write(name, len); - // SkDebugf("--- fonthost serialize <%s> %d\n", name, face->getStyle()); - } -#endif - sk_throw(); -} - -SkTypeface* SkFontHost::Deserialize(SkStream* stream) { -#if 0 - load_system_fonts(); - - int style = stream->readU8(); - - int len = stream->readPackedUInt(); - if (len > 0) { - SkString str; - str.resize(len); - stream->read(str.writable_str(), len); - - const FontInitRec* rec = gSystemFonts; - for (size_t i = 0; i < SK_ARRAY_COUNT(gSystemFonts); i++) { - if (strcmp(rec[i].fFileName, str.c_str()) == 0) { - // backup until we hit the fNames - for (int j = i; j >= 0; --j) { - if (rec[j].fNames != NULL) { - return SkFontHost::CreateTypeface(NULL, rec[j].fNames[0], - (SkTypeface::Style)style); - } - } - } - } - } - return SkFontHost::CreateTypeface(NULL, NULL, (SkTypeface::Style)style); -#endif - sk_throw(); - return NULL; -} - -/////////////////////////////////////////////////////////////////////////////// - -SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace, - const char familyName[], - SkTypeface::Style style) { - load_system_fonts(); - - SkAutoMutexAcquire ac(gFamilyMutex); - - // clip to legal style bits - style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic); - - SkTypeface* tf = NULL; - - if (NULL != familyFace) { - tf = find_typeface(familyFace, style); - } else if (NULL != familyName) { - // SkDebugf("======= familyName <%s>\n", familyName); - tf = find_typeface(familyName, style); - } - - if (NULL == tf) { - tf = find_best_face(gDefaultFamily, style); - } - - return tf; -} - -SkTypeface* SkFontHost::ValidFontID(uint32_t fontID) { - SkAutoMutexAcquire ac(gFamilyMutex); - - return valid_uniqueID(fontID); -} - -SkStream* SkFontHost::OpenStream(uint32_t fontID) { - FamilyTypeface* tf = (FamilyTypeface*)SkFontHost::ResolveTypeface(fontID); - SkStream* stream = tf ? tf->openStream() : NULL; - - if (NULL == stream || stream->getLength() == 0) { - delete stream; - stream = NULL; - } - return stream; -} - -void SkFontHost::CloseStream(uint32_t fontID, SkStream* stream) { - FamilyTypeface* tf = (FamilyTypeface*)SkFontHost::ResolveTypeface(fontID); - if (NULL != tf) { - tf->closeStream(stream); - } -} - -SkScalerContext* SkFontHost::CreateFallbackScalerContext( - const SkScalerContext::Rec& rec) { - load_system_fonts(); - - SkAutoDescriptor ad(sizeof(rec) + SkDescriptor::ComputeOverhead(1)); - SkDescriptor* desc = ad.getDesc(); - - desc->init(); - SkScalerContext::Rec* newRec = - (SkScalerContext::Rec*)desc->addEntry(kRec_SkDescriptorTag, - sizeof(rec), &rec); - newRec->fFontID = gFallBackTypeface->uniqueID(); - desc->computeChecksum(); - - return SkFontHost::CreateScalerContext(desc); -} - -/////////////////////////////////////////////////////////////////////////////// - -SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) { - if (NULL == stream || stream->getLength() <= 0) { - SkDELETE(stream); - return NULL; - } - - SkString name; - SkTypeface::Style style = find_name_and_style(stream, &name); - - return SkNEW_ARGS(StreamTypeface, (style, false, NULL, stream)); -} - -SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) { - SkTypeface* face = NULL; - SkFILEStream* stream = SkNEW_ARGS(SkFILEStream, (path)); - - if (stream->isValid()) { - return CreateTypeface(stream); - } - stream->unref(); - return NULL; -} - -/////////////////////////////////////////////////////////////////////////////// - -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 -} - diff --git a/src/ports/SkFontHost_mac.cpp b/src/ports/SkFontHost_mac.cpp deleted file mode 100755 index f0e3a93..0000000 --- a/src/ports/SkFontHost_mac.cpp +++ /dev/null @@ -1,572 +0,0 @@ -/* - ** Copyright 2006, The Android Open Source Project - ** - ** Licensed under the Apache License, Version 2.0 (the "License"); - ** you may not use this file except in compliance with the License. - ** You may obtain a copy of the License at - ** - ** http://www.apache.org/licenses/LICENSE-2.0 - ** - ** Unless required by applicable law or agreed to in writing, software - ** distributed under the License is distributed on an "AS IS" BASIS, - ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - ** See the License for the specific language governing permissions and - ** limitations under the License. -*/ - -#include <carbon/carbon.h> -#include "SkFontHost.h" -#include "SkDescriptor.h" -#include "SkPoint.h" - -// Give 1MB font cache budget -#define FONT_CACHE_MEMORY_BUDGET (1024 * 1024) - -const char* gDefaultfont = "Arial"; // hard code for now -static SkMutex gFTMutex; - -static inline SkPoint F32PtToSkPoint(const Float32Point p) { - SkPoint sp = { SkFloatToScalar(p.x), SkFloatToScalar(p.y) }; - return sp; -} - -static inline uint32_t _rotl(uint32_t v, uint32_t r) { - return (v << r | v >> (32 - r)); -} - -// This will generate a unique ID based on the fontname + fontstyle -// and also used by upper layer -uint32_t FontFaceChecksum(const char *name,SkTypeface::Style style) -{ - if (!name) return style; - - char* q = (char*)name; - - // From "Performance in Practice of String Hashing Functions" - // Ramakrishna & Zobel - const uint32_t L = 5; - const uint32_t R = 2; - - uint32_t h = 0x12345678; - while (*q) { - uint32_t ql = tolower(*q); - h ^= ((h << L) + (h >> R) + ql); - q ++; - } - - // add style - h = _rotl(h, 3) ^ style; - - return h; -} - -#pragma mark - -struct SkFaceRec { - SkFaceRec* fNext; - uint32_t fRefCnt; - ATSUFontID fFontID; - ATSUStyle fStyle; - - SkFaceRec() : fFontID(0), fRefCnt(0), fStyle(NULL) {}; - - ~SkFaceRec() { - if (fStyle) { - ::ATSUDisposeStyle(fStyle); - fStyle = NULL; - } - } - - uint32_t ref() { - return ++fRefCnt; - } -}; - -// Font Face list -static SkFaceRec* gFaceRecHead = NULL; - -static SkFaceRec* find_ft_face(const ATSUFontID fontID) { - SkFaceRec* rec = gFaceRecHead; - while (rec) { - if (rec->fFontID == fontID) { - return rec; - } - rec = rec->fNext; - } - - return NULL; -} - -static SkFaceRec* insert_ft_face(const ATSUFontID afontID, const ATSUStyle atsuStyle) { - SkFaceRec* rec = find_ft_face(afontID); - if (rec) { - return rec; // found? - } - - rec = SkNEW(SkFaceRec); - rec->fFontID = afontID; - rec->fStyle = atsuStyle; - rec->fNext = gFaceRecHead; - gFaceRecHead = rec; - - return rec; -} - -static void unref_ft_face(const ATSUFontID fontID) { - - SkFaceRec* rec = gFaceRecHead; - SkFaceRec* prev = NULL; - while (rec) { - SkFaceRec* next = rec->fNext; - if (rec->fFontID == fontID) { - if (--rec->fRefCnt == 0) { - if (prev) - prev->fNext = next; - else - gFaceRecHead = next; - - SkDELETE(rec); - } - return; - } - prev = rec; - rec = next; - } - SkASSERT("shouldn't get here, face not in list"); -} - -#pragma mark - - -// have to do this because SkTypeface::SkTypeface() is protected -class SkTypeface_Mac : public SkTypeface { -public: - SkTypeface_Mac(SkTypeface::Style style, uint32_t id) : SkTypeface(style, id) {} - - ~SkTypeface_Mac() {} -}; - -#pragma mark - - -static SkTypeface* CreateTypeface_(const char *name, const SkTypeface::Style style) { - - OSStatus err; - ATSUStyle atsuStyle; - ::ATSUCreateStyle(&atsuStyle); - if (name != NULL) { - static const ATSUAttributeTag fontTag = kATSUFontTag; - static const ByteCount fontTagSize = sizeof(ATSUFontID); - - ATSUFontID fontID = 0; -#if 1 - err = ::ATSUFindFontFromName( - name,strlen(name),kFontNoNameCode, /* instead of regular, kFontFamilyName returns bold and/or italic sometimes, but why this works?? */ - kFontMacintoshPlatform,kFontNoScriptCode,kFontNoLanguageCode,&fontID); -#else - CFStringRef cfontName = CFStringCreateWithCString(NULL, name, kCFStringEncodingASCII); - ATSFontRef fontRef = ::ATSFontFindFromName(cfontName,kATSOptionFlagsDefault); - fontID = ::FMGetFontFromATSFontRef(fontRef); - CFRelease(cfontName); -#endif - if (0 != fontID) { - const ATSUAttributeValuePtr values[] = { &fontID }; - err = ::ATSUSetAttributes(atsuStyle,1,&fontTag,&fontTagSize,values); - } - else { - } - } - if (style != SkTypeface::kNormal) { - Boolean fontItalic = ((style & SkTypeface::kItalic) != 0); - Boolean fontBold = ((style & SkTypeface::kBold) != 0); - const ATSUAttributeTag tags[2] = { kATSUQDBoldfaceTag, kATSUQDItalicTag }; - const ATSUAttributeValuePtr values[2] = { &fontBold, &fontItalic }; - const ByteCount sizes[2] = { sizeof(Boolean), sizeof(Boolean) }; - err = ::ATSUSetAttributes(atsuStyle,2,tags,sizes,values); - } - - uint32_t cs = FontFaceChecksum(name,style); - SkTypeface_Mac* ptypeface = new SkTypeface_Mac(style,cs); - - if (NULL == ptypeface) { - SkASSERT(false); - return NULL; - } - - SkFaceRec* rec = insert_ft_face(cs, atsuStyle); - SkASSERT(rec); - - return ptypeface; -} - -static SkTypeface* CreateTypeface_(const SkFaceRec* rec, const SkTypeface::Style style) { - - OSStatus err; - ATSUStyle atsuStyle; - err = ::ATSUCreateAndCopyStyle(rec->fStyle, &atsuStyle); - - Boolean fontItalic = ((style & SkTypeface::kItalic) != 0); - Boolean fontBold = ((style & SkTypeface::kBold) != 0); - const ATSUAttributeTag tags[2] = { kATSUQDBoldfaceTag, kATSUQDItalicTag }; - const ATSUAttributeValuePtr values[2] = { &fontBold, &fontItalic }; - const ByteCount sizes[2] = { sizeof(Boolean), sizeof(Boolean) }; - err = ::ATSUSetAttributes(atsuStyle,2,tags,sizes,values); - - // get old font id and name - ATSUFontID fontID = 0; - ByteCount actual = 0; - err = ::ATSUGetAttribute(rec->fStyle,kATSUFontTag,sizeof(ATSUFontID),&fontID,&actual); - - ByteCount actualLength = 0; - char *fontname = NULL; - err = ::ATSUFindFontName(fontID , kFontFamilyName, kFontUnicodePlatform, kFontNoScriptCode, - kFontNoLanguageCode , 0 , NULL , &actualLength , NULL ); - if ( err == noErr) - { - actualLength += 1 ; - fontname = (char*)malloc( actualLength ); - err = ::ATSUFindFontName(fontID, kFontFamilyName, kFontUnicodePlatform, kFontNoScriptCode, - kFontNoLanguageCode, actualLength, fontname , NULL, NULL); - } - - SkTypeface_Mac* ptypeface = NULL; - if (fontname == NULL) { - ptypeface = new SkTypeface_Mac(style,rec->fFontID); - return ptypeface; - } - else { - uint32_t cs = FontFaceChecksum(fontname,style); - ptypeface = new SkTypeface_Mac(style, cs); - - if (NULL == ptypeface) { - SkASSERT(false); - return NULL; - } - - free(fontname); - - insert_ft_face(cs,atsuStyle); - } - return ptypeface; -} - -#pragma mark - - -class SkScalerContext_Mac : public SkScalerContext { -public: - SkScalerContext_Mac(const SkDescriptor* desc); - virtual ~SkScalerContext_Mac(); - -protected: - virtual unsigned generateGlyphCount() const; - virtual uint16_t generateCharToGlyph(SkUnichar uni); - virtual void generateAdvance(SkGlyph* glyph); - virtual void generateMetrics(SkGlyph* glyph); - virtual void generateImage(const SkGlyph& glyph); - virtual void generatePath(const SkGlyph& glyph, SkPath* path); - virtual void generateLineHeight(SkPoint* ascent, SkPoint* descent); - virtual void generateFontMetrics(SkPaint::FontMetrics* mX, SkPaint::FontMetrics* mY); -// virtual SkDeviceContext getDC() { return NULL; } // not implemented on Mac - -private: - ATSUTextLayout fLayout; - ATSUStyle fStyle; - CGColorSpaceRef fGrayColorSpace; - - static OSStatus MoveTo(const Float32Point *pt, void *cb); - static OSStatus Line(const Float32Point *pt, void *cb); - static OSStatus Curve(const Float32Point *pt1, const Float32Point *pt2, const Float32Point *pt3, void *cb); - static OSStatus Close(void *cb); -}; - -SkScalerContext_Mac::SkScalerContext_Mac(const SkDescriptor* desc) - : SkScalerContext(desc), fLayout(0), fStyle(0) -{ - SkAutoMutexAcquire ac(gFTMutex); - OSStatus err; - - SkFaceRec* rec = find_ft_face(fRec.fFontID); - if (rec) { - rec->ref(); - err = ::ATSUCreateAndCopyStyle(rec->fStyle, &fStyle); - } - else { - SkASSERT(false); - // create a default - err = ::ATSUCreateStyle(&fStyle); - } - - uint32_t size = SkScalarFloor(fRec.fTextSize); - Fixed fixedSize = IntToFixed(size); - static const ATSUAttributeTag sizeTag = kATSUSizeTag; - static const ByteCount sizeTagSize = sizeof(Fixed); - const ATSUAttributeValuePtr values[] = { &fixedSize }; - err = ::ATSUSetAttributes(fStyle,1,&sizeTag,&sizeTagSize,values); - - err = ::ATSUCreateTextLayout(&fLayout); - - fGrayColorSpace = ::CGColorSpaceCreateDeviceGray(); -} - -SkScalerContext_Mac::~SkScalerContext_Mac() -{ - ::CGColorSpaceRelease(fGrayColorSpace); - - unref_ft_face(fRec.fFontID); - - ::ATSUDisposeTextLayout(fLayout); - ::ATSUDisposeStyle(fStyle); -} - -unsigned SkScalerContext_Mac::generateGlyphCount() const -{ - return 0xFFFF; -} - -uint16_t SkScalerContext_Mac::generateCharToGlyph(SkUnichar uni) -{ - SkAutoMutexAcquire ac(gFTMutex); - - OSStatus err; - UniChar achar = uni; - err = ::ATSUSetTextPointerLocation(fLayout,&achar,0,1,1); - err = ::ATSUSetRunStyle(fLayout,fStyle,kATSUFromTextBeginning,kATSUToTextEnd); - - ATSLayoutRecord *layoutPtr; - ItemCount count; - ATSGlyphRef glyph; - - err = ::ATSUDirectGetLayoutDataArrayPtrFromTextLayout(fLayout,0,kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,(void**)&layoutPtr,&count); - glyph = layoutPtr->glyphID; - ::ATSUDirectReleaseLayoutDataArrayPtr(NULL,kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,(void**)&layoutPtr); - return glyph; -} - -static void set_glyph_metrics_on_error(SkGlyph* glyph) { - glyph->fRsbDelta = 0; - glyph->fLsbDelta = 0; - glyph->fWidth = 0; - glyph->fHeight = 0; - glyph->fTop = 0; - glyph->fLeft = 0; - glyph->fAdvanceX = 0; - glyph->fAdvanceY = 0; -} - -void SkScalerContext_Mac::generateAdvance(SkGlyph* glyph) { - this->generateMetrics(glyph); -} - -void SkScalerContext_Mac::generateMetrics(SkGlyph* glyph) { - GlyphID glyphID = glyph->getGlyphID(fBaseGlyphCount); - ATSGlyphScreenMetrics metrics; - - OSStatus err = ATSUGlyphGetScreenMetrics(fStyle, 1, &glyphID, 0, true, true, - &metrics); - if (noErr != err) { - set_glyph_metrics_on_error(glyph); - } else { - glyph->fAdvanceX = SkFloatToFixed(metrics.deviceAdvance.x); - glyph->fAdvanceY = -SkFloatToFixed(metrics.deviceAdvance.y); - glyph->fWidth = metrics.width; - glyph->fHeight = metrics.height; - glyph->fLeft = sk_float_round2int(metrics.topLeft.x); - glyph->fTop = -sk_float_round2int(metrics.topLeft.y); - } -} - -void SkScalerContext_Mac::generateFontMetrics(SkPaint::FontMetrics* mx, - SkPaint::FontMetrics* my) { -#if 0 - OSStatus ATSFontGetVerticalMetrics ( - ATSFontRef iFont, - ATSOptionFlags iOptions, - ATSFontMetrics *oMetrics - ); -#endif - //SkASSERT(false); - if (mx) - memset(mx, 0, sizeof(SkPaint::FontMetrics)); - if (my) - memset(my, 0, sizeof(SkPaint::FontMetrics)); - return; -} - -void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) -{ - SkAutoMutexAcquire ac(gFTMutex); - SkASSERT(fLayout); - OSStatus err; - - bzero(glyph.fImage, glyph.fHeight * glyph.rowBytes()); - CGContextRef contextRef = ::CGBitmapContextCreate(glyph.fImage, - glyph.fWidth, glyph.fHeight, 8, - glyph.rowBytes(), fGrayColorSpace, - kCGImageAlphaNone); - if (!contextRef) { - SkASSERT(false); - return; - } - - ::CGContextSetGrayFillColor(contextRef, 1.0, 1.0); - ::CGContextSetTextDrawingMode(contextRef, kCGTextFill); - - ATSUAttributeTag tag = kATSUCGContextTag; - ByteCount size = sizeof(CGContextRef); - ATSUAttributeValuePtr value = &contextRef; - err = ::ATSUSetLayoutControls(fLayout, 1, &tag, &size, &value); - SkASSERT(!err); - err = ::ATSUDrawText(fLayout, kATSUFromTextBeginning, kATSUToTextEnd, - SkIntToFixed(-glyph.fLeft), - SkIntToFixed(glyph.fTop + glyph.fHeight)); - SkASSERT(!err); - ::CGContextRelease(contextRef); -} - -void SkScalerContext_Mac::generatePath(const SkGlyph& glyph, SkPath* path) -{ - SkAutoMutexAcquire ac(gFTMutex); - OSStatus err,result; - - err = ::ATSUGlyphGetCubicPaths( - fStyle,glyph.fID, - &SkScalerContext_Mac::MoveTo, - &SkScalerContext_Mac::Line, - &SkScalerContext_Mac::Curve, - &SkScalerContext_Mac::Close, - path,&result); - SkASSERT(err == noErr); -} - -void SkScalerContext_Mac::generateLineHeight(SkPoint* ascent, SkPoint* descent) -{ - ATSUTextMeasurement textAscent, textDescent; - ByteCount actual = 0; - OSStatus err = ::ATSUGetAttribute(fStyle,kATSULineAscentTag,sizeof(ATSUTextMeasurement),&textAscent,&actual); - ascent->set(0,textAscent); - err = ::ATSUGetAttribute(fStyle,kATSULineDescentTag,sizeof(ATSUTextMeasurement),&textDescent,&actual); - descent->set(0,textDescent); -} - -OSStatus SkScalerContext_Mac::MoveTo(const Float32Point *pt, void *cb) -{ - reinterpret_cast<SkPath*>(cb)->moveTo(F32PtToSkPoint(*pt)); - return noErr; -} - -OSStatus SkScalerContext_Mac::Line(const Float32Point *pt, void *cb) -{ - reinterpret_cast<SkPath*>(cb)->lineTo(F32PtToSkPoint(*pt)); - return noErr; -} - -OSStatus SkScalerContext_Mac::Curve(const Float32Point *pt1, - const Float32Point *pt2, - const Float32Point *pt3, void *cb) -{ - reinterpret_cast<SkPath*>(cb)->cubicTo(F32PtToSkPoint(*pt1), - F32PtToSkPoint(*pt2), - F32PtToSkPoint(*pt3)); - return noErr; -} - -OSStatus SkScalerContext_Mac::Close(void *cb) -{ - reinterpret_cast<SkPath*>(cb)->close(); - return noErr; -} - -#pragma mark - - -void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) { - SkASSERT(!"SkFontHost::Serialize unimplemented"); -} - -SkTypeface* SkFontHost::Deserialize(SkStream* stream) { - SkASSERT(!"SkFontHost::Deserialize unimplemented"); - return NULL; -} - -SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) { - - //Should not be used on Mac, keep linker happy - SkASSERT(false); - return CreateTypeface_(gDefaultfont,SkTypeface::kNormal); -} - -SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) { - // TODO - return CreateTypeface_(gDefaultfont,SkTypeface::kNormal); -} - -SkScalerContext* SkFontHost::CreateScalerContext(const SkDescriptor* desc) -{ - return new SkScalerContext_Mac(desc); -} - -SkScalerContext* SkFontHost::CreateFallbackScalerContext(const SkScalerContext::Rec& rec) -{ - SkAutoDescriptor ad(sizeof(rec) + sizeof(gDefaultfont) + SkDescriptor::ComputeOverhead(2)); - SkDescriptor* desc = ad.getDesc(); - - desc->init(); - SkScalerContext::Rec* newRec = - (SkScalerContext::Rec*)desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec); - - CreateTypeface_(gDefaultfont,SkTypeface::kNormal); - newRec->fFontID = FontFaceChecksum(gDefaultfont,SkTypeface::kNormal); - desc->computeChecksum(); - - return SkFontHost::CreateScalerContext(desc); -} - -SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace, - const char familyName[], SkTypeface::Style style) { - - SkAutoMutexAcquire ac(gFTMutex); - - // clip to legal style bits - style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic); - - SkTypeface* tf = NULL; - - if (NULL == familyFace && NULL == familyName) { - tf = CreateTypeface_(gDefaultfont,style); - } - else { - if (NULL != familyFace) { - uint32_t id = familyFace->uniqueID(); - SkFaceRec* rec = find_ft_face(id); - if (!rec) { - SkASSERT(false); - tf = CreateTypeface_(gDefaultfont,style); - } - else { - tf = CreateTypeface_(rec,style); - } - } - else { - tf = CreateTypeface_(familyName,style); - } - } - - if (NULL == tf) { - tf = CreateTypeface_(gDefaultfont,style); - } - return tf; - -} - -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) -} - diff --git a/src/ports/SkFontHost_none.cpp b/src/ports/SkFontHost_none.cpp deleted file mode 100644 index 608ee29..0000000 --- a/src/ports/SkFontHost_none.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* Copyright 2006-2008, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#include "SkFontHost.h" - -SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace, - const char famillyName[], - SkTypeface::Style style) { - SkASSERT(!"SkFontHost::FindTypeface unimplemented"); - return NULL; -} - -SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream*) { - SkASSERT(!"SkFontHost::CreateTypeface unimplemented"); - return NULL; -} - -SkTypeface* SkFontHost::CreateTypefaceFromFile(char const*) { - SkASSERT(!"SkFontHost::CreateTypefaceFromFile unimplemented"); - return NULL; -} - -/////////////////////////////////////////////////////////////////////////////// - -bool SkFontHost::ValidFontID(uint32_t uniqueID) { - SkASSERT(!"SkFontHost::ResolveTypeface unimplemented"); - return false; -} - -SkStream* SkFontHost::OpenStream(uint32_t uniqueID) { - SkASSERT(!"SkFontHost::OpenStream unimplemented"); - return NULL; -} - -/////////////////////////////////////////////////////////////////////////////// - -void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) { - SkASSERT(!"SkFontHost::Serialize unimplemented"); -} - -SkTypeface* SkFontHost::Deserialize(SkStream* stream) { - SkASSERT(!"SkFontHost::Deserialize unimplemented"); - return NULL; -} - -/////////////////////////////////////////////////////////////////////////////// - -SkScalerContext* SkFontHost::CreateScalerContext(const SkDescriptor* desc) { - SkASSERT(!"SkFontHost::CreateScalarContext unimplemented"); - return NULL; -} - -SkScalerContext* SkFontHost::CreateFallbackScalerContext( - const SkScalerContext::Rec&) { - SkASSERT(!"SkFontHost::CreateFallbackScalerContext unimplemented"); - return NULL; -} - - -/////////////////////////////////////////////////////////////////////////////// - -size_t SkFontHost::ShouldPurgeFontCache(size_t sizeAllocatedSoFar) { - return 0; // nothing to do (change me if you want to limit the font cache) -} - -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) -} - diff --git a/src/ports/SkFontHost_win.cpp b/src/ports/SkFontHost_win.cpp deleted file mode 100644 index 4cc04b5..0000000 --- a/src/ports/SkFontHost_win.cpp +++ /dev/null @@ -1,602 +0,0 @@ -/*
- ** Copyright 2006, The Android Open Source Project
- **
- ** Licensed under the Apache License, Version 2.0 (the "License");
- ** you may not use this file except in compliance with the License.
- ** You may obtain a copy of the License at
- **
- ** http://www.apache.org/licenses/LICENSE-2.0
- **
- ** Unless required by applicable law or agreed to in writing, software
- ** distributed under the License is distributed on an "AS IS" BASIS,
- ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ** See the License for the specific language governing permissions and
- ** limitations under the License.
- */
-
-#include "SkString.h"
-//#include "SkStream.h"
-
-#include "SkFontHost.h"
-#include "SkDescriptor.h"
-#include "SkThread.h"
-
-#ifdef WIN32
-#include "windows.h"
-#include "tchar.h"
-
-// client3d has to undefine this for now
-#define CAN_USE_LOGFONT_NAME
-
-static SkMutex gFTMutex;
-
-// these globals are loaded (once) by get_default_font()
-static LOGFONT gDefaultFont = {0};
-
-static const uint16_t BUFFERSIZE = (16384 - 32);
-static uint8_t glyphbuf[BUFFERSIZE];
-
-// Give 1MB font cache budget
-#define FONT_CACHE_MEMORY_BUDGET (1024 * 1024)
-
-static inline FIXED SkFixedToFIXED(SkFixed x) {
- return *(FIXED*)(&x);
-}
-
-static inline FIXED SkScalarToFIXED(SkScalar x) {
- return SkFixedToFIXED(SkScalarToFixed(x));
-}
-
-// This will generate a unique ID based on the fontname + fontstyle
-// and also used by upper layer
-uint32_t FontFaceChecksum(const TCHAR *q, SkTypeface::Style style)
-{
- if (!q) return style;
-
- // From "Performance in Practice of String Hashing Functions"
- // Ramakrishna & Zobel
- const uint32_t L = 5;
- const uint32_t R = 2;
-
- uint32_t h = 0x12345678;
- while (*q) {
- //uint32_t ql = tolower(*q);
- h ^= ((h << L) + (h >> R) + *q);
- q ++;
- }
-
- // add style
- h = _rotl(h, 3) ^ style;
-
- return h;
-}
-
-static SkTypeface::Style GetFontStyle(const LOGFONT& lf) {
- int style = SkTypeface::kNormal;
- if (lf.lfWeight == FW_SEMIBOLD || lf.lfWeight == FW_DEMIBOLD || lf.lfWeight == FW_BOLD)
- style |= SkTypeface::kBold;
- if (lf.lfItalic)
- style |= SkTypeface::kItalic;
-
- return (SkTypeface::Style)style;
-}
-
-struct SkFaceRec {
- SkFaceRec* fNext;
- uint32_t fRefCnt;
- uint32_t fFontID; // checksum of fFace
- LOGFONT fFace;
-
- SkFaceRec() : fFontID(-1), fRefCnt(0) {
- memset(&fFace, 0, sizeof(LOGFONT));
- }
- ~SkFaceRec() {}
-
- uint32_t ref() {
- return ++fRefCnt;
- }
-};
-
-// Font Face list
-static SkFaceRec* gFaceRecHead = NULL;
-
-static SkFaceRec* find_ft_face(uint32_t fontID) {
- SkFaceRec* rec = gFaceRecHead;
- while (rec) {
- if (rec->fFontID == fontID) {
- return rec;
- }
- rec = rec->fNext;
- }
-
- return NULL;
-}
-
-static SkFaceRec* insert_ft_face(const LOGFONT& lf) {
- // need a const char*
- uint32_t id = FontFaceChecksum(&(lf.lfFaceName[0]), GetFontStyle(lf));
- SkFaceRec* rec = find_ft_face(id);
- if (rec) {
- return rec; // found?
- }
-
- rec = SkNEW(SkFaceRec);
- rec->fFontID = id;
- memcpy(&(rec->fFace), &lf, sizeof(LOGFONT));
- rec->fNext = gFaceRecHead;
- gFaceRecHead = rec;
-
- return rec;
-}
-
-static void unref_ft_face(uint32_t fontID) {
-
- SkFaceRec* rec = gFaceRecHead;
- SkFaceRec* prev = NULL;
- while (rec) {
- SkFaceRec* next = rec->fNext;
- if (rec->fFontID == fontID) {
- if (--rec->fRefCnt == 0) {
- if (prev)
- prev->fNext = next;
- else
- gFaceRecHead = next;
-
- SkDELETE(rec);
- }
- return;
- }
- prev = rec;
- rec = next;
- }
- SkASSERT("shouldn't get here, face not in list");
-}
-
-// have to do this because SkTypeface::SkTypeface() is protected
-class FontFaceRec_Typeface : public SkTypeface {
-public:
-
- FontFaceRec_Typeface(Style style, uint32_t id) : SkTypeface(style, id) {};
-
- virtual ~FontFaceRec_Typeface() {};
-};
-
-static const LOGFONT* get_default_font() {
- // don't hardcode on Windows, Win2000, XP, Vista, and international all have different default
- // and the user could change too
-
- if (gDefaultFont.lfFaceName[0] != 0) {
- return &gDefaultFont;
- }
-
- NONCLIENTMETRICS ncm;
- ncm.cbSize = sizeof(NONCLIENTMETRICS);
- SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0);
-
- memcpy(&gDefaultFont, &(ncm.lfMessageFont), sizeof(LOGFONT));
-
- return &gDefaultFont;
-}
-
-static SkTypeface* CreateTypeface_(const LOGFONT& lf) {
-
- SkTypeface::Style style = GetFontStyle(lf);
- FontFaceRec_Typeface* ptypeface = new FontFaceRec_Typeface(style, FontFaceChecksum(lf.lfFaceName, style));
-
- if (NULL == ptypeface) {
- SkASSERT(false);
- return NULL;
- }
-
- SkFaceRec* rec = insert_ft_face(lf);
- SkASSERT(rec);
-
- return ptypeface;
-}
-
-class SkScalerContext_Windows : public SkScalerContext {
-public:
- SkScalerContext_Windows(const SkDescriptor* desc);
- virtual ~SkScalerContext_Windows();
-
-protected:
- virtual unsigned generateGlyphCount() const;
- virtual uint16_t generateCharToGlyph(SkUnichar uni);
- virtual void generateAdvance(SkGlyph* glyph);
- virtual void generateMetrics(SkGlyph* glyph);
- virtual void generateImage(const SkGlyph& glyph);
- virtual void generatePath(const SkGlyph& glyph, SkPath* path);
- virtual void generateLineHeight(SkPoint* ascent, SkPoint* descent);
- virtual void generateFontMetrics(SkPaint::FontMetrics* mX, SkPaint::FontMetrics* mY);
- //virtual SkDeviceContext getDC() {return ddc;}
-private:
- uint32_t fFontID;
- LOGFONT lf;
- MAT2 mat22;
- HDC ddc;
- HFONT savefont;
- HFONT font;
-};
-
-SkScalerContext_Windows::SkScalerContext_Windows(const SkDescriptor* desc) : SkScalerContext(desc), ddc(0), font(0), savefont(0) {
- SkAutoMutexAcquire ac(gFTMutex);
-
- fFontID = fRec.fFontID;
- SkFaceRec* rec = find_ft_face(fRec.fFontID);
- if (rec) {
- rec->ref();
- memcpy(&lf, &(rec->fFace), sizeof(LOGFONT));
- }
- else {
- SkASSERT(false);
- memcpy(&lf, &gDefaultFont, sizeof(LOGFONT));
- }
-
- mat22.eM11 = SkScalarToFIXED(fRec.fPost2x2[0][0]);
- mat22.eM12 = SkScalarToFIXED(-fRec.fPost2x2[0][1]);
- mat22.eM21 = SkScalarToFIXED(fRec.fPost2x2[1][0]);
- mat22.eM22 = SkScalarToFIXED(-fRec.fPost2x2[1][1]);
-
- ddc = ::CreateCompatibleDC(NULL);
- SetBkMode(ddc, TRANSPARENT);
-
- lf.lfHeight = SkScalarFloor(fRec.fTextSize);
- font = CreateFontIndirect(&lf);
- savefont = (HFONT)SelectObject(ddc, font);
-}
-
-SkScalerContext_Windows::~SkScalerContext_Windows() {
- unref_ft_face(fFontID);
-
- if (ddc) {
- ::SelectObject(ddc, savefont);
- ::DeleteDC(ddc);
- ddc = NULL;
- }
- if (font) {
- ::DeleteObject(font);
- }
-}
-
-unsigned SkScalerContext_Windows::generateGlyphCount() const {
- return 0xFFFF;
- // return fFace->num_glyphs;
-}
-
-uint16_t SkScalerContext_Windows::generateCharToGlyph(SkUnichar uni) {
-
- //uint16_t index = 0;
- //GetGlyphIndicesW(ddc, &(uint16_t&)uni, 1, &index, 0);
- //return index;
-
- // let's just use the uni as index on Windows
- return SkToU16(uni);
-}
-
-void SkScalerContext_Windows::generateAdvance(SkGlyph* glyph) {
- this->generateMetrics(glyph);
-}
-
-void SkScalerContext_Windows::generateMetrics(SkGlyph* glyph) {
-
- SkASSERT(ddc);
-
- GLYPHMETRICS gm;
- memset(&gm, 0, sizeof(gm));
-
- glyph->fRsbDelta = 0;
- glyph->fLsbDelta = 0;
-
- UINT glyphIndexFlag = 0; //glyph->fIsCodePoint ? 0 : GGO_GLYPH_INDEX;
- // UINT glyphIndexFlag = GGO_GLYPH_INDEX;
- // Note: need to use GGO_GRAY8_BITMAP instead of GGO_METRICS because GGO_METRICS returns a smaller
- // BlackBlox; we need the bigger one in case we need the image. fAdvance is the same.
- uint32_t ret = GetGlyphOutlineW(ddc, glyph->getGlyphID(0), GGO_GRAY8_BITMAP | glyphIndexFlag, &gm, 0, NULL, &mat22);
-
- if (GDI_ERROR != ret) {
- if (ret == 0) {
- // for white space, ret is zero and gmBlackBoxX, gmBlackBoxY are 1 incorrectly!
- gm.gmBlackBoxX = gm.gmBlackBoxY = 0;
- }
- glyph->fWidth = gm.gmBlackBoxX;
- glyph->fHeight = gm.gmBlackBoxY;
- glyph->fTop = SkToS16(gm.gmptGlyphOrigin.y - gm.gmBlackBoxY);
- glyph->fLeft = SkToS16(gm.gmptGlyphOrigin.x);
- glyph->fAdvanceX = SkIntToFixed(gm.gmCellIncX);
- glyph->fAdvanceY = -SkIntToFixed(gm.gmCellIncY);
- } else {
- glyph->fWidth = 0;
- }
-
-#if 0
- char buf[1024];
- sprintf(buf, "generateMetrics: id:%d, w=%d, h=%d, font:%s, fh:%d\n", glyph->fID, glyph->fWidth, glyph->fHeight, lf.lfFaceName, lf.lfHeight);
- OutputDebugString(buf);
-#endif
-}
-
-void SkScalerContext_Windows::generateFontMetrics(SkPaint::FontMetrics* mx, SkPaint::FontMetrics* my) {
- //SkASSERT(false);
- if (mx)
- memset(mx, 0, sizeof(SkPaint::FontMetrics));
- if (my)
- memset(my, 0, sizeof(SkPaint::FontMetrics));
- return;
-}
-
-void SkScalerContext_Windows::generateImage(const SkGlyph& glyph) {
-
- SkAutoMutexAcquire ac(gFTMutex);
-
- SkASSERT(ddc);
-
- GLYPHMETRICS gm;
- memset(&gm, 0, sizeof(gm));
-
-#if 0
- char buf[1024];
- sprintf(buf, "generateImage: id:%d, w=%d, h=%d, font:%s,fh:%d\n", glyph.fID, glyph.fWidth, glyph.fHeight, lf.lfFaceName, lf.lfHeight);
- OutputDebugString(buf);
-#endif
-
- uint32_t bytecount = 0;
- UINT glyphIndexFlag = 0; //glyph.fIsCodePoint ? 0 : GGO_GLYPH_INDEX;
- // UINT glyphIndexFlag = GGO_GLYPH_INDEX;
- uint32_t total_size = GetGlyphOutlineW(ddc, glyph.fID, GGO_GRAY8_BITMAP | glyphIndexFlag, &gm, 0, NULL, &mat22);
- if (GDI_ERROR != total_size && total_size > 0) {
- uint8_t *pBuff = new uint8_t[total_size];
- if (NULL != pBuff) {
- total_size = GetGlyphOutlineW(ddc, glyph.fID, GGO_GRAY8_BITMAP | glyphIndexFlag, &gm, total_size, pBuff, &mat22);
-
- SkASSERT(total_size != GDI_ERROR);
-
- SkASSERT(glyph.fWidth == gm.gmBlackBoxX);
- SkASSERT(glyph.fHeight == gm.gmBlackBoxY);
-
- uint8_t* dst = (uint8_t*)glyph.fImage;
- uint32_t pitch = (gm.gmBlackBoxX + 3) & ~0x3;
- if (pitch != glyph.rowBytes()) {
- SkASSERT(false); // glyph.fImage has different rowsize!?
- }
-
- for (int32_t y = gm.gmBlackBoxY - 1; y >= 0; y--) {
- uint8_t* src = pBuff + pitch * y;
-
- for (uint32_t x = 0; x < gm.gmBlackBoxX; x++) {
- if (*src > 63) {
- *dst = 0xFF;
- }
- else {
- *dst = *src << 2; // scale to 0-255
- }
- dst++;
- src++;
- bytecount++;
- }
- memset(dst, 0, glyph.rowBytes() - glyph.fWidth);
- dst += glyph.rowBytes() - glyph.fWidth;
- }
-
- delete[] pBuff;
- }
- }
-
- SkASSERT(GDI_ERROR != total_size && total_size >= 0);
-
-}
-
-void SkScalerContext_Windows::generatePath(const SkGlyph& glyph, SkPath* path) {
-
- SkAutoMutexAcquire ac(gFTMutex);
-
- SkASSERT(&glyph && path);
- SkASSERT(ddc);
-
- path->reset();
-
-#if 0
- char buf[1024];
- sprintf(buf, "generatePath: id:%d, w=%d, h=%d, font:%s,fh:%d\n", glyph.fID, glyph.fWidth, glyph.fHeight, lf.lfFaceName, lf.lfHeight);
- OutputDebugString(buf);
-#endif
-
- GLYPHMETRICS gm;
- UINT glyphIndexFlag = 0; //glyph.fIsCodePoint ? 0 : GGO_GLYPH_INDEX;
- uint32_t total_size = GetGlyphOutlineW(ddc, glyph.fID, GGO_NATIVE | glyphIndexFlag, &gm, BUFFERSIZE, glyphbuf, &mat22);
-
- if (GDI_ERROR != total_size) {
-
- const uint8_t* cur_glyph = glyphbuf;
- const uint8_t* end_glyph = glyphbuf + total_size;
-
- while(cur_glyph < end_glyph) {
- const TTPOLYGONHEADER* th = (TTPOLYGONHEADER*)cur_glyph;
-
- const uint8_t* end_poly = cur_glyph + th->cb;
- const uint8_t* cur_poly = cur_glyph + sizeof(TTPOLYGONHEADER);
-
- path->moveTo(SkFixedToScalar(*(SkFixed*)(&th->pfxStart.x)), SkFixedToScalar(*(SkFixed*)(&th->pfxStart.y)));
-
- while(cur_poly < end_poly) {
- const TTPOLYCURVE* pc = (const TTPOLYCURVE*)cur_poly;
-
- if (pc->wType == TT_PRIM_LINE) {
- for (uint16_t i = 0; i < pc->cpfx; i++) {
- path->lineTo(SkFixedToScalar(*(SkFixed*)(&pc->apfx[i].x)), SkFixedToScalar(*(SkFixed*)(&pc->apfx[i].y)));
- }
- }
-
- if (pc->wType == TT_PRIM_QSPLINE) {
- for (uint16_t u = 0; u < pc->cpfx - 1; u++) { // Walk through points in spline
- POINTFX pnt_b = pc->apfx[u]; // B is always the current point
- POINTFX pnt_c = pc->apfx[u+1];
-
- if (u < pc->cpfx - 2) { // If not on last spline, compute C
- pnt_c.x = SkFixedToFIXED(SkFixedAve(*(SkFixed*)(&pnt_b.x), *(SkFixed*)(&pnt_c.x)));
- pnt_c.y = SkFixedToFIXED(SkFixedAve(*(SkFixed*)(&pnt_b.y), *(SkFixed*)(&pnt_c.y)));
- }
-
- path->quadTo(SkFixedToScalar(*(SkFixed*)(&pnt_b.x)), SkFixedToScalar(*(SkFixed*)(&pnt_b.y)), SkFixedToScalar(*(SkFixed*)(&pnt_c.x)), SkFixedToScalar(*(SkFixed*)(&pnt_c.y)));
- }
- }
- cur_poly += sizeof(uint16_t) * 2 + sizeof(POINTFX) * pc->cpfx;
- }
- cur_glyph += th->cb;
- path->close();
- }
- }
- else {
- SkASSERT(false);
- }
- //char buf[1024];
- //sprintf(buf, "generatePath: count:%d\n", count);
- //OutputDebugString(buf);
-}
-
-
-// Note: not sure this is the correct implementation
-void SkScalerContext_Windows::generateLineHeight(SkPoint* ascent, SkPoint* descent) {
-
- SkASSERT(ddc);
-
- OUTLINETEXTMETRIC otm;
-
- uint32_t ret = GetOutlineTextMetrics(ddc, sizeof(otm), &otm);
-
- if (sizeof(otm) == ret) {
- if (ascent)
- ascent->iset(0, otm.otmAscent);
- if (descent)
- descent->iset(0, otm.otmDescent);
- }
-
- return;
-}
-
-void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) {
- SkASSERT(!"SkFontHost::Serialize unimplemented");
-}
-
-SkTypeface* SkFontHost::Deserialize(SkStream* stream) {
- SkASSERT(!"SkFontHost::Deserialize unimplemented");
- return NULL;
-}
-
-SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
-
- //Should not be used on Windows, keep linker happy
- SkASSERT(false);
- get_default_font();
- return CreateTypeface_(gDefaultFont);
-}
-
-SkScalerContext* SkFontHost::CreateScalerContext(const SkDescriptor* desc) {
- return SkNEW_ARGS(SkScalerContext_Windows, (desc));
-}
-
-SkScalerContext* SkFontHost::CreateFallbackScalerContext(const SkScalerContext::Rec& rec) {
- get_default_font();
-
- SkAutoDescriptor ad(sizeof(rec) + sizeof(gDefaultFont) + SkDescriptor::ComputeOverhead(2));
- SkDescriptor* desc = ad.getDesc();
-
- desc->init();
- SkScalerContext::Rec* newRec =
- (SkScalerContext::Rec*)desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
-
- get_default_font();
- CreateTypeface_(gDefaultFont);
- newRec->fFontID = FontFaceChecksum(gDefaultFont.lfFaceName, GetFontStyle(gDefaultFont));
- desc->computeChecksum();
-
- return SkFontHost::CreateScalerContext(desc);
-}
-
-/** Return the closest matching typeface given either an existing family
- (specified by a typeface in that family) or by a familyName, and a
- requested style.
- 1) If familyFace is null, use famillyName.
- 2) If famillyName is null, use familyFace.
- 3) If both are null, return the default font that best matches style
- This MUST not return NULL.
- */
-
-SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
- const char familyName[], SkTypeface::Style style) {
-
- SkAutoMutexAcquire ac(gFTMutex);
-
-#ifndef CAN_USE_LOGFONT_NAME
- familyName = NULL;
- familyFace = NULL;
-#endif
-
- // clip to legal style bits
- style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic);
-
- SkTypeface* tf = NULL;
- if (NULL == familyFace && NULL == familyName) {
- LOGFONT lf;
- get_default_font();
- memcpy(&lf, &gDefaultFont, sizeof(LOGFONT));
- lf.lfWeight = (style & SkTypeface::kBold) != 0 ? FW_BOLD : FW_NORMAL ;
- lf.lfItalic = ((style & SkTypeface::kItalic) != 0);
- tf = CreateTypeface_(lf);
- } else {
-#ifdef CAN_USE_LOGFONT_NAME
- LOGFONT lf;
- if (NULL != familyFace) {
- uint32_t id = familyFace->uniqueID();
- SkFaceRec* rec = find_ft_face(id);
- if (!rec) {
- SkASSERT(false);
- get_default_font();
- memcpy(&lf, &gDefaultFont, sizeof(LOGFONT));
- }
- else {
- memcpy(&lf, &(rec->fFace), sizeof(LOGFONT));
- }
- }
- else {
- memset(&lf, 0, sizeof(LOGFONT));
-
- lf.lfHeight = -11; // default
- lf.lfQuality = PROOF_QUALITY;
- lf.lfCharSet = DEFAULT_CHARSET;
-
- _tcsncpy(lf.lfFaceName, familyName, LF_FACESIZE);
- lf.lfFaceName[LF_FACESIZE-1] = '\0';
- }
-
- // use the style desired
- lf.lfWeight = (style & SkTypeface::kBold) != 0 ? FW_BOLD : FW_NORMAL ;
- lf.lfItalic = ((style & SkTypeface::kItalic) != 0);
- tf = CreateTypeface_(lf);
-#endif
- }
-
- if (NULL == tf) {
- get_default_font();
- tf = CreateTypeface_(gDefaultFont);
- }
- return tf;
-}
-
-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)
-}
-
-#endif // WIN32
-
diff --git a/src/ports/SkImageDecoder_CG.cpp b/src/ports/SkImageDecoder_CG.cpp deleted file mode 100644 index 7f8b26c..0000000 --- a/src/ports/SkImageDecoder_CG.cpp +++ /dev/null @@ -1,192 +0,0 @@ -/* Copyright 2008, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#include <Carbon/Carbon.h> -#include "SkImageDecoder.h" -#include "SkImageEncoder.h" -#include "SkMovie.h" -#include "SkStream.h" -#include "SkTemplates.h" - -static void malloc_release_proc(void* info, const void* data, size_t size) { - sk_free(info); -} - -static CGDataProviderRef SkStreamToDataProvider(SkStream* stream) { - // TODO: use callbacks, so we don't have to load all the data into RAM - size_t len = stream->getLength(); - void* data = sk_malloc_throw(len); - stream->read(data, len); - - return CGDataProviderCreateWithData(data, data, len, malloc_release_proc); -} - -static CGImageSourceRef SkStreamToCGImageSource(SkStream* stream) { - CGDataProviderRef data = SkStreamToDataProvider(stream); - CGImageSourceRef imageSrc = CGImageSourceCreateWithDataProvider(data, 0); - CGDataProviderRelease(data); - return imageSrc; -} - -class SkImageDecoder_CG : public SkImageDecoder { -protected: - virtual bool onDecode(SkStream* stream, SkBitmap* bm, - SkBitmap::Config pref, Mode); -}; - -#define BITMAP_INFO (kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast) - -bool SkImageDecoder_CG::onDecode(SkStream* stream, SkBitmap* bm, - SkBitmap::Config pref, Mode mode) { - CGImageSourceRef imageSrc = SkStreamToCGImageSource(stream); - - 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); - const int height = CGImageGetHeight(image); - 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), image); - CGContextRelease(cg); - CGColorSpaceRelease(cs); - - bm->unlockPixels(); - return true; -} - -/////////////////////////////////////////////////////////////////////////////// - -SkImageDecoder* SkImageDecoder::Factory(SkStream* stream) { - return SkNEW(SkImageDecoder_CG); -} - -///////////////////////////////////////////////////////////////////////// - -SkMovie* SkMovie::DecodeStream(SkStream* stream) { - return NULL; -} - -///////////////////////////////////////////////////////////////////////// - -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) { - switch (t) { - case kJPEG_Type: - case kPNG_Type: - break; - default: - return NULL; - } - return SkNEW_ARGS(SkImageEncoder_CG, (t)); -} - |