diff options
author | reed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2009-04-14 14:28:22 +0000 |
---|---|---|
committer | reed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2009-04-14 14:28:22 +0000 |
commit | 1dc0ad757eddbe5cdf1440a2ce24ad77304ac92f (patch) | |
tree | f7c9d8f736630f007bfdedc2021090013fd16112 | |
parent | 04eef65090a9f261826ed82f4e3abc86d593d62a (diff) | |
download | src-1dc0ad757eddbe5cdf1440a2ce24ad77304ac92f.tar.gz |
add SkSfntUtils to parse some known truetype tables
add comments and cleanup to count_tables in SkFontHost_tables.cpp
fix transparency bug in gifs
use (alpha+1) for blending in srcover mode, to ensure opaque results
git-svn-id: http://skia.googlecode.com/svn/trunk/src@155 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r-- | images/SkImageDecoder_libgif.cpp | 15 | ||||
-rw-r--r-- | ports/SkFontHost_tables.cpp | 34 | ||||
-rw-r--r-- | utils/SkNinePatch.cpp | 2 | ||||
-rw-r--r-- | utils/SkSfntUtils.cpp | 87 | ||||
-rw-r--r-- | utils/utils_files.mk | 10 |
5 files changed, 134 insertions, 14 deletions
diff --git a/images/SkImageDecoder_libgif.cpp b/images/SkImageDecoder_libgif.cpp index ed8817ab..86ead1fa 100644 --- a/images/SkImageDecoder_libgif.cpp +++ b/images/SkImageDecoder_libgif.cpp @@ -171,6 +171,7 @@ bool SkGIFImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* bm, int width, height; GifRecordType recType; GifByteType *extData; + int transpIndex = -1; // -1 means we don't have it (yet) do { if (DGifGetRecordType(gif, &recType) == GIF_ERROR) { @@ -226,7 +227,7 @@ bool SkGIFImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* bm, cmap->Colors[index].Green, cmap->Colors[index].Blue); - int transpIndex = find_transpIndex(temp_save, colorCount); + transpIndex = find_transpIndex(temp_save, colorCount); if (transpIndex < 0) ctable->setFlags(ctable->getFlags() | SkColorTable::kColorsAreOpaque_Flag); else @@ -257,12 +258,18 @@ bool SkGIFImageDecoder::onDecode(SkStream* sk_stream, SkBitmap* bm, if ((desc.Top | desc.Left) > 0 || innerWidth < width || innerHeight < height) { - uint8_t fill = (uint8_t)gif->SBackGroundColor; + int fill; + if (transpIndex >= 0) { + fill = transpIndex; + } else { + fill = gif->SBackGroundColor; + } // check for valid fill index/color - if (fill >= (unsigned)colorCount) { + if (static_cast<unsigned>(fill) >= + static_cast<unsigned>(colorCount)) { fill = 0; } - memset(scanline, gif->SBackGroundColor, bm->getSize()); + memset(scanline, fill, bm->getSize()); // bump our starting address scanline += desc.Top * rowBytes + desc.Left; } diff --git a/ports/SkFontHost_tables.cpp b/ports/SkFontHost_tables.cpp index fdf0b063..49452728 100644 --- a/ports/SkFontHost_tables.cpp +++ b/ports/SkFontHost_tables.cpp @@ -29,18 +29,30 @@ struct SkSFNTDirEntry { uint32_t fLength; }; +/** Return the number of tables, or if this is a TTC (collection), return the + number of tables in the first element of the collection. In either case, + if offsetToDir is not-null, set it to the offset to the beginning of the + table headers (SkSFNTDirEntry), relative to the start of the stream. + + On an error, return 0 for number of tables, and ignore offsetToDir + */ static int count_tables(SkStream* stream, size_t* offsetToDir = NULL) { SkSharedTTHeader shared; if (stream->read(&shared, sizeof(shared)) != sizeof(shared)) { return 0; } + // by default, SkSFNTHeader is at the start of the stream + size_t offset = 0; + + // if we're really a collection, the first 4-bytes will be 'ttcf' uint32_t tag = SkEndian_SwapBE32(shared.fCollection.fTag); if (SkSetFourByteTag('t', 't', 'c', 'f') == tag) { if (shared.fCollection.fNumOffsets == 0) { return 0; } - size_t offset = SkEndian_SwapBE32(shared.fCollection.fOffset0); + // this is the offset to the first local SkSFNTHeader + offset = SkEndian_SwapBE32(shared.fCollection.fOffset0); stream->rewind(); if (stream->skip(offset) != offset) { return 0; @@ -48,13 +60,12 @@ static int count_tables(SkStream* stream, size_t* offsetToDir = NULL) { if (stream->read(&shared, sizeof(shared)) != sizeof(shared)) { return 0; } - if (offsetToDir) { - *offsetToDir = offset; - } - } else { - *offsetToDir = 0; } - + + if (offsetToDir) { + // add the size of the header, so we will point to the DirEntries + *offsetToDir = offset + sizeof(SkSFNTDirEntry); + } return SkEndian_SwapBE16(shared.fSingle.fNumTables); } @@ -64,6 +75,12 @@ struct SfntHeader { SfntHeader() : fCount(0), fDir(NULL) {} ~SfntHeader() { sk_free(fDir); } + /** If it returns true, then fCount and fDir are properly initialized. + Note: fDir will point to the raw array of SkSFNTDirEntry values, + meaning they will still be in the file's native endianness (BE). + + fDir will be automatically freed when this object is destroyed + */ bool init(SkStream* stream) { size_t offsetToDir; fCount = count_tables(stream, &offsetToDir); @@ -72,8 +89,7 @@ struct SfntHeader { } stream->rewind(); - const size_t tableRecordOffset = offsetToDir + sizeof(SkSFNTHeader); - if (stream->skip(tableRecordOffset) != tableRecordOffset) { + if (stream->skip(offsetToDir) != offsetToDir) { return false; } diff --git a/utils/SkNinePatch.cpp b/utils/SkNinePatch.cpp index b8e11fbc..3d85edcf 100644 --- a/utils/SkNinePatch.cpp +++ b/utils/SkNinePatch.cpp @@ -186,7 +186,7 @@ void SkNinePatch::DrawMesh(SkCanvas* canvas, const SkRect& bounds, if (numXDivs == 2 && numYDivs <= 2) { mesh.fIndices = g3x3Indices; } else { - int n = fillIndices(indices, numXDivs + 1, numYDivs + 1); + SkDEBUGCODE(int n =) fillIndices(indices, numXDivs + 1, numYDivs + 1); SkASSERT(n == indexCount); mesh.fIndices = indices; } diff --git a/utils/SkSfntUtils.cpp b/utils/SkSfntUtils.cpp new file mode 100644 index 00000000..36f1f97d --- /dev/null +++ b/utils/SkSfntUtils.cpp @@ -0,0 +1,87 @@ +#include "SkEndian.h" +#include "SkSfntUtils.h" + +static uint16_t parse_be16(const uint8_t*& p) { + uint16_t value = (p[0] << 8) | p[1]; + p += 2; + return value; +} + +static uint32_t parse_be32(const uint8_t*& p) { + uint32_t value = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; + p += 4; + return value; +} + +static Sk64 parse_be64(const uint8_t*& p) { + Sk64 value; + value.fHi = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; + value.fLo = (p[4] << 24) | (p[5] << 16) | (p[6] << 8) | p[7]; + p += 8; + return value; +} + +/////////////////////////////////////////////////////////////////////////////// + +bool SkSfntUtils::ReadTable_head(SkFontID fontID, SkSfntTable_head* head) { + static const uint32_t gTag = SkSetFourByteTag('h', 'e', 'a', 'd'); + static const ssize_t gSize = 54; + + uint8_t storage[gSize]; + ssize_t size = SkFontHost::GetTableData(fontID, gTag, 0, gSize, storage); + if (size != gSize) { + return false; + } + + const uint8_t* p = storage; + head->fVersion = parse_be32(p); + head->fRevision = parse_be32(p); + head->fCheckSumAdjustment = parse_be32(p); + head->fMagicNumber = parse_be32(p); + head->fFlags = parse_be16(p); + head->fUnitsPerEm = parse_be16(p); + head->fDateCreated = parse_be64(p); + head->fDateModified = parse_be64(p); + head->fXMin = parse_be16(p); + head->fXMin = parse_be16(p); + head->fXMin = parse_be16(p); + head->fXMin = parse_be16(p); + head->fMacStyle = parse_be16(p); + head->fLowestPPEM = parse_be16(p); + head->fFontDirectionHint = parse_be16(p); + head->fIndexToLocFormat = parse_be16(p); + head->fGlyphDataFormat = parse_be16(p); + SkASSERT(p - storage == size); + return true; +} + +bool SkSfntUtils::ReadTable_maxp(SkFontID fontID, SkSfntTable_maxp* maxp) { + static const uint32_t gTag = SkSetFourByteTag('m', 'a', 'x', 'p'); + static const ssize_t gSize = 32; + + uint8_t storage[gSize]; + ssize_t size = SkFontHost::GetTableData(fontID, gTag, 0, gSize, storage); + if (size != gSize) { + return false; + } + + const uint8_t* p = storage; + maxp->fVersion = parse_be32(p); + maxp->fNumGlyphs = parse_be16(p); + maxp->fMaxPoints = parse_be16(p); + maxp->fMaxContours = parse_be16(p); + maxp->fMaxComponentPoints = parse_be16(p); + maxp->fMaxComponentContours = parse_be16(p); + maxp->fMaxZones = parse_be16(p); + maxp->fMaxTwilightPoints = parse_be16(p); + maxp->fMaxStorage = parse_be16(p); + maxp->fMaxFunctionDefs = parse_be16(p); + maxp->fMaxInstructionDefs = parse_be16(p); + maxp->fMaxStackElements = parse_be16(p); + maxp->fMaxSizeOfInstructions = parse_be16(p); + maxp->fMaxComponentElements = parse_be16(p); + maxp->fMaxComponentDepth = parse_be16(p); + SkASSERT(p - storage == size); + return true; +} + diff --git a/utils/utils_files.mk b/utils/utils_files.mk new file mode 100644 index 00000000..a8c9496a --- /dev/null +++ b/utils/utils_files.mk @@ -0,0 +1,10 @@ +SOURCE := \ + SkCamera.cpp \ + SkColorMatrix.cpp \ + SkCullPoints.cpp \ + SkDumpCanvas.cpp \ + SkInterpolator.cpp \ + SkNinePatch.cpp \ + SkProxyCanvas.cpp \ + SkSfntUtils.cpp \ + SkUnitMappers.cpp |