Line data Source code
1 : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 0 : gfxGlyphExtents::~gfxGlyphExtents()
28 : {
29 : #ifdef DEBUG_TEXT_RUN_STORAGE_METRICS
30 : gGlyphExtentsWidthsTotalSize +=
31 : mContainedGlyphWidths.SizeOfExcludingThis(&FontCacheMallocSizeOf);
32 : gGlyphExtentsCount++;
33 : #endif
34 0 : MOZ_COUNT_DTOR(gfxGlyphExtents);
35 0 : }
36 :
37 : bool
38 13 : gfxGlyphExtents::GetTightGlyphExtentsAppUnits(gfxFont* aFont,
39 : DrawTarget* aDrawTarget, uint32_t aGlyphID, gfxRect* aExtents)
40 : {
41 13 : HashEntry *entry = mTightGlyphExtents.GetEntry(aGlyphID);
42 13 : if (!entry) {
43 : // Some functions higher up in the call chain deliberately pass in a
44 : // nullptr DrawTarget, e.g. GetBaselinePosition() passes nullptr to
45 : // gfxTextRun::MeasureText() and that nullptr reaches here.
46 2 : if (!aDrawTarget) {
47 0 : NS_WARNING("Could not get glyph extents (no aDrawTarget)");
48 0 : return false;
49 : }
50 :
51 2 : if (aFont->SetupCairoFont(aDrawTarget)) {
52 : #ifdef DEBUG_TEXT_RUN_STORAGE_METRICS
53 : ++gGlyphExtentsSetupLazyTight;
54 : #endif
55 2 : aFont->SetupGlyphExtents(aDrawTarget, aGlyphID, true, this);
56 2 : entry = mTightGlyphExtents.GetEntry(aGlyphID);
57 : }
58 2 : if (!entry) {
59 0 : NS_WARNING("Could not get glyph extents");
60 0 : return false;
61 : }
62 : }
63 :
64 13 : *aExtents = gfxRect(entry->x, entry->y, entry->width, entry->height);
65 13 : return true;
66 : }
67 :
68 0 : gfxGlyphExtents::GlyphWidths::~GlyphWidths()
69 : {
70 0 : uint32_t i, count = mBlocks.Length();
71 0 : for (i = 0; i < count; ++i) {
72 0 : uintptr_t bits = mBlocks[i];
73 0 : if (bits && !(bits & 0x1)) {
74 0 : delete[] reinterpret_cast<uint16_t *>(bits);
75 : }
76 : }
77 0 : }
78 :
79 : uint32_t
80 0 : gfxGlyphExtents::GlyphWidths::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
81 : {
82 : uint32_t i;
83 0 : uint32_t size = mBlocks.ShallowSizeOfExcludingThis(aMallocSizeOf);
84 0 : for (i = 0; i < mBlocks.Length(); ++i) {
85 0 : uintptr_t bits = mBlocks[i];
86 0 : if (bits && !(bits & 0x1)) {
87 0 : size += aMallocSizeOf(reinterpret_cast<void*>(bits));
88 : }
89 : }
90 0 : return size;
91 : }
92 :
93 : void
94 51 : gfxGlyphExtents::GlyphWidths::Set(uint32_t aGlyphID, uint16_t aWidth)
95 : {
96 51 : uint32_t block = aGlyphID >> BLOCK_SIZE_BITS;
97 51 : uint32_t len = mBlocks.Length();
98 51 : if (block >= len) {
99 2 : uintptr_t *elems = mBlocks.AppendElements(block + 1 - len);
100 2 : if (!elems)
101 0 : return;
102 2 : memset(elems, 0, sizeof(uintptr_t)*(block + 1 - len));
103 : }
104 :
105 51 : uintptr_t bits = mBlocks[block];
106 51 : uint32_t glyphOffset = aGlyphID & (BLOCK_SIZE - 1);
107 51 : if (!bits) {
108 2 : mBlocks[block] = MakeSingle(glyphOffset, aWidth);
109 2 : return;
110 : }
111 :
112 : uint16_t *newBlock;
113 49 : if (bits & 0x1) {
114 : // Expand the block to a real block. We could avoid this by checking
115 : // glyphOffset == GetGlyphOffset(bits), but that never happens so don't bother
116 2 : newBlock = new uint16_t[BLOCK_SIZE];
117 2 : if (!newBlock)
118 0 : return;
119 : uint32_t i;
120 258 : for (i = 0; i < BLOCK_SIZE; ++i) {
121 256 : newBlock[i] = INVALID_WIDTH;
122 : }
123 2 : newBlock[GetGlyphOffset(bits)] = GetWidth(bits);
124 2 : mBlocks[block] = reinterpret_cast<uintptr_t>(newBlock);
125 : } else {
126 47 : newBlock = reinterpret_cast<uint16_t *>(bits);
127 : }
128 49 : newBlock[glyphOffset] = aWidth;
129 : }
130 :
131 : void
132 5 : gfxGlyphExtents::SetTightGlyphExtents(uint32_t aGlyphID, const gfxRect& aExtentsAppUnits)
133 : {
134 5 : HashEntry *entry = mTightGlyphExtents.PutEntry(aGlyphID);
135 5 : if (!entry)
136 0 : return;
137 5 : entry->x = aExtentsAppUnits.X();
138 5 : entry->y = aExtentsAppUnits.Y();
139 5 : entry->width = aExtentsAppUnits.Width();
140 5 : entry->height = aExtentsAppUnits.Height();
141 : }
142 :
143 : size_t
144 0 : gfxGlyphExtents::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
145 : {
146 0 : return mContainedGlyphWidths.SizeOfExcludingThis(aMallocSizeOf) +
147 0 : mTightGlyphExtents.ShallowSizeOfExcludingThis(aMallocSizeOf);
148 : }
149 :
150 : size_t
151 0 : gfxGlyphExtents::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
152 : {
153 0 : return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
154 : }
|