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 : #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 2 : explicit gfxGlyphExtents(int32_t aAppUnitsPerDevUnit) :
42 2 : mAppUnitsPerDevUnit(aAppUnitsPerDevUnit) {
43 2 : MOZ_COUNT_CTOR(gfxGlyphExtents);
44 2 : }
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 429 : uint16_t GetContainedGlyphWidthAppUnits(uint32_t aGlyphID) const {
58 429 : return mContainedGlyphWidths.Get(aGlyphID);
59 : }
60 :
61 202 : bool IsGlyphKnown(uint32_t aGlyphID) const {
62 262 : return mContainedGlyphWidths.Get(aGlyphID) != INVALID_WIDTH ||
63 262 : mTightGlyphExtents.GetEntry(aGlyphID) != nullptr;
64 : }
65 :
66 0 : bool IsGlyphKnownWithTightExtents(uint32_t aGlyphID) const {
67 0 : return mTightGlyphExtents.GetEntry(aGlyphID) != nullptr;
68 : }
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 51 : void SetContainedGlyphWidthAppUnits(uint32_t aGlyphID, uint16_t aWidth) {
77 51 : mContainedGlyphWidths.Set(aGlyphID, aWidth);
78 51 : }
79 : void SetTightGlyphExtents(uint32_t aGlyphID, const gfxRect& aExtentsAppUnits);
80 :
81 87 : 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 0 : 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 5 : explicit HashEntry(KeyTypePointer aPtr) : nsUint32HashKey(aPtr) {}
92 : HashEntry(const HashEntry& toCopy) : nsUint32HashKey(toCopy) {
93 : x = toCopy.x; y = toCopy.y; width = toCopy.width; height = toCopy.height;
94 : }
95 :
96 : float x, y, width, height;
97 : };
98 :
99 : enum { BLOCK_SIZE_BITS = 7, BLOCK_SIZE = 1 << BLOCK_SIZE_BITS }; // 128-glyph blocks
100 :
101 2 : class GlyphWidths {
102 : public:
103 : void Set(uint32_t aIndex, uint16_t aValue);
104 631 : uint16_t Get(uint32_t aIndex) const {
105 631 : uint32_t block = aIndex >> BLOCK_SIZE_BITS;
106 631 : if (block >= mBlocks.Length())
107 0 : return INVALID_WIDTH;
108 631 : uintptr_t bits = mBlocks[block];
109 631 : if (!bits)
110 0 : return INVALID_WIDTH;
111 631 : uint32_t indexInBlock = aIndex & (BLOCK_SIZE - 1);
112 631 : if (bits & 0x1) {
113 2 : if (GetGlyphOffset(bits) != indexInBlock)
114 2 : return INVALID_WIDTH;
115 0 : return GetWidth(bits);
116 : }
117 629 : uint16_t *widths = reinterpret_cast<uint16_t *>(bits);
118 629 : return widths[indexInBlock];
119 : }
120 :
121 : uint32_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
122 :
123 : ~GlyphWidths();
124 :
125 : private:
126 4 : static uint32_t GetGlyphOffset(uintptr_t aBits) {
127 4 : NS_ASSERTION(aBits & 0x1, "This is really a pointer...");
128 4 : return (aBits >> 1) & ((1 << BLOCK_SIZE_BITS) - 1);
129 : }
130 2 : static uint32_t GetWidth(uintptr_t aBits) {
131 2 : NS_ASSERTION(aBits & 0x1, "This is really a pointer...");
132 2 : return aBits >> (1 + BLOCK_SIZE_BITS);
133 : }
134 2 : static uintptr_t MakeSingle(uint32_t aGlyphOffset, uint16_t aWidth) {
135 2 : return (aWidth << (1 + BLOCK_SIZE_BITS)) + (aGlyphOffset << 1) + 1;
136 : }
137 :
138 : nsTArray<uintptr_t> mBlocks;
139 : };
140 :
141 : GlyphWidths mContainedGlyphWidths;
142 : nsTHashtable<HashEntry> mTightGlyphExtents;
143 : int32_t mAppUnitsPerDevUnit;
144 :
145 : private:
146 : // not implemented:
147 : gfxGlyphExtents(const gfxGlyphExtents& aOther) = delete;
148 : gfxGlyphExtents& operator=(const gfxGlyphExtents& aOther) = delete;
149 : };
150 :
151 : #endif
|