diff options
Diffstat (limited to 'libs')
-rw-r--r-- | libs/androidfw/ResourceTypes.cpp | 74 | ||||
-rw-r--r-- | libs/androidfw/tests/Android.mk | 30 | ||||
-rw-r--r-- | libs/androidfw/tests/ResTable_test.cpp | 81 | ||||
-rw-r--r-- | libs/hwui/AssetAtlas.cpp | 22 | ||||
-rw-r--r-- | libs/hwui/AssetAtlas.h | 62 | ||||
-rw-r--r-- | libs/hwui/Canvas.h | 7 | ||||
-rw-r--r-- | libs/hwui/DisplayListRenderer.h | 2 | ||||
-rw-r--r-- | libs/hwui/SkiaCanvas.cpp | 28 | ||||
-rw-r--r-- | libs/hwui/SkiaCanvasProxy.cpp | 1 | ||||
-rw-r--r-- | libs/hwui/renderthread/RenderProxy.cpp | 4 | ||||
-rw-r--r-- | libs/hwui/renderthread/RenderProxy.h | 2 |
11 files changed, 213 insertions, 100 deletions
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp index e247150..04ebe70 100644 --- a/libs/androidfw/ResourceTypes.cpp +++ b/libs/androidfw/ResourceTypes.cpp @@ -17,6 +17,16 @@ #define LOG_TAG "ResourceType" //#define LOG_NDEBUG 0 +#include <ctype.h> +#include <memory.h> +#include <stddef.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +#include <limits> +#include <type_traits> + #include <androidfw/ByteBucketArray.h> #include <androidfw/ResourceTypes.h> #include <androidfw/TypeWrappers.h> @@ -27,17 +37,10 @@ #include <utils/String16.h> #include <utils/String8.h> -#ifdef HAVE_ANDROID_OS +#ifdef __ANDROID__ #include <binder/TextOutput.h> #endif -#include <stdlib.h> -#include <string.h> -#include <memory.h> -#include <ctype.h> -#include <stdint.h> -#include <stddef.h> - #ifndef INT32_MAX #define INT32_MAX ((int32_t)(2147483647)) #endif @@ -4615,8 +4618,7 @@ static bool parse_unit(const char* str, Res_value* outValue, return false; } - -bool ResTable::stringToInt(const char16_t* s, size_t len, Res_value* outValue) +bool U16StringToInt(const char16_t* s, size_t len, Res_value* outValue) { while (len > 0 && isspace16(*s)) { s++; @@ -4628,7 +4630,7 @@ bool ResTable::stringToInt(const char16_t* s, size_t len, Res_value* outValue) } size_t i = 0; - int32_t val = 0; + int64_t val = 0; bool neg = false; if (*s == '-') { @@ -4640,28 +4642,50 @@ bool ResTable::stringToInt(const char16_t* s, size_t len, Res_value* outValue) return false; } + static_assert(std::is_same<uint32_t, Res_value::data_type>::value, + "Res_value::data_type has changed. The range checks in this " + "function are no longer correct."); + // Decimal or hex? - if (s[i] == '0' && s[i+1] == 'x') { - if (outValue) - outValue->dataType = outValue->TYPE_INT_HEX; + bool isHex; + if (len > 1 && s[i] == '0' && s[i+1] == 'x') { + isHex = true; i += 2; + + if (neg) { + return false; + } + + if (i == len) { + // Just u"0x" + return false; + } + bool error = false; while (i < len && !error) { val = (val*16) + get_hex(s[i], &error); i++; + + if (val > std::numeric_limits<uint32_t>::max()) { + return false; + } } if (error) { return false; } } else { - if (outValue) - outValue->dataType = outValue->TYPE_INT_DEC; + isHex = false; while (i < len) { if (s[i] < '0' || s[i] > '9') { return false; } val = (val*10) + s[i]-'0'; i++; + + if ((neg && -val < std::numeric_limits<int32_t>::min()) || + (!neg && val > std::numeric_limits<int32_t>::max())) { + return false; + } } } @@ -4671,13 +4695,21 @@ bool ResTable::stringToInt(const char16_t* s, size_t len, Res_value* outValue) i++; } - if (i == len) { - if (outValue) - outValue->data = val; - return true; + if (i != len) { + return false; } - return false; + if (outValue) { + outValue->dataType = + isHex ? outValue->TYPE_INT_HEX : outValue->TYPE_INT_DEC; + outValue->data = static_cast<Res_value::data_type>(val); + } + return true; +} + +bool ResTable::stringToInt(const char16_t* s, size_t len, Res_value* outValue) +{ + return U16StringToInt(s, len, outValue); } bool ResTable::stringToFloat(const char16_t* s, size_t len, Res_value* outValue) diff --git a/libs/androidfw/tests/Android.mk b/libs/androidfw/tests/Android.mk index 58b78b5..a353575 100644 --- a/libs/androidfw/tests/Android.mk +++ b/libs/androidfw/tests/Android.mk @@ -19,6 +19,7 @@ # targets here. # ========================================================== LOCAL_PATH:= $(call my-dir) + testFiles := \ AttributeFinder_test.cpp \ ByteBucketArray_test.cpp \ @@ -32,27 +33,33 @@ testFiles := \ TypeWrappers_test.cpp \ ZipUtils_test.cpp +androidfw_test_cflags := \ + -Wall \ + -Werror \ + -Wunused \ + -Wunreachable-code \ + -Wno-missing-field-initializers \ + +# gtest is broken. +androidfw_test_cflags += -Wno-unnamed-type-template-args + # ========================================================== # Build the host tests: libandroidfw_tests # ========================================================== include $(CLEAR_VARS) LOCAL_MODULE := libandroidfw_tests - -LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code -# gtest is broken. -LOCAL_CFLAGS += -Wno-unnamed-type-template-args - +LOCAL_CFLAGS := $(androidfw_test_cflags) LOCAL_SRC_FILES := $(testFiles) LOCAL_STATIC_LIBRARIES := \ libandroidfw \ libutils \ libcutils \ - liblog + liblog \ + libz \ include $(BUILD_HOST_NATIVE_TEST) - # ========================================================== # Build the device tests: libandroidfw_tests # ========================================================== @@ -60,14 +67,11 @@ ifneq ($(SDK_ONLY),true) include $(CLEAR_VARS) LOCAL_MODULE := libandroidfw_tests - -LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code -# gtest is broken. -LOCAL_CFLAGS += -Wno-unnamed-type-template-args - +LOCAL_CFLAGS := $(androidfw_test_cflags) LOCAL_SRC_FILES := $(testFiles) \ BackupData_test.cpp \ - ObbFile_test.cpp + ObbFile_test.cpp \ + LOCAL_SHARED_LIBRARIES := \ libandroidfw \ libcutils \ diff --git a/libs/androidfw/tests/ResTable_test.cpp b/libs/androidfw/tests/ResTable_test.cpp index 6a9314e..dcfe91e 100644 --- a/libs/androidfw/tests/ResTable_test.cpp +++ b/libs/androidfw/tests/ResTable_test.cpp @@ -16,6 +16,10 @@ #include <androidfw/ResourceTypes.h> +#include <codecvt> +#include <locale> +#include <string> + #include <utils/String8.h> #include <utils/String16.h> #include "TestHelpers.h" @@ -201,4 +205,81 @@ TEST(ResTableTest, emptyTableHasSensibleDefaults) { ASSERT_LT(table.getResource(base::R::integer::number1, &val, MAY_NOT_BE_BAG), 0); } +void testU16StringToInt(const char16_t* str, uint32_t expectedValue, + bool expectSuccess, bool expectHex) { + size_t len = std::char_traits<char16_t>::length(str); + + // Gtest can't print UTF-16 strings, so we have to convert to UTF-8 :( + std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert; + std::string s = convert.to_bytes(std::u16string(str, len)); + + Res_value out = {}; + ASSERT_EQ(expectSuccess, U16StringToInt(str, len, &out)) + << "Failed with " << s; + + if (!expectSuccess) { + ASSERT_EQ(out.TYPE_NULL, out.dataType) << "Failed with " << s; + return; + } + + if (expectHex) { + ASSERT_EQ(out.TYPE_INT_HEX, out.dataType) << "Failed with " << s; + } else { + ASSERT_EQ(out.TYPE_INT_DEC, out.dataType) << "Failed with " << s; + } + + ASSERT_EQ(expectedValue, out.data) << "Failed with " << s; +} + +TEST(ResTableTest, U16StringToInt) { + testU16StringToInt(u"", 0U, false, false); + testU16StringToInt(u" ", 0U, false, false); + testU16StringToInt(u"\t\n", 0U, false, false); + + testU16StringToInt(u"abcd", 0U, false, false); + testU16StringToInt(u"10abcd", 0U, false, false); + testU16StringToInt(u"42 42", 0U, false, false); + testU16StringToInt(u"- 42", 0U, false, false); + testU16StringToInt(u"-", 0U, false, false); + + testU16StringToInt(u"0x", 0U, false, true); + testU16StringToInt(u"0xnope", 0U, false, true); + testU16StringToInt(u"0X42", 0U, false, true); + testU16StringToInt(u"0x42 0x42", 0U, false, true); + testU16StringToInt(u"-0x0", 0U, false, true); + testU16StringToInt(u"-0x42", 0U, false, true); + testU16StringToInt(u"- 0x42", 0U, false, true); + + // Note that u" 42" would pass. This preserves the old behavior, but it may + // not be desired. + testU16StringToInt(u"42 ", 0U, false, false); + testU16StringToInt(u"0x42 ", 0U, false, true); + + // Decimal cases. + testU16StringToInt(u"0", 0U, true, false); + testU16StringToInt(u"-0", 0U, true, false); + testU16StringToInt(u"42", 42U, true, false); + testU16StringToInt(u" 42", 42U, true, false); + testU16StringToInt(u"-42", static_cast<uint32_t>(-42), true, false); + testU16StringToInt(u" -42", static_cast<uint32_t>(-42), true, false); + testU16StringToInt(u"042", 42U, true, false); + testU16StringToInt(u"-042", static_cast<uint32_t>(-42), true, false); + + // Hex cases. + testU16StringToInt(u"0x0", 0x0, true, true); + testU16StringToInt(u"0x42", 0x42, true, true); + testU16StringToInt(u" 0x42", 0x42, true, true); + + // Just before overflow cases: + testU16StringToInt(u"2147483647", INT_MAX, true, false); + testU16StringToInt(u"-2147483648", static_cast<uint32_t>(INT_MIN), true, + false); + testU16StringToInt(u"0xffffffff", UINT_MAX, true, true); + + // Overflow cases: + testU16StringToInt(u"2147483648", 0U, false, false); + testU16StringToInt(u"-2147483649", 0U, false, false); + testU16StringToInt(u"0x1ffffffff", 0U, false, true); +} + } diff --git a/libs/hwui/AssetAtlas.cpp b/libs/hwui/AssetAtlas.cpp index 4d2e3a0..882826e 100644 --- a/libs/hwui/AssetAtlas.cpp +++ b/libs/hwui/AssetAtlas.cpp @@ -82,12 +82,12 @@ void AssetAtlas::updateTextureId() { /////////////////////////////////////////////////////////////////////////////// AssetAtlas::Entry* AssetAtlas::getEntry(const SkBitmap* bitmap) const { - ssize_t index = mEntries.indexOfKey(bitmap); + ssize_t index = mEntries.indexOfKey(bitmap->pixelRef()); return index >= 0 ? mEntries.valueAt(index) : nullptr; } Texture* AssetAtlas::getEntryTexture(const SkBitmap* bitmap) const { - ssize_t index = mEntries.indexOfKey(bitmap); + ssize_t index = mEntries.indexOfKey(bitmap->pixelRef()); return index >= 0 ? mEntries.valueAt(index)->texture : nullptr; } @@ -120,7 +120,7 @@ void AssetAtlas::createEntries(Caches& caches, int64_t* map, int count) { const float height = float(mTexture->height); for (int i = 0; i < count; ) { - SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(map[i++]); + SkPixelRef* pixelRef = reinterpret_cast<SkPixelRef*>(map[i++]); // NOTE: We're converting from 64 bit signed values to 32 bit // signed values. This is guaranteed to be safe because the "x" // and "y" coordinate values are guaranteed to be representable @@ -131,21 +131,21 @@ void AssetAtlas::createEntries(Caches& caches, int64_t* map, int count) { bool rotated = map[i++] > 0; // Bitmaps should never be null, we're just extra paranoid - if (!bitmap) continue; + if (!pixelRef) continue; const UvMapper mapper( - x / width, (x + bitmap->width()) / width, - y / height, (y + bitmap->height()) / height); + x / width, (x + pixelRef->info().width()) / width, + y / height, (y + pixelRef->info().height()) / height); Texture* texture = new DelegateTexture(caches, mTexture); - texture->blend = !bitmap->isOpaque(); - texture->width = bitmap->width(); - texture->height = bitmap->height(); + texture->blend = !SkAlphaTypeIsOpaque(pixelRef->info().alphaType()); + texture->width = pixelRef->info().width(); + texture->height = pixelRef->info().height(); - Entry* entry = new Entry(bitmap, x, y, rotated, texture, mapper, *this); + Entry* entry = new Entry(pixelRef, x, y, rotated, texture, mapper, *this); texture->uvMapper = &entry->uvMapper; - mEntries.add(entry->bitmap, entry); + mEntries.add(entry->pixelRef, entry); } } diff --git a/libs/hwui/AssetAtlas.h b/libs/hwui/AssetAtlas.h index 1772eff..17c5281 100644 --- a/libs/hwui/AssetAtlas.h +++ b/libs/hwui/AssetAtlas.h @@ -48,24 +48,8 @@ public: * Entry representing the position and rotation of a * bitmap inside the atlas. */ - struct Entry { - /** - * The bitmap that generated this atlas entry. - */ - SkBitmap* bitmap; - - /** - * Location of the bitmap inside the atlas, in pixels. - */ - int x; - int y; - - /** - * If set, the bitmap is rotated 90 degrees (clockwise) - * inside the atlas. - */ - bool rotated; - + class Entry { + public: /* * A "virtual texture" object that represents the texture * this entry belongs to. This texture should never be @@ -80,11 +64,6 @@ public: const UvMapper uvMapper; /** - * Atlas this entry belongs to. - */ - const AssetAtlas& atlas; - - /** * Unique identifier used to merge bitmaps and 9-patches stored * in the atlas. */ @@ -93,10 +72,37 @@ public: } private: - Entry(SkBitmap* bitmap, int x, int y, bool rotated, - Texture* texture, const UvMapper& mapper, const AssetAtlas& atlas): - bitmap(bitmap), x(x), y(y), rotated(rotated), - texture(texture), uvMapper(mapper), atlas(atlas) { + /** + * The pixel ref that generated this atlas entry. + */ + SkPixelRef* pixelRef; + + /** + * Location of the bitmap inside the atlas, in pixels. + */ + int x; + int y; + + /** + * If set, the bitmap is rotated 90 degrees (clockwise) + * inside the atlas. + */ + bool rotated; + + /** + * Atlas this entry belongs to. + */ + const AssetAtlas& atlas; + + Entry(SkPixelRef* pixelRef, int x, int y, bool rotated, + Texture* texture, const UvMapper& mapper, const AssetAtlas& atlas) + : texture(texture) + , uvMapper(mapper) + , pixelRef(pixelRef) + , x(x) + , y(y) + , rotated(rotated) + , atlas(atlas) { } ~Entry() { @@ -178,7 +184,7 @@ private: const bool mBlendKey; const bool mOpaqueKey; - KeyedVector<const SkBitmap*, Entry*> mEntries; + KeyedVector<const SkPixelRef*, Entry*> mEntries; }; // class AssetAtlas }; // namespace uirenderer diff --git a/libs/hwui/Canvas.h b/libs/hwui/Canvas.h index 7ad0683..aa24673 100644 --- a/libs/hwui/Canvas.h +++ b/libs/hwui/Canvas.h @@ -29,7 +29,7 @@ class ANDROID_API Canvas { public: virtual ~Canvas() {}; - static Canvas* create_canvas(SkBitmap* bitmap); + static Canvas* create_canvas(const SkBitmap& bitmap); /** * Create a new Canvas object which delegates to an SkCanvas. @@ -52,7 +52,7 @@ public: */ virtual SkCanvas* asSkCanvas() = 0; - virtual void setBitmap(SkBitmap* bitmap, bool copyState) = 0; + virtual void setBitmap(const SkBitmap& bitmap) = 0; virtual bool isOpaque() = 0; virtual int width() = 0; @@ -87,7 +87,8 @@ public: virtual bool quickRejectRect(float left, float top, float right, float bottom) const = 0; virtual bool quickRejectPath(const SkPath& path) const = 0; - virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op) = 0; + virtual bool clipRect(float left, float top, float right, float bottom, + SkRegion::Op op = SkRegion::kIntersect_Op) = 0; virtual bool clipPath(const SkPath* path, SkRegion::Op op) = 0; virtual bool clipRegion(const SkRegion* region, SkRegion::Op op) = 0; diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h index 53fd1ad..ff698f5 100644 --- a/libs/hwui/DisplayListRenderer.h +++ b/libs/hwui/DisplayListRenderer.h @@ -138,7 +138,7 @@ public: // ---------------------------------------------------------------------------- virtual SkCanvas* asSkCanvas() override; - virtual void setBitmap(SkBitmap* bitmap, bool copyState) override { + virtual void setBitmap(const SkBitmap& bitmap) override { LOG_ALWAYS_FATAL("DisplayListRenderer is not backed by a bitmap."); } diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp index 8b11757..a323065 100644 --- a/libs/hwui/SkiaCanvas.cpp +++ b/libs/hwui/SkiaCanvas.cpp @@ -31,7 +31,7 @@ namespace android { // Holds an SkCanvas reference plus additional native data. class SkiaCanvas : public Canvas { public: - explicit SkiaCanvas(SkBitmap* bitmap); + explicit SkiaCanvas(const SkBitmap& bitmap); /** * Create a new SkiaCanvas. @@ -49,7 +49,7 @@ public: return mCanvas.get(); } - virtual void setBitmap(SkBitmap* bitmap, bool copyState) override; + virtual void setBitmap(const SkBitmap& bitmap) override; virtual bool isOpaque() override; virtual int width() override; @@ -145,19 +145,7 @@ private: SkAutoTDelete<SkDeque> mSaveStack; // lazily allocated, tracks partial saves. }; -// Construct an SkCanvas from the bitmap. -static SkCanvas* createCanvas(SkBitmap* bitmap) { - if (bitmap) { - return SkNEW_ARGS(SkCanvas, (*bitmap)); - } - - // Create an empty bitmap device to prevent callers from crashing - // if they attempt to draw into this canvas. - SkBitmap emptyBitmap; - return new SkCanvas(emptyBitmap); -} - -Canvas* Canvas::create_canvas(SkBitmap* bitmap) { +Canvas* Canvas::create_canvas(const SkBitmap& bitmap) { return new SkiaCanvas(bitmap); } @@ -165,8 +153,8 @@ Canvas* Canvas::create_canvas(SkCanvas* skiaCanvas) { return new SkiaCanvas(skiaCanvas); } -SkiaCanvas::SkiaCanvas(SkBitmap* bitmap) { - mCanvas.reset(createCanvas(bitmap)); +SkiaCanvas::SkiaCanvas(const SkBitmap& bitmap) { + mCanvas.reset(new SkCanvas(bitmap)); } // ---------------------------------------------------------------------------- @@ -191,11 +179,11 @@ private: SkCanvas* m_dstCanvas; }; -void SkiaCanvas::setBitmap(SkBitmap* bitmap, bool copyState) { - SkCanvas* newCanvas = createCanvas(bitmap); +void SkiaCanvas::setBitmap(const SkBitmap& bitmap) { + SkCanvas* newCanvas = new SkCanvas(bitmap); SkASSERT(newCanvas); - if (copyState) { + if (!bitmap.isNull()) { // Copy the canvas matrix & clip state. newCanvas->setMatrix(mCanvas->getTotalMatrix()); if (NULL != mCanvas->getDevice() && NULL != newCanvas->getDevice()) { diff --git a/libs/hwui/SkiaCanvasProxy.cpp b/libs/hwui/SkiaCanvasProxy.cpp index ec1bb90..8a6c8c5 100644 --- a/libs/hwui/SkiaCanvasProxy.cpp +++ b/libs/hwui/SkiaCanvasProxy.cpp @@ -289,6 +289,7 @@ void SkiaCanvasProxy::onDrawPosText(const void* text, size_t byteLength, const S // but even more conservative bounds if this is too slow. SkRect bounds; glyphs.paint.measureText(glyphs.glyphIDs, glyphs.count << 1, &bounds); + bounds.offset(x, y); SK_COMPILE_ASSERT(sizeof(SkPoint) == sizeof(float)*2, SkPoint_is_no_longer_2_floats); mCanvas->drawText(glyphs.glyphIDs, &posArray[0].fX, glyphs.count, glyphs.paint, x, y, diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp index cc87241..d15fa39 100644 --- a/libs/hwui/renderthread/RenderProxy.cpp +++ b/libs/hwui/renderthread/RenderProxy.cpp @@ -293,11 +293,11 @@ CREATE_BRIDGE3(copyLayerInto, CanvasContext* context, DeferredLayerUpdater* laye return (void*) success; } -bool RenderProxy::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) { +bool RenderProxy::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap& bitmap) { SETUP_TASK(copyLayerInto); args->context = mContext; args->layer = layer; - args->bitmap = bitmap; + args->bitmap = &bitmap; return (bool) postAndWait(task); } diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h index 29c6f08..cc475fa 100644 --- a/libs/hwui/renderthread/RenderProxy.h +++ b/libs/hwui/renderthread/RenderProxy.h @@ -83,7 +83,7 @@ public: ANDROID_API DeferredLayerUpdater* createTextureLayer(); ANDROID_API void buildLayer(RenderNode* node); - ANDROID_API bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap); + ANDROID_API bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap& bitmap); ANDROID_API void pushLayerUpdate(DeferredLayerUpdater* layer); ANDROID_API void cancelLayerUpdate(DeferredLayerUpdater* layer); ANDROID_API void detachSurfaceTexture(DeferredLayerUpdater* layer); |