Bug 777614 - Update patches directory for patches applied against upstream Skia

This commit is contained in:
George Wright 2012-09-18 15:32:26 -04:00
parent acfc80edb4
commit d8dc00adc0
22 changed files with 960 additions and 16 deletions

View File

@ -0,0 +1,34 @@
From 2dd8c789fc4ad3b5323c2c29f3e982d185f5b5d9 Mon Sep 17 00:00:00 2001
From: George Wright <gw@gwright.org.uk>
Date: Thu, 13 Sep 2012 22:33:38 -0400
Subject: [PATCH 1/9] Bug 777614 - Re-add our SkUserConfig.h r=nrc
---
gfx/skia/include/config/SkUserConfig.h | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/gfx/skia/include/config/SkUserConfig.h b/gfx/skia/include/config/SkUserConfig.h
index 353272c..fbfbfe0 100644
--- a/gfx/skia/include/config/SkUserConfig.h
+++ b/gfx/skia/include/config/SkUserConfig.h
@@ -184,5 +184,16 @@
directories from your include search path when you're not building the GPU
backend. Defaults to 1 (build the GPU code).
*/
-//#define SK_SUPPORT_GPU 1
+#define SK_SUPPORT_GPU 0
+
+/* Don't dither 32bit gradients, to match what the canvas test suite expects.
+ */
+#define SK_DISABLE_DITHER_32BIT_GRADIENT
+
+/* Don't include stdint.h on windows as it conflicts with our build system.
+ */
+#ifdef SK_BUILD_FOR_WIN32
+ #define SK_IGNORE_STDINT_DOT_H
+#endif
+
#endif
--
1.7.11.4

View File

