diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /gfx/thebes/gfxGlyphExtents.h | |
parent | Initial commit. (diff) | |
download | firefox-esr-upstream.tar.xz firefox-esr-upstream.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'gfx/thebes/gfxGlyphExtents.h')
-rw-r--r-- | gfx/thebes/gfxGlyphExtents.h | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/gfx/thebes/gfxGlyphExtents.h b/gfx/thebes/gfxGlyphExtents.h new file mode 100644 index 0000000000..fb41112413 --- /dev/null +++ b/gfx/thebes/gfxGlyphExtents.h @@ -0,0 +1,172 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef GFX_GLYPHEXTENTS_H +#define GFX_GLYPHEXTENTS_H + +#include "gfxFont.h" +#include "gfxRect.h" +#include "nsTHashtable.h" +#include "nsHashKeys.h" +#include "nsTArray.h" +#include "mozilla/MemoryReporting.h" +#include "mozilla/RWLock.h" + +class gfxContext; + +namespace mozilla { +namespace gfx { +class DrawTarget; +} // namespace gfx +} // namespace mozilla + +/** + * This stores glyph bounds information for a particular gfxFont, at + * a particular appunits-per-dev-pixel ratio (because the compressed glyph + * width array is stored in appunits). + * + * We store a hashtable from glyph IDs to float bounding rects. For the + * common case where the glyph has no horizontal left bearing, and no + * y overflow above the font ascent or below the font descent, and tight + * bounding boxes are not required, we avoid storing the glyph ID in the + * hashtable and instead consult an array of 16-bit glyph XMost values (in + * appunits). This array always has an entry for the font's space glyph --- the + * width is assumed to be zero. + */ +class gfxGlyphExtents { + typedef mozilla::gfx::DrawTarget DrawTarget; + + public: + explicit gfxGlyphExtents(int32_t aAppUnitsPerDevUnit) + : mAppUnitsPerDevUnit(aAppUnitsPerDevUnit), + mLock("gfxGlyphExtents lock") { + MOZ_COUNT_CTOR(gfxGlyphExtents); + } + ~gfxGlyphExtents(); + + enum { INVALID_WIDTH = 0xFFFF }; + + void NotifyGlyphsChanged() { + mozilla::AutoWriteLock lock(mLock); + mTightGlyphExtents.Clear(); + } + + // returns INVALID_WIDTH => not a contained glyph + // Otherwise the glyph has no before-bearing or vertical bearings, + // and the result is its width measured from the baseline origin, in + // appunits. + uint16_t GetContainedGlyphWidthAppUnitsLocked(uint32_t aGlyphID) const + MOZ_REQUIRES_SHARED(mLock) { + return mContainedGlyphWidths.Get(aGlyphID); + } + + bool IsGlyphKnownLocked(uint32_t aGlyphID) const MOZ_REQUIRES_SHARED(mLock) { + return mContainedGlyphWidths.Get(aGlyphID) != INVALID_WIDTH || + mTightGlyphExtents.GetEntry(aGlyphID) != nullptr; + } + + bool IsGlyphKnownWithTightExtentsLocked(uint32_t aGlyphID) const + MOZ_REQUIRES_SHARED(mLock) { + return mTightGlyphExtents.GetEntry(aGlyphID) != nullptr; + } + + // Get glyph extents; a rectangle relative to the left baseline origin + // Returns true on success. Can fail on OOM or when aContext is null + // and extents were not (successfully) prefetched. + bool GetTightGlyphExtentsAppUnitsLocked(gfxFont* aFont, + DrawTarget* aDrawTarget, + uint32_t aGlyphID, gfxRect* aExtents) + MOZ_REQUIRES_SHARED(mLock); + bool GetTightGlyphExtentsAppUnits(gfxFont* aFont, DrawTarget* aDrawTarget, + uint32_t aGlyphID, gfxRect* aExtents) { + mozilla::AutoReadLock lock(mLock); + return GetTightGlyphExtentsAppUnitsLocked(aFont, aDrawTarget, aGlyphID, + aExtents); + } + + void SetContainedGlyphWidthAppUnits(uint32_t aGlyphID, uint16_t aWidth) { + mozilla::AutoWriteLock lock(mLock); + mContainedGlyphWidths.Set(aGlyphID, aWidth); + } + void SetTightGlyphExtents(uint32_t aGlyphID, const gfxRect& aExtentsAppUnits); + + int32_t GetAppUnitsPerDevUnit() { return mAppUnitsPerDevUnit; } + + size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; + size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; + + private: + class HashEntry : public nsUint32HashKey { + public: + // When constructing a new entry in the hashtable, we'll leave this + // blank. The caller of Put() will fill this in. + explicit HashEntry(KeyTypePointer aPtr) + : nsUint32HashKey(aPtr), x(0.0), y(0.0), width(0.0), height(0.0) {} + HashEntry(HashEntry&& aOther) + : nsUint32HashKey(std::move(aOther)), + x(aOther.x), + y(aOther.y), + width(aOther.width), + height(aOther.height) {} + + float x, y, width, height; + }; + + enum { + BLOCK_SIZE_BITS = 7, + BLOCK_SIZE = 1 << BLOCK_SIZE_BITS + }; // 128-glyph blocks + + class GlyphWidths { + public: + void Set(uint32_t aIndex, uint16_t aValue); + uint16_t Get(uint32_t aIndex) const { + uint32_t block = aIndex >> BLOCK_SIZE_BITS; + if (block >= mBlocks.Length()) return INVALID_WIDTH; + uintptr_t bits = mBlocks[block]; + if (!bits) return INVALID_WIDTH; + uint32_t indexInBlock = aIndex & (BLOCK_SIZE - 1); + if (bits & 0x1) { + if (GetGlyphOffset(bits) != indexInBlock) return INVALID_WIDTH; + return GetWidth(bits); + } + uint16_t* widths = reinterpret_cast<uint16_t*>(bits); + return widths[indexInBlock]; + } + + uint32_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; + + ~GlyphWidths(); + + private: + static uint32_t GetGlyphOffset(uintptr_t aBits) { + NS_ASSERTION(aBits & 0x1, "This is really a pointer..."); + return (aBits >> 1) & ((1 << BLOCK_SIZE_BITS) - 1); + } + static uint32_t GetWidth(uintptr_t aBits) { + NS_ASSERTION(aBits & 0x1, "This is really a pointer..."); + return aBits >> (1 + BLOCK_SIZE_BITS); + } + static uintptr_t MakeSingle(uint32_t aGlyphOffset, uint16_t aWidth) { + return (aWidth << (1 + BLOCK_SIZE_BITS)) + (aGlyphOffset << 1) + 1; + } + + nsTArray<uintptr_t> mBlocks; + }; + + GlyphWidths mContainedGlyphWidths MOZ_GUARDED_BY(mLock); + nsTHashtable<HashEntry> mTightGlyphExtents MOZ_GUARDED_BY(mLock); + const int32_t mAppUnitsPerDevUnit; + + public: + mutable mozilla::RWLock mLock; + + private: + // not implemented: + gfxGlyphExtents(const gfxGlyphExtents& aOther) = delete; + gfxGlyphExtents& operator=(const gfxGlyphExtents& aOther) = delete; +}; + +#endif |