Reduce heap memory in minikin.

am: 97ee89d605

Change-Id: Ifb5bbba4ce7d452d844693409ac0ecad3168ed29
This commit is contained in:
Seigo Nonaka
2017-04-15 00:59:39 +00:00
committed by android-build-merger
5 changed files with 62 additions and 6 deletions

View File

@@ -68,6 +68,7 @@ public:
private:
void initFromRanges(const uint32_t* ranges, size_t nRanges);
static const uint32_t kMaximumCapacity = 0xFFFFFF;
static const int kLogValuesPerPage = 8;
static const int kPageMask = (1 << kLogValuesPerPage) - 1;
static const int kLogBytesPerEl = 2;
@@ -77,16 +78,16 @@ private:
typedef uint32_t element;
static const element kElAllOnes = ~((element)0);
static const element kElFirst = ((element)1) << kElMask;
static const uint32_t noZeroPage = ~0u;
static const uint16_t noZeroPage = 0xFFFF;
static uint32_t calcNumPages(const uint32_t* ranges, size_t nRanges);
static int CountLeadingZeros(element x);
uint32_t mMaxVal;
std::unique_ptr<uint32_t[]> mIndices;
std::unique_ptr<uint16_t[]> mIndices;
std::unique_ptr<element[]> mBitmaps;
uint32_t mZeroPageIndex;
uint16_t mZeroPageIndex;
// Forbid copy and assign.
SparseBitSet(const SparseBitSet&) = delete;

View File

@@ -25,6 +25,7 @@ using std::vector;
#include <minikin/SparseBitSet.h>
#include <minikin/CmapCoverage.h>
#include "MinikinInternal.h"
namespace minikin {
@@ -127,6 +128,16 @@ static bool getCoverageFormat12(vector<uint32_t>& coverage, const uint8_t* data,
android_errorWriteLog(0x534e4554, "26413177");
return false;
}
// No need to read outside of Unicode code point range.
if (start > MAX_UNICODE_CODE_POINT) {
return true;
}
if (end > MAX_UNICODE_CODE_POINT) {
// file is inclusive, vector is exclusive
addRange(coverage, start, MAX_UNICODE_CODE_POINT + 1);
return true;
}
addRange(coverage, start, end + 1); // file is inclusive, vector is exclusive
}
return true;

View File

@@ -38,6 +38,8 @@ void assertMinikinLocked();
hb_blob_t* getFontTable(const MinikinFont* minikinFont, uint32_t tag);
constexpr uint32_t MAX_UNICODE_CODE_POINT = 0x10FFFF;
// An RAII wrapper for hb_blob_t
class HbBlob {
public:

View File

@@ -55,8 +55,12 @@ void SparseBitSet::initFromRanges(const uint32_t* ranges, size_t nRanges) {
if (nRanges == 0) {
return;
}
mMaxVal = ranges[nRanges * 2 - 1];
mIndices.reset(new uint32_t[(mMaxVal + kPageMask) >> kLogValuesPerPage]);
const uint32_t maxVal = ranges[nRanges * 2 - 1];
if (maxVal >= kMaximumCapacity) {
return;
}
mMaxVal = maxVal;
mIndices.reset(new uint16_t[(mMaxVal + kPageMask) >> kLogValuesPerPage]);
uint32_t nPages = calcNumPages(ranges, nRanges);
mBitmaps.reset(new element[nPages << (kLogValuesPerPage - kLogBitsPerEl)]());
mZeroPageIndex = noZeroPage;
@@ -124,7 +128,7 @@ uint32_t SparseBitSet::nextSetBit(uint32_t fromIndex) const {
}
uint32_t maxPage = (mMaxVal + kPageMask) >> kLogValuesPerPage;
for (uint32_t page = fromPage + 1; page < maxPage; page++) {
uint32_t index = mIndices[page];
uint16_t index = mIndices[page];
if (index == mZeroPageIndex) {
continue;
}

View File

@@ -271,6 +271,34 @@ TEST(CmapCoverageTest, SingleFormat12) {
}
}
TEST(CmapCoverageTest, Format12_beyondTheUnicodeLimit) {
bool has_cmap_format_14_subtable = false;
{
SCOPED_TRACE("Starting range is out of Unicode code point. Should be ignored.");
std::vector<uint8_t> cmap = CmapBuilder::buildSingleFormat12Cmap(
0, 0, std::vector<uint32_t>({'a', 'a', 0x110000, 0x110000}));
SparseBitSet coverage = CmapCoverage::getCoverage(
cmap.data(), cmap.size(), &has_cmap_format_14_subtable);
EXPECT_TRUE(coverage.get('a'));
EXPECT_FALSE(coverage.get(0x110000));
EXPECT_FALSE(has_cmap_format_14_subtable);
}
{
SCOPED_TRACE("Ending range is out of Unicode code point. Should be ignored.");
std::vector<uint8_t> cmap = CmapBuilder::buildSingleFormat12Cmap(
0, 0, std::vector<uint32_t>({'a', 'a', 0x10FF00, 0x110000}));
SparseBitSet coverage = CmapCoverage::getCoverage(
cmap.data(), cmap.size(), &has_cmap_format_14_subtable);
EXPECT_TRUE(coverage.get('a'));
EXPECT_TRUE(coverage.get(0x10FF00));
EXPECT_TRUE(coverage.get(0x10FFFF));
EXPECT_FALSE(coverage.get(0x110000));
EXPECT_FALSE(has_cmap_format_14_subtable);
}
}
TEST(CmapCoverageTest, notSupportedEncodings) {
bool has_cmap_format_14_subtable = false;
@@ -398,6 +426,16 @@ TEST(CmapCoverageTest, brokenFormat12Table) {
builder.appendTable(0, 0, table);
std::vector<uint8_t> cmap = builder.build();
SparseBitSet coverage = CmapCoverage::getCoverage(
cmap.data(), cmap.size(), &has_cmap_format_14_subtable);
EXPECT_EQ(0U, coverage.length());
EXPECT_FALSE(has_cmap_format_14_subtable);
}
{
SCOPED_TRACE("Too large code point");
std::vector<uint8_t> cmap = CmapBuilder::buildSingleFormat12Cmap(
0, 0, std::vector<uint32_t>({0x110000, 0x110000}));
SparseBitSet coverage = CmapCoverage::getCoverage(
cmap.data(), cmap.size(), &has_cmap_format_14_subtable);
EXPECT_EQ(0U, coverage.length());