diff options
Diffstat (limited to 'gfx/thebes/gfxGlyphExtents.h')
-rw-r--r-- | gfx/thebes/gfxGlyphExtents.h | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/gfx/thebes/gfxGlyphExtents.h b/gfx/thebes/gfxGlyphExtents.h new file mode 100644 index 0000000000..38e495f95f --- /dev/null +++ b/gfx/thebes/gfxGlyphExtents.h @@ -0,0 +1,153 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef GFX_GLYPHEXTENTS_H +#define GFX_GLYPHEXTENTS_H + +#include "gfxFont.h" +#include "gfxRect.h" +#include "nsTHashtable.h" +#include "nsHashKeys.h" +#include "nsTArray.h" +#include "mozilla/MemoryReporting.h" + +class gfxContext; + +namespace mozilla { +namespace gfx { +class DrawTarget; +} // namespace gfx +} // namespace mozilla + +/** + * This stores glyph bounds information for a particular gfxFont, at + * a particular appunits-per-dev-pixel ratio (because the compressed glyph + * width array is stored in appunits). + * + * We store a hashtable from glyph IDs to float bounding rects. For the + * common case where the glyph has no horizontal left bearing, and no + * y overflow above the font ascent or below the font descent, and tight + * bounding boxes are not required, we avoid storing the glyph ID in the + * hashtable and instead consult an array of 16-bit glyph XMost values (in + * appunits). This array always has an entry for the font's space glyph --- the + * width is assumed to be zero. + */ +class gfxGlyphExtents { + typedef mozilla::gfx::DrawTarget DrawTarget; + + public: + explicit gfxGlyphExtents(int32_t aAppUnitsPerDevUnit) + : mAppUnitsPerDevUnit(aAppUnitsPerDevUnit) { + MOZ_COUNT_CTOR(gfxGlyphExtents); + } + ~gfxGlyphExtents(); + + enum { INVALID_WIDTH = 0xFFFF }; + + void NotifyGlyphsChanged() { mTightGlyphExtents.Clear(); } + + // returns INVALID_WIDTH => not a contained glyph + // Otherwise the glyph has no before-bearing or vertical bearings, + // and the result is its width measured from the baseline origin, in + // appunits. + uint16_t GetContainedGlyphWidthAppUnits(uint32_t aGlyphID) const { + return mContainedGlyphWidths.Get(aGlyphID); + } + + bool IsGlyphKnown(uint32_t aGlyphID) const { + return mContainedGlyphWidths.Get(aGlyphID) != INVALID_WIDTH || + mTightGlyphExtents.GetEntry(aGlyphID) != nullptr; + } + + bool IsGlyphKnownWithTightExtents(uint32_t aGlyphID) const { + return mTightGlyphExtents.GetEntry(aGlyphID) != nullptr; + } + + // Get glyph extents; a rectangle relative to the left baseline origin + // Returns true on success. Can fail on OOM or when aContext is null + // and extents were not (successfully) prefetched. + bool GetTightGlyphExtentsAppUnits(gfxFont* aFont, DrawTarget* aDrawTarget, + uint32_t aGlyphID, gfxRect* aExtents); + + void SetContainedGlyphWidthAppUnits(uint32_t aGlyphID, uint16_t aWidth) { + mContainedGlyphWidths.Set(aGlyphID, aWidth); + } + void SetTightGlyphExtents(uint32_t aGlyphID, const gfxRect& aExtentsAppUnits); + + int32_t GetAppUnitsPerDevUnit() { return mAppUnitsPerDevUnit; } + + size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; + size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; + + private: + class HashEntry : public nsUint32HashKey { + public: + // When constructing a new entry in the hashtable, we'll leave this + // blank. The caller of Put() will fill this in. + explicit HashEntry(KeyTypePointer aPtr) + : nsUint32HashKey(aPtr), x(0.0), y(0.0), width(0.0), height(0.0) {} + HashEntry(HashEntry&& aOther) + : nsUint32HashKey(std::move(aOther)), + x(aOther.x), + y(aOther.y), + width(aOther.width), + height(aOther.height) {} + + float x, y, width, height; + }; + + enum { + BLOCK_SIZE_BITS = 7, + BLOCK_SIZE = 1 << BLOCK_SIZE_BITS + }; // 128-glyph blocks + + class GlyphWidths { + public: + void Set(uint32_t aIndex, uint16_t aValue); + uint16_t Get(uint32_t aIndex) const { + uint32_t block = aIndex >> BLOCK_SIZE_BITS; + if (block >= mBlocks.Length()) return INVALID_WIDTH; + uintptr_t bits = mBlocks[block]; + if (!bits) return INVALID_WIDTH; + uint32_t indexInBlock = aIndex & (BLOCK_SIZE - 1); + if (bits & 0x1) { + if (GetGlyphOffset(bits) != indexInBlock) return INVALID_WIDTH; + return GetWidth(bits); + } + uint16_t* widths = reinterpret_cast<uint16_t*>(bits); + return widths[indexInBlock]; + } + + uint32_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; + + ~GlyphWidths(); + + private: + static uint32_t GetGlyphOffset(uintptr_t aBits) { + NS_ASSERTION(aBits & 0x1, "This is really a pointer..."); + return (aBits >> 1) & ((1 << BLOCK_SIZE_BITS) - 1); + } + static uint32_t GetWidth(uintptr_t aBits) { + NS_ASSERTION(aBits & 0x1, "This is really a pointer..."); + return aBits >> (1 + BLOCK_SIZE_BITS); + } + static uintptr_t MakeSingle(uint32_t aGlyphOffset, uint16_t aWidth) { + return (aWidth << (1 + BLOCK_SIZE_BITS)) + (aGlyphOffset << 1) + 1; + } + + nsTArray<uintptr_t> mBlocks; + }; + + GlyphWidths mContainedGlyphWidths; + nsTHashtable<HashEntry> mTightGlyphExtents; + int32_t mAppUnitsPerDevUnit; + + private: + // not implemented: + gfxGlyphExtents(const gfxGlyphExtents& aOther) = delete; + gfxGlyphExtents& operator=(const gfxGlyphExtents& aOther) = delete; +}; + +#endif |