gfxGlyphExtents.cpp (4844B)
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 #include "gfxGlyphExtents.h" 7 #include "gfxTextRun.h" 8 9 using namespace mozilla; 10 11 #ifdef DEBUG_roc 12 # define DEBUG_TEXT_RUN_STORAGE_METRICS 13 #endif 14 15 #ifdef DEBUG_TEXT_RUN_STORAGE_METRICS 16 extern uint32_t gTextRunStorageHighWaterMark; 17 extern uint32_t gTextRunStorage; 18 extern uint32_t gFontCount; 19 extern uint32_t gGlyphExtentsCount; 20 extern uint32_t gGlyphExtentsWidthsTotalSize; 21 extern uint32_t gGlyphExtentsSetupEagerSimple; 22 extern uint32_t gGlyphExtentsSetupEagerTight; 23 extern uint32_t gGlyphExtentsSetupLazyTight; 24 extern uint32_t gGlyphExtentsSetupFallBackToTight; 25 #endif 26 27 gfxGlyphExtents::~gfxGlyphExtents() { 28 #ifdef DEBUG_TEXT_RUN_STORAGE_METRICS 29 gGlyphExtentsWidthsTotalSize += 30 mContainedGlyphWidths.SizeOfExcludingThis(&FontCacheMallocSizeOf); 31 gGlyphExtentsCount++; 32 #endif 33 MOZ_COUNT_DTOR(gfxGlyphExtents); 34 } 35 36 bool gfxGlyphExtents::GetTightGlyphExtentsAppUnitsLocked( 37 gfxFont* aFont, DrawTarget* aDrawTarget, uint32_t aGlyphID, 38 gfxRect* aExtents) { 39 HashEntry* entry = mTightGlyphExtents.GetEntry(aGlyphID); 40 if (!entry) { 41 // Some functions higher up in the call chain deliberately pass in a 42 // nullptr DrawTarget, e.g. GetBaselinePosition() passes nullptr to 43 // gfxTextRun::MeasureText() and that nullptr reaches here. 44 if (!aDrawTarget) { 45 NS_WARNING("Could not get glyph extents (no aDrawTarget)"); 46 return false; 47 } 48 49 #ifdef DEBUG_TEXT_RUN_STORAGE_METRICS 50 ++gGlyphExtentsSetupLazyTight; 51 #endif 52 // We need to temporarily release the read lock, as SetupGlyphExtents will 53 // take a write lock internally when it wants to set the new entry. 54 MOZ_PUSH_IGNORE_THREAD_SAFETY 55 mLock.ReadUnlock(); 56 aFont->SetupGlyphExtents(aDrawTarget, aGlyphID, true, this); 57 mLock.ReadLock(); 58 MOZ_POP_THREAD_SAFETY 59 60 entry = mTightGlyphExtents.GetEntry(aGlyphID); 61 if (!entry) { 62 NS_WARNING("Could not get glyph extents"); 63 return false; 64 } 65 } 66 67 *aExtents = gfxRect(entry->x, entry->y, entry->width, entry->height); 68 return true; 69 } 70 71 gfxGlyphExtents::GlyphWidths::~GlyphWidths() { 72 uint32_t i, count = mBlocks.Length(); 73 for (i = 0; i < count; ++i) { 74 uintptr_t bits = mBlocks[i]; 75 if (bits && !(bits & 0x1)) { 76 delete[] reinterpret_cast<uint16_t*>(bits); 77 } 78 } 79 } 80 81 uint32_t gfxGlyphExtents::GlyphWidths::SizeOfExcludingThis( 82 MallocSizeOf aMallocSizeOf) const { 83 uint32_t i; 84 uint32_t size = mBlocks.ShallowSizeOfExcludingThis(aMallocSizeOf); 85 for (i = 0; i < mBlocks.Length(); ++i) { 86 uintptr_t bits = mBlocks[i]; 87 if (bits && !(bits & 0x1)) { 88 size += aMallocSizeOf(reinterpret_cast<void*>(bits)); 89 } 90 } 91 return size; 92 } 93 94 void gfxGlyphExtents::GlyphWidths::Set(uint32_t aGlyphID, uint16_t aWidth) { 95 uint32_t block = aGlyphID >> BLOCK_SIZE_BITS; 96 uint32_t len = mBlocks.Length(); 97 if (block >= len) { 98 uintptr_t* elems = mBlocks.AppendElements(block + 1 - len); 99 if (!elems) return; 100 memset(elems, 0, sizeof(uintptr_t) * (block + 1 - len)); 101 } 102 103 uintptr_t bits = mBlocks[block]; 104 uint32_t glyphOffset = aGlyphID & (BLOCK_SIZE - 1); 105 if (!bits) { 106 mBlocks[block] = MakeSingle(glyphOffset, aWidth); 107 return; 108 } 109 110 uint16_t* newBlock; 111 if (bits & 0x1) { 112 // Expand the block to a real block. We could avoid this by checking 113 // glyphOffset == GetGlyphOffset(bits), but that never happens so don't 114 // bother 115 newBlock = new uint16_t[BLOCK_SIZE]; 116 if (!newBlock) return; 117 uint32_t i; 118 for (i = 0; i < BLOCK_SIZE; ++i) { 119 newBlock[i] = INVALID_WIDTH; 120 } 121 newBlock[GetGlyphOffset(bits)] = GetWidth(bits); 122 mBlocks[block] = reinterpret_cast<uintptr_t>(newBlock); 123 } else { 124 newBlock = reinterpret_cast<uint16_t*>(bits); 125 } 126 newBlock[glyphOffset] = aWidth; 127 } 128 129 void gfxGlyphExtents::SetTightGlyphExtents(uint32_t aGlyphID, 130 const gfxRect& aExtentsAppUnits) { 131 AutoWriteLock lock(mLock); 132 HashEntry* entry = mTightGlyphExtents.PutEntry(aGlyphID); 133 if (!entry) { 134 return; 135 } 136 entry->x = aExtentsAppUnits.X(); 137 entry->y = aExtentsAppUnits.Y(); 138 entry->width = aExtentsAppUnits.Width(); 139 entry->height = aExtentsAppUnits.Height(); 140 } 141 142 size_t gfxGlyphExtents::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const { 143 AutoReadLock lock(mLock); 144 return mContainedGlyphWidths.SizeOfExcludingThis(aMallocSizeOf) + 145 mTightGlyphExtents.ShallowSizeOfExcludingThis(aMallocSizeOf); 146 } 147 148 size_t gfxGlyphExtents::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const { 149 return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); 150 }