@ -0,0 +1,684 @@
From 0d730a94e9f6676d5cde45f955fe025a4549817e Mon Sep 17 00:00:00 2001
From: George Wright <gw@gwright.org.uk>
Date: Thu, 23 Aug 2012 16:45:38 -0400
Subject: [PATCH 4/9] Bug 777614 - Re-apply bug 719872 - Fix crash on Android
by reverting to older FontHost r=nrc
---
gfx/skia/src/ports/SkFontHost_android_old.cpp | 664 ++++++++++++++++++++++++++
1 file changed, 664 insertions(+)
create mode 100644 gfx/skia/src/ports/SkFontHost_android_old.cpp
diff --git a/gfx/skia/src/ports/SkFontHost_android_old.cpp b/gfx/skia/src/ports/SkFontHost_android_old.cpp
new file mode 100644
index 0000000..b5c4f3c
--- /dev/null
+++ b/gfx/skia/src/ports/SkFontHost_android_old.cpp
@@ -0,0 +1,664 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#include "SkFontHost.h"
+#include "SkDescriptor.h"
+#include "SkMMapStream.h"
+#include "SkPaint.h"
+#include "SkString.h"
+#include "SkStream.h"
+#include "SkThread.h"
+#include "SkTSearch.h"
+#include <stdio.h>
+
+#define FONT_CACHE_MEMORY_BUDGET (768 * 1024)
+
+#ifndef SK_FONT_FILE_PREFIX
+ #define SK_FONT_FILE_PREFIX "/fonts/"
+#endif
+
+bool find_name_and_attributes(SkStream* stream, SkString* name, SkTypeface::Style* style,
+ bool* isFixedWidth);
+
+static void GetFullPathForSysFonts(SkString* full, const char name[]) {
+ full->set(getenv("ANDROID_ROOT"));
+ 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;
+}
+
+/* Returns the matching typeface, or NULL. If a typeface is found, its refcnt
+ is not modified.
+ */
+static SkTypeface* find_from_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 face;
+ }
+ }
+ curr = curr->fNext;
+ }
+ return NULL;
+}
+
+/* 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 SkTypeface* find_typeface(const char name[], SkTypeface::Style style) {
+ NameFamilyPair* list = gNameList.begin();
+ int count = gNameList.count();
+
+ int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0]));
+
+ if (index >= 0) {
+ return find_best_face(list[index].fFamily, style);
+ }
+ return 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, SkTypeface* familyMember,
+ bool isFixedWidth)
+ : SkTypeface(style, sk_atomic_inc(&gUniqueFontID) + 1, isFixedWidth) {
+ fIsSysFont = sysFont;
+
+ SkAutoMutexAcquire ac(gFamilyMutex);
+
+ FamilyRec* rec = NULL;
+ if (familyMember) {
+ rec = find_family(familyMember);
+ SkASSERT(rec);
+ } else {
+ rec = SkNEW(FamilyRec);
+ }
+ rec->fFaces[style] = this;
+ }
+
+ 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; }
+
+ virtual SkStream* openStream() = 0;
+ virtual const char* getUniqueString() const = 0;
+ virtual const char* getFilePath() const = 0;
+
+private:
+ bool fIsSysFont;
+
+ typedef SkTypeface INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class StreamTypeface : public FamilyTypeface {
+public:
+ StreamTypeface(Style style, bool sysFont, SkTypeface* familyMember,
+ SkStream* stream, bool isFixedWidth)
+ : INHERITED(style, sysFont, familyMember, isFixedWidth) {
+ SkASSERT(stream);
+ stream->ref();
+ fStream = stream;
+ }
+ virtual ~StreamTypeface() {
+ fStream->unref();
+ }
+
+ // overrides
+ virtual SkStream* openStream() {
+ // we just ref our existing stream, since the caller will call unref()
+ // when they are through
+ fStream->ref();
+ // must rewind each time, since the caller assumes a "new" stream
+ fStream->rewind();
+ return fStream;
+ }
+ virtual const char* getUniqueString() const { return NULL; }
+ virtual const char* getFilePath() const { return NULL; }
+
+private:
+ SkStream* fStream;
+
+ typedef FamilyTypeface INHERITED;
+};
+
+class FileTypeface : public FamilyTypeface {
+public:
+ FileTypeface(Style style, bool sysFont, SkTypeface* familyMember,
+ const char path[], bool isFixedWidth)
+ : INHERITED(style, sysFont, familyMember, isFixedWidth) {
+ SkString fullpath;
+
+ if (sysFont) {
+ GetFullPathForSysFonts(&fullpath, path);
+ path = fullpath.c_str();
+ }
+ 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 const char* getUniqueString() const {
+ const char* str = strrchr(fPath.c_str(), '/');
+ if (str) {
+ str += 1; // skip the '/'
+ }
+ return str;
+ }
+ virtual const char* getFilePath() const {
+ return fPath.c_str();
+ }
+
+private:
+ SkString fPath;
+
+ typedef FamilyTypeface INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+static bool get_name_and_style(const char path[], SkString* name,
+ SkTypeface::Style* style,
+ bool* isFixedWidth, bool isExpected) {
+ SkString fullpath;
+ GetFullPathForSysFonts(&fullpath, path);
+
+ SkMMAPStream stream(fullpath.c_str());
+ if (stream.getLength() > 0) {
+ find_name_and_attributes(&stream, name, style, isFixedWidth);
+ return true;
+ }
+ else {
+ SkFILEStream stream(fullpath.c_str());
+ if (stream.getLength() > 0) {
+ find_name_and_attributes(&stream, name, style, isFixedWidth);
+ return true;
+ }
+ }
+
+ if (isExpected) {
+ SkDebugf("---- failed to open <%s> as a font\n", fullpath.c_str());
+ }
+ return false;
+}
+
+// used to record our notion of the pre-existing fonts
+struct FontInitRec {
+ const char* fFileName;
+ const char* const* fNames; // null-terminated list
+};
+
+static const char* gSansNames[] = {
+ "sans-serif", "arial", "helvetica", "tahoma", "verdana", NULL
+};
+
+static const char* gSerifNames[] = {
+ "serif", "times", "times new roman", "palatino", "georgia", "baskerville",
+ "goudy", "fantasy", "cursive", "ITC Stone Serif", NULL
+};
+
+static const char* gMonoNames[] = {
+ "monospace", "courier", "courier new", "monaco", NULL
+};
+
+// deliberately empty, but we use the address to identify fallback fonts
+static const char* gFBNames[] = { NULL };
+
+/* Fonts must be grouped by family, with the first font in a family having the
+ list of names (even if that list is empty), and the following members having
+ null for the list. The names list must be NULL-terminated
+*/
+static const FontInitRec gSystemFonts[] = {
+ { "DroidSans.ttf", gSansNames },
+ { "DroidSans-Bold.ttf", NULL },
+ { "DroidSerif-Regular.ttf", gSerifNames },
+ { "DroidSerif-Bold.ttf", NULL },
+ { "DroidSerif-Italic.ttf", NULL },
+ { "DroidSerif-BoldItalic.ttf", NULL },
+ { "DroidSansMono.ttf", gMonoNames },
+ /* These are optional, and can be ignored if not found in the file system.
+ These are appended to gFallbackFonts[] as they are seen, so we list
+ them in the order we want them to be accessed by NextLogicalFont().
+ */
+ { "DroidSansArabic.ttf", gFBNames },
+ { "DroidSansHebrew.ttf", gFBNames },
+ { "DroidSansThai.ttf", gFBNames },
+ { "MTLmr3m.ttf", gFBNames }, // Motoya Japanese Font
+ { "MTLc3m.ttf", gFBNames }, // Motoya Japanese Font
+ { "DroidSansJapanese.ttf", gFBNames },
+ { "DroidSansFallback.ttf", gFBNames }
+};
+
+#define DEFAULT_NAMES gSansNames
+
+// these globals are assigned (once) by load_system_fonts()
+static FamilyRec* gDefaultFamily;
+static SkTypeface* gDefaultNormal;
+
+/* This is sized conservatively, assuming that it will never be a size issue.
+ It will be initialized in load_system_fonts(), and will be filled with the
+ fontIDs that can be used for fallback consideration, in sorted order (sorted
+ meaning element[0] should be used first, then element[1], etc. When we hit
+ a fontID==0 in the array, the list is done, hence our allocation size is
+ +1 the total number of possible system fonts. Also see NextLogicalFont().
+ */
+static uint32_t gFallbackFonts[SK_ARRAY_COUNT(gSystemFonts)+1];
+
+/* Called once (ensured by the sentinel check at the beginning of our body).
+ Initializes all the globals, and register the system fonts.
+ */
+static void load_system_fonts() {
+ // check if we've already be called
+ if (NULL != gDefaultNormal) {
+ return;
+ }
+
+ const FontInitRec* rec = gSystemFonts;
+ SkTypeface* firstInFamily = NULL;
+ int fallbackCount = 0;
+
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gSystemFonts); i++) {
+ // if we're the first in a new family, clear firstInFamily
+ if (rec[i].fNames != NULL) {
+ firstInFamily = NULL;
+ }
+
+ bool isFixedWidth;
+ SkString name;
+ SkTypeface::Style style;
+
+ // we expect all the fonts, except the "fallback" fonts
+ bool isExpected = (rec[i].fNames != gFBNames);
+ if (!get_name_and_style(rec[i].fFileName, &name, &style,
+ &isFixedWidth, isExpected)) {
+ continue;
+ }
+
+ SkTypeface* tf = SkNEW_ARGS(FileTypeface,
+ (style,
+ true, // system-font (cannot delete)
+ firstInFamily, // what family to join
+ rec[i].fFileName,
+ isFixedWidth) // filename
+ );
+
+ if (rec[i].fNames != NULL) {
+ // see if this is one of our fallback fonts
+ if (rec[i].fNames == gFBNames) {
+ // SkDebugf("---- adding %s as fallback[%d] fontID %d\n",
+ // rec[i].fFileName, fallbackCount, tf->uniqueID());
+ gFallbackFonts[fallbackCount++] = tf->uniqueID();
+ }
+
+ firstInFamily = tf;
+ FamilyRec* family = find_family(tf);
+ const char* const* names = rec[i].fNames;
+
+ // record the default family if this is it
+ if (names == DEFAULT_NAMES) {
+ gDefaultFamily = family;
+ }
+ // add the names to map to this family
+ while (*names) {
+ add_name(*names, family);
+ names += 1;
+ }
+ }
+ }
+
+ // 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
+ gDefaultNormal = find_best_face(gDefaultFamily, SkTypeface::kNormal);
+ // now terminate our fallback list with the sentinel value
+ gFallbackFonts[fallbackCount] = 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) {
+ const char* name = ((FamilyTypeface*)face)->getUniqueString();
+
+ stream->write8((uint8_t)face->style());
+
+ 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->style());
+ }
+}
+
+SkTypeface* SkFontHost::Deserialize(SkStream* stream) {
+ 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 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);
+ }
+
+ // we ref(), since the symantic is to return a new instance
+ tf->ref();
+ return tf;
+}
+
+SkStream* SkFontHost::OpenStream(uint32_t fontID) {
+ SkAutoMutexAcquire ac(gFamilyMutex);
+
+ FamilyTypeface* tf = (FamilyTypeface*)find_from_uniqueID(fontID);
+ SkStream* stream = tf ? tf->openStream() : NULL;
+
+ if (stream && stream->getLength() == 0) {
+ stream->unref();
+ stream = NULL;
+ }
+ return stream;
+}
+
+size_t SkFontHost::GetFileName(SkFontID fontID, char path[], size_t length,
+ int32_t* index) {
+ SkAutoMutexAcquire ac(gFamilyMutex);
+
+ FamilyTypeface* tf = (FamilyTypeface*)find_from_uniqueID(fontID);
+ const char* src = tf ? tf->getFilePath() : NULL;
+
+ if (src) {
+ size_t size = strlen(src);
+ if (path) {
+ memcpy(path, src, SkMin32(size, length));
+ }
+ if (index) {
+ *index = 0; // we don't have collections (yet)
+ }
+ return size;
+ } else {
+ return 0;
+ }
+}
+
+SkFontID SkFontHost::NextLogicalFont(SkFontID currFontID, SkFontID origFontID) {
+ load_system_fonts();
+
+ /* First see if fontID is already one of our fallbacks. If so, return
+ its successor. If fontID is not in our list, then return the first one
+ in our list. Note: list is zero-terminated, and returning zero means
+ we have no more fonts to use for fallbacks.
+ */
+ const uint32_t* list = gFallbackFonts;
+ for (int i = 0; list[i] != 0; i++) {
+ if (list[i] == currFontID) {
+ return list[i+1];
+ }
+ }
+ return list[0];
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
+ if (NULL == stream || stream->getLength() <= 0) {
+ return NULL;
+ }
+
+ bool isFixedWidth;
+ SkString name;
+ SkTypeface::Style style;
+ find_name_and_attributes(stream, &name, &style, &isFixedWidth);
+
+ if (!name.isEmpty()) {
+ return SkNEW_ARGS(StreamTypeface, (style, false, NULL, stream, isFixedWidth));
+ } else {
+ return NULL;
+ }
+}
+
+SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
+ SkStream* stream = SkNEW_ARGS(SkMMAPStream, (path));
+ SkTypeface* face = SkFontHost::CreateTypefaceFromStream(stream);
+ // since we created the stream, we let go of our ref() here
+ stream->unref();
+ return face;
+}
+
+///////////////////////////////////////////////////////////////////////////////
--
1.7.11.4

View File

@ -0,0 +1,198 @@
From 1ab13a923399aa638388231baca784ba89f2c82b Mon Sep 17 00:00:00 2001
From: George Wright <gw@gwright.org.uk>
Date: Wed, 12 Sep 2012 12:30:29 -0400
Subject: [PATCH 5/9] Bug 777614 - Re-apply bug 687188 - Expand the gradient
cache by 2 to store 0/1 colour stop values for
clamping. r=nrc
---
.../src/effects/gradients/SkGradientShader.cpp | 22 +++++++++++----
.../src/effects/gradients/SkGradientShaderPriv.h | 5 +++-
.../src/effects/gradients/SkLinearGradient.cpp | 32 ++++++++++++++++------
.../gradients/SkTwoPointConicalGradient.cpp | 11 ++++++--
.../effects/gradients/SkTwoPointRadialGradient.cpp | 11 ++++++--
5 files changed, 61 insertions(+), 20 deletions(-)
diff --git a/gfx/skia/src/effects/gradients/SkGradientShader.cpp b/gfx/skia/src/effects/gradients/SkGradientShader.cpp
index f0dac4d..79e7202 100644
--- a/gfx/skia/src/effects/gradients/SkGradientShader.cpp
+++ b/gfx/skia/src/effects/gradients/SkGradientShader.cpp
@@ -426,15 +426,15 @@ static void complete_32bit_cache(SkPMColor* cache, int stride) {
const SkPMColor* SkGradientShaderBase::getCache32() const {
if (fCache32 == NULL) {
- // double the count for dither entries
- const int entryCount = kCache32Count * 2;
+ // double the count for dither entries, and have an extra two entries for clamp values
+ const int entryCount = kCache32Count * 2 + 2;
const size_t allocSize = sizeof(SkPMColor) * entryCount;
if (NULL == fCache32PixelRef) {
fCache32PixelRef = SkNEW_ARGS(SkMallocPixelRef,
(NULL, allocSize, NULL));
}
- fCache32 = (SkPMColor*)fCache32PixelRef->getAddr();
+ fCache32 = (SkPMColor*)fCache32PixelRef->getAddr() + 1;
if (fColorCount == 2) {
Build32bitCache(fCache32, fOrigColors[0], fOrigColors[1],
kGradient32Length, fCacheAlpha);
@@ -458,7 +458,7 @@ const SkPMColor* SkGradientShaderBase::getCache32() const {
SkMallocPixelRef* newPR = SkNEW_ARGS(SkMallocPixelRef,
(NULL, allocSize, NULL));
SkPMColor* linear = fCache32; // just computed linear data
- SkPMColor* mapped = (SkPMColor*)newPR->getAddr(); // storage for mapped data
+ SkPMColor* mapped = (SkPMColor*)newPR->getAddr() + 1; // storage for mapped data
SkUnitMapper* map = fMapper;
for (int i = 0; i < kGradient32Length; i++) {
int index = map->mapUnit16((i << 8) | i) >> 8;
@@ -467,10 +467,22 @@ const SkPMColor* SkGradientShaderBase::getCache32() const {
}
fCache32PixelRef->unref();
fCache32PixelRef = newPR;
- fCache32 = (SkPMColor*)newPR->getAddr();
+ fCache32 = (SkPMColor*)newPR->getAddr() + 1;
}
complete_32bit_cache(fCache32, kCache32Count);
}
+
+ // Write the clamp colours into the first and last entries of fCache32
+ fCache32[kCache32ClampLower] = SkPackARGB32(fCacheAlpha,
+ SkColorGetR(fOrigColors[0]),
+ SkColorGetG(fOrigColors[0]),
+ SkColorGetB(fOrigColors[0]));
+
+ fCache32[kCache32ClampUpper] = SkPackARGB32(fCacheAlpha,
+ SkColorGetR(fOrigColors[fColorCount - 1]),
+ SkColorGetG(fOrigColors[fColorCount - 1]),
+ SkColorGetB(fOrigColors[fColorCount - 1]));
+
return fCache32;
}
diff --git a/gfx/skia/src/effects/gradients/SkGradientShaderPriv.h b/gfx/skia/src/effects/gradients/SkGradientShaderPriv.h
index 0e7c2fc..7427935 100644
--- a/gfx/skia/src/effects/gradients/SkGradientShaderPriv.h
+++ b/gfx/skia/src/effects/gradients/SkGradientShaderPriv.h
@@ -133,7 +133,10 @@ public:
kDitherStride32 = 0,
#endif
kDitherStride16 = kCache16Count,
- kLerpRemainderMask32 = (1 << (16 - kCache32Bits)) - 1
+ kLerpRemainderMask32 = (1 << (16 - kCache32Bits)) - 1,
+
+ kCache32ClampLower = -1,
+ kCache32ClampUpper = kCache32Count * 2
};
diff --git a/gfx/skia/src/effects/gradients/SkLinearGradient.cpp b/gfx/skia/src/effects/gradients/SkLinearGradient.cpp
index bcebc26..d400b4d 100644
--- a/gfx/skia/src/effects/gradients/SkLinearGradient.cpp
+++ b/gfx/skia/src/effects/gradients/SkLinearGradient.cpp
@@ -126,6 +126,17 @@ void shadeSpan_linear_vertical(TileProc proc, SkFixed dx, SkFixed fx,
SkPMColor* SK_RESTRICT dstC,
const SkPMColor* SK_RESTRICT cache,
int toggle, int count) {
+ if (proc == clamp_tileproc) {
+ // No need to lerp or dither for clamp values
+ if (fx < 0) {
+ sk_memset32(dstC, cache[SkGradientShaderBase::kCache32ClampLower], count);
+ return;
+ } else if (fx > 0xffff) {
+ sk_memset32(dstC, cache[SkGradientShaderBase::kCache32ClampUpper], count);
+ return;
+ }
+ }
+
// We're a vertical gradient, so no change in a span.
// If colors change sharply across the gradient, dithering is
// insufficient (it subsamples the color space) and we need to lerp.
@@ -144,6 +155,17 @@ void shadeSpan_linear_vertical_lerp(TileProc proc, SkFixed dx, SkFixed fx,
SkPMColor* SK_RESTRICT dstC,
const SkPMColor* SK_RESTRICT cache,
int toggle, int count) {
+ if (proc == clamp_tileproc) {
+ // No need to lerp or dither for clamp values
+ if (fx < 0) {
+ sk_memset32(dstC, cache[SkGradientShaderBase::kCache32ClampLower], count);
+ return;
+ } else if (fx > 0xffff) {
+ sk_memset32(dstC, cache[SkGradientShaderBase::kCache32ClampUpper], count);
+ return;
+ }
+ }
+
// We're a vertical gradient, so no change in a span.
// If colors change sharply across the gradient, dithering is
// insufficient (it subsamples the color space) and we need to lerp.
@@ -169,10 +191,7 @@ void shadeSpan_linear_clamp(TileProc proc, SkFixed dx, SkFixed fx,
range.init(fx, dx, count, 0, SkGradientShaderBase::kGradient32Length);
if ((count = range.fCount0) > 0) {
- sk_memset32_dither(dstC,
- cache[toggle + range.fV0],
- cache[(toggle ^ SkGradientShaderBase::kDitherStride32) + range.fV0],
- count);
+ sk_memset32(dstC, cache[SkGradientShaderBase::kCache32ClampLower], count);
dstC += count;
}
if ((count = range.fCount1) > 0) {
@@ -191,10 +210,7 @@ void shadeSpan_linear_clamp(TileProc proc, SkFixed dx, SkFixed fx,
}
}
if ((count = range.fCount2) > 0) {
- sk_memset32_dither(dstC,
- cache[toggle + range.fV1],
- cache[(toggle ^ SkGradientShaderBase::kDitherStride32) + range.fV1],
- count);
+ sk_memset32(dstC, cache[SkGradientShaderBase::kCache32ClampUpper], count);
}
}
diff --git a/gfx/skia/src/effects/gradients/SkTwoPointConicalGradient.cpp b/gfx/skia/src/effects/gradients/SkTwoPointConicalGradient.cpp
index 3466d2c..764a444 100644
--- a/gfx/skia/src/effects/gradients/SkTwoPointConicalGradient.cpp
+++ b/gfx/skia/src/effects/gradients/SkTwoPointConicalGradient.cpp
@@ -123,9 +123,14 @@ static void twopoint_clamp(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC,
if (TwoPtRadial::DontDrawT(t)) {
*dstC++ = 0;
} else {
- SkFixed index = SkClampMax(t, 0xFFFF);
- SkASSERT(index <= 0xFFFF);
- *dstC++ = cache[index >> SkGradientShaderBase::kCache32Shift];
+ if (t < 0) {
+ *dstC++ = cache[SkGradientShaderBase::kCache32ClampLower];
+ } else if (t > 0xFFFF) {
+ *dstC++ = cache[SkGradientShaderBase::kCache32ClampUpper];
+ } else {
+ SkASSERT(t <= 0xFFFF);
+ *dstC++ = cache[t >> SkGradientShaderBase::kCache32Shift];
+ }
}
}
}
diff --git a/gfx/skia/src/effects/gradients/SkTwoPointRadialGradient.cpp b/gfx/skia/src/effects/gradients/SkTwoPointRadialGradient.cpp
index 9362ded..22b028e 100644
--- a/gfx/skia/src/effects/gradients/SkTwoPointRadialGradient.cpp
+++ b/gfx/skia/src/effects/gradients/SkTwoPointRadialGradient.cpp
@@ -120,9 +120,14 @@ void shadeSpan_twopoint_clamp(SkScalar fx, SkScalar dx,
for (; count > 0; --count) {
SkFixed t = two_point_radial(b, fx, fy, fSr2D2, foura,
fOneOverTwoA, posRoot);
- SkFixed index = SkClampMax(t, 0xFFFF);
- SkASSERT(index <= 0xFFFF);
- *dstC++ = cache[index >> SkGradientShaderBase::kCache32Shift];
+ if (t < 0) {
+ *dstC++ = cache[SkGradientShaderBase::kCache32ClampLower];
+ } else if (t > 0xFFFF) {
+ *dstC++ = cache[SkGradientShaderBase::kCache32ClampUpper];
+ } else {
+ SkASSERT(t <= 0xFFFF);
+ *dstC++ = cache[t >> SkGradientShaderBase::kCache32Shift];
+ }
fx += dx;
fy += dy;
b += db;
--
1.7.11.4

View File

@ -0,0 +1,40 @@
From 2c5a8cebc806ed287ce7c3723ea64a233266cd9e Mon Sep 17 00:00:00 2001
From: George Wright <gw@gwright.org.uk>
Date: Thu, 13 Sep 2012 14:55:33 -0400
Subject: [PATCH 9/9] Bug 777614 - Re-apply 759683 - Handle compilers that
don't support SSSE3 intrinsics r=nrc
---
gfx/skia/src/opts/opts_check_SSE2.cpp | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/gfx/skia/src/opts/opts_check_SSE2.cpp b/gfx/skia/src/opts/opts_check_SSE2.cpp
index 96d0dea..add6d5f 100644
--- a/gfx/skia/src/opts/opts_check_SSE2.cpp
+++ b/gfx/skia/src/opts/opts_check_SSE2.cpp
@@ -86,9 +86,13 @@ static inline bool hasSSSE3() {
#else
static inline bool hasSSSE3() {
+#if defined(SK_BUILD_SSSE3)
int cpu_info[4] = { 0 };
getcpuid(1, cpu_info);
return (cpu_info[2] & 0x200) != 0;
+#else
+ return false;
+#endif
}
#endif
@@ -104,7 +108,7 @@ static bool cachedHasSSSE3() {
void SkBitmapProcState::platformProcs() {
if (cachedHasSSSE3()) {
-#if !defined(SK_BUILD_FOR_ANDROID)
+#if !defined(SK_BUILD_FOR_ANDROID) && defined(SK_BUILD_SSSE3)
// Disable SSSE3 optimization for Android x86
if (fSampleProc32 == S32_opaque_D32_filter_DX) {
fSampleProc32 = S32_opaque_D32_filter_DX_SSSE3;
--
1.7.11.4

View File

@ -3,19 +3,7 @@ The original patches are archived in archive/
See the relevant bugs in bugzilla for information on these patches:
0001-Bug-687189-Implement-SkPaint-getPosTextPath.patch
0002-Bug-688366-Dont-invalidate-all-radial-gradients.patch
0003-SkUserConfig-for-Mozilla.patch
0004-Bug-722011-Fix-trailing-commas-in-enums.patch
0005-Bug-731384-Fix-clang-SK_OVERRIDE.patch
0006-Bug-751814-ARM-EDSP-ARMv6-Skia-fixes.patch
0007-Bug-719872-Old-Android-FontHost.patch
0008-Bug-687188-Skia-radial-gradients.patch
0009-Bug-755869-FreeBSD-Hurd.patch
0010-Bug-689069-ARM-Opts.patch
0011-Bug-719575-Fix-clang-build.patch
0012-Bug-759683-make-ssse3-conditional.patch
0013-Bug-761890-fonts.patch
0014-Bug-765038-Fix-clang-build.patch
0015-Bug-766017-warnings.patch
0016-Bug-718849-Radial-Gradients.patch
0001-Bug-777614-Re-add-our-SkUserConfig.h-r-nrc.patch
0004-Bug-777614-Re-apply-bug-719872-Fix-crash-on-Android-.patch
0005-Bug-777614-Re-apply-bug-687188-Expand-the-gradient-c.patch
0009-Bug-777614-Re-apply-759683-Handle-compilers-that-don.patch