no bug - Bumping Firefox l10n changesets r=release a=l10n-bump DONTBUILD CLOSED TREE
[gecko.git] / gfx / thebes / gfxGlyphExtents.h
blobfb411124136db4cf039ace7b21e052f6f073c329
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/. */
6 #ifndef GFX_GLYPHEXTENTS_H
7 #define GFX_GLYPHEXTENTS_H
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"
17 class gfxContext;
19 namespace mozilla {
20 namespace gfx {
21 class DrawTarget;
22 } // namespace gfx
23 } // namespace mozilla
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).
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.
38 class gfxGlyphExtents {
39 typedef mozilla::gfx::DrawTarget DrawTarget;
41 public:
42 explicit gfxGlyphExtents(int32_t aAppUnitsPerDevUnit)
43 : mAppUnitsPerDevUnit(aAppUnitsPerDevUnit),
44 mLock("gfxGlyphExtents lock") {
45 MOZ_COUNT_CTOR(gfxGlyphExtents);
47 ~gfxGlyphExtents();
49 enum { INVALID_WIDTH = 0xFFFF };
51 void NotifyGlyphsChanged() {
52 mozilla::AutoWriteLock lock(mLock);
53 mTightGlyphExtents.Clear();
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);
65 bool IsGlyphKnownLocked(uint32_t aGlyphID) const MOZ_REQUIRES_SHARED(mLock) {
66 return mContainedGlyphWidths.Get(aGlyphID) != INVALID_WIDTH ||
67 mTightGlyphExtents.GetEntry(aGlyphID) != nullptr;
70 bool IsGlyphKnownWithTightExtentsLocked(uint32_t aGlyphID) const
71 MOZ_REQUIRES_SHARED(mLock) {
72 return mTightGlyphExtents.GetEntry(aGlyphID) != nullptr;
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);
89 void SetContainedGlyphWidthAppUnits(uint32_t aGlyphID, uint16_t aWidth) {
90 mozilla::AutoWriteLock lock(mLock);
91 mContainedGlyphWidths.Set(aGlyphID, aWidth);
93 void SetTightGlyphExtents(uint32_t aGlyphID, const gfxRect& aExtentsAppUnits);
95 int32_t GetAppUnitsPerDevUnit() { return mAppUnitsPerDevUnit; }
97 size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
98 size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
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) {}
114 float x, y, width, height;
117 enum {
118 BLOCK_SIZE_BITS = 7,
119 BLOCK_SIZE = 1 << BLOCK_SIZE_BITS
120 }; // 128-glyph blocks
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);
135 uint16_t* widths = reinterpret_cast<uint16_t*>(bits);
136 return widths[indexInBlock];
139 uint32_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
141 ~GlyphWidths();
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);
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);
152 static uintptr_t MakeSingle(uint32_t aGlyphOffset, uint16_t aWidth) {
153 return (aWidth << (1 + BLOCK_SIZE_BITS)) + (aGlyphOffset << 1) + 1;
156 nsTArray<uintptr_t> mBlocks;
159 GlyphWidths mContainedGlyphWidths MOZ_GUARDED_BY(mLock);
160 nsTHashtable<HashEntry> mTightGlyphExtents MOZ_GUARDED_BY(mLock);
161 const int32_t mAppUnitsPerDevUnit;
163 public:
164 mutable mozilla::RWLock mLock;
166 private:
167 // not implemented:
168 gfxGlyphExtents(const gfxGlyphExtents& aOther) = delete;
169 gfxGlyphExtents& operator=(const gfxGlyphExtents& aOther) = delete;
172 #endif