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