gfxGlyphExtents.h (5995B)
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #ifndef GFX_GLYPHEXTENTS_H 7 #define GFX_GLYPHEXTENTS_H 8 9 #include "gfxFont.h" 10 #include "gfxRect.h" 11 #include "nsTHashtable.h" 12 #include "nsHashKeys.h" 13 #include "nsTArray.h" 14 #include "mozilla/MemoryReporting.h" 15 #include "mozilla/RWLock.h" 16 17 class gfxContext; 18 19 namespace mozilla { 20 namespace gfx { 21 class DrawTarget; 22 } // namespace gfx 23 } // namespace mozilla 24 25 /** 26 * This stores glyph bounds information for a particular gfxFont, at 27 * a particular appunits-per-dev-pixel ratio (because the compressed glyph 28 * width array is stored in appunits). 29 * 30 * We store a hashtable from glyph IDs to float bounding rects. For the 31 * common case where the glyph has no horizontal left bearing, and no 32 * y overflow above the font ascent or below the font descent, and tight 33 * bounding boxes are not required, we avoid storing the glyph ID in the 34 * hashtable and instead consult an array of 16-bit glyph XMost values (in 35 * appunits). This array always has an entry for the font's space glyph --- the 36 * width is assumed to be zero. 37 */ 38 class gfxGlyphExtents { 39 typedef mozilla::gfx::DrawTarget DrawTarget; 40 41 public: 42 explicit gfxGlyphExtents(int32_t aAppUnitsPerDevUnit) 43 : mAppUnitsPerDevUnit(aAppUnitsPerDevUnit), 44 mLock("gfxGlyphExtents lock") { 45 MOZ_COUNT_CTOR(gfxGlyphExtents); 46 } 47 ~gfxGlyphExtents(); 48 49 enum { INVALID_WIDTH = 0xFFFF }; 50 51 void NotifyGlyphsChanged() { 52 mozilla::AutoWriteLock lock(mLock); 53 mTightGlyphExtents.Clear(); 54 } 55 56 // returns INVALID_WIDTH => not a contained glyph 57 // Otherwise the glyph has no before-bearing or vertical bearings, 58 // and the result is its width measured from the baseline origin, in 59 // appunits. 60 uint16_t GetContainedGlyphWidthAppUnitsLocked(uint32_t aGlyphID) const 61 MOZ_REQUIRES_SHARED(mLock) { 62 return mContainedGlyphWidths.Get(aGlyphID); 63 } 64 65 bool IsGlyphKnownLocked(uint32_t aGlyphID) const MOZ_REQUIRES_SHARED(mLock) { 66 return mContainedGlyphWidths.Get(aGlyphID) != INVALID_WIDTH || 67 mTightGlyphExtents.GetEntry(aGlyphID) != nullptr; 68 } 69 70 bool IsGlyphKnownWithTightExtentsLocked(uint32_t aGlyphID) const 71 MOZ_REQUIRES_SHARED(mLock) { 72 return mTightGlyphExtents.GetEntry(aGlyphID) != nullptr; 73 } 74 75 // Get glyph extents; a rectangle relative to the left baseline origin 76 // Returns true on success. Can fail on OOM or when aContext is null 77 // and extents were not (successfully) prefetched. 78 bool GetTightGlyphExtentsAppUnitsLocked(gfxFont* aFont, 79 DrawTarget* aDrawTarget, 80 uint32_t aGlyphID, gfxRect* aExtents) 81 MOZ_REQUIRES_SHARED(mLock); 82 bool GetTightGlyphExtentsAppUnits(gfxFont* aFont, DrawTarget* aDrawTarget, 83 uint32_t aGlyphID, gfxRect* aExtents) { 84 mozilla::AutoReadLock lock(mLock); 85 return GetTightGlyphExtentsAppUnitsLocked(aFont, aDrawTarget, aGlyphID, 86 aExtents); 87 } 88 89 void SetContainedGlyphWidthAppUnits(uint32_t aGlyphID, uint16_t aWidth) { 90 mozilla::AutoWriteLock lock(mLock); 91 mContainedGlyphWidths.Set(aGlyphID, aWidth); 92 } 93 void SetTightGlyphExtents(uint32_t aGlyphID, const gfxRect& aExtentsAppUnits); 94 95 int32_t GetAppUnitsPerDevUnit() { return mAppUnitsPerDevUnit; } 96 97 size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; 98 size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; 99 100 private: 101 class HashEntry : public nsUint32HashKey { 102 public: 103 // When constructing a new entry in the hashtable, we'll leave this 104 // blank. The caller of Put() will fill this in. 105 explicit HashEntry(KeyTypePointer aPtr) 106 : nsUint32HashKey(aPtr), x(0.0), y(0.0), width(0.0), height(0.0) {} 107 HashEntry(HashEntry&& aOther) 108 : nsUint32HashKey(std::move(aOther)), 109 x(aOther.x), 110 y(aOther.y), 111 width(aOther.width), 112 height(aOther.height) {} 113 114 float x, y, width, height; 115 }; 116 117 enum { 118 BLOCK_SIZE_BITS = 7, 119 BLOCK_SIZE = 1 << BLOCK_SIZE_BITS 120 }; // 128-glyph blocks 121 122 class GlyphWidths { 123 public: 124 void Set(uint32_t aIndex, uint16_t aValue); 125 uint16_t Get(uint32_t aIndex) const { 126 uint32_t block = aIndex >> BLOCK_SIZE_BITS; 127 if (block >= mBlocks.Length()) return INVALID_WIDTH; 128 uintptr_t bits = mBlocks[block]; 129 if (!bits) return INVALID_WIDTH; 130 uint32_t indexInBlock = aIndex & (BLOCK_SIZE - 1); 131 if (bits & 0x1) { 132 if (GetGlyphOffset(bits) != indexInBlock) return INVALID_WIDTH; 133 return GetWidth(bits); 134 } 135 uint16_t* widths = reinterpret_cast<uint16_t*>(bits); 136 return widths[indexInBlock]; 137 } 138 139 uint32_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; 140 141 ~GlyphWidths(); 142 143 private: 144 static uint32_t GetGlyphOffset(uintptr_t aBits) { 145 NS_ASSERTION(aBits & 0x1, "This is really a pointer..."); 146 return (aBits >> 1) & ((1 << BLOCK_SIZE_BITS) - 1); 147 } 148 static uint32_t GetWidth(uintptr_t aBits) { 149 NS_ASSERTION(aBits & 0x1, "This is really a pointer..."); 150 return aBits >> (1 + BLOCK_SIZE_BITS); 151 } 152 static uintptr_t MakeSingle(uint32_t aGlyphOffset, uint16_t aWidth) { 153 return (aWidth << (1 + BLOCK_SIZE_BITS)) + (aGlyphOffset << 1) + 1; 154 } 155 156 nsTArray<uintptr_t> mBlocks; 157 }; 158 159 GlyphWidths mContainedGlyphWidths MOZ_GUARDED_BY(mLock); 160 nsTHashtable<HashEntry> mTightGlyphExtents MOZ_GUARDED_BY(mLock); 161 const int32_t mAppUnitsPerDevUnit; 162 163 public: 164 mutable mozilla::RWLock mLock; 165 166 private: 167 // not implemented: 168 gfxGlyphExtents(const gfxGlyphExtents& aOther) = delete; 169 gfxGlyphExtents& operator=(const gfxGlyphExtents& aOther) = delete; 170 }; 171 172 #endif