2014-09-16 09:58:12 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
|
|
* 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
|
|
|
|
|
2014-09-30 06:38:26 +00:00
|
|
|
#include "gfxFont.h"
|
2014-09-16 09:58:12 +00:00
|
|
|
#include "nsTHashtable.h"
|
|
|
|
#include "nsHashKeys.h"
|
|
|
|
#include "nsTArray.h"
|
|
|
|
#include "mozilla/MemoryReporting.h"
|
|
|
|
|
|
|
|
class gfxContext;
|
|
|
|
struct gfxRect;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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 {
|
|
|
|
public:
|
|
|
|
explicit gfxGlyphExtents(int32_t aAppUnitsPerDevUnit) :
|
|
|
|
mAppUnitsPerDevUnit(aAppUnitsPerDevUnit) {
|
|
|
|
MOZ_COUNT_CTOR(gfxGlyphExtents);
|
|
|
|
}
|
|
|
|
~gfxGlyphExtents();
|
|
|
|
|
|
|
|
enum { INVALID_WIDTH = 0xFFFF };
|
|
|
|
|
|
|
|
void NotifyGlyphsChanged() {
|
|
|
|
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 GetContainedGlyphWidthAppUnits(uint32_t aGlyphID) const {
|
|
|
|
return mContainedGlyphWidths.Get(aGlyphID);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsGlyphKnown(uint32_t aGlyphID) const {
|
|
|
|
return mContainedGlyphWidths.Get(aGlyphID) != INVALID_WIDTH ||
|
|
|
|
mTightGlyphExtents.GetEntry(aGlyphID) != nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsGlyphKnownWithTightExtents(uint32_t aGlyphID) const {
|
|
|
|
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.
|
2015-12-15 21:56:41 +00:00
|
|
|
bool GetTightGlyphExtentsAppUnits(gfxFont* aFont,
|
|
|
|
DrawTarget* aDrawTarget, uint32_t aGlyphID, gfxRect* aExtents);
|
2014-09-16 09:58:12 +00:00
|
|
|
|
|
|
|
void SetContainedGlyphWidthAppUnits(uint32_t aGlyphID, uint16_t aWidth) {
|
|
|
|
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) {}
|
|
|
|
HashEntry(const HashEntry& toCopy) : nsUint32HashKey(toCopy) {
|
|
|
|
x = toCopy.x; y = toCopy.y; width = toCopy.width; height = toCopy.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;
|
|
|
|
nsTHashtable<HashEntry> mTightGlyphExtents;
|
|
|
|
int32_t mAppUnitsPerDevUnit;
|
|
|
|
|
|
|
|
private:
|
|
|
|
// not implemented:
|
2015-01-06 23:35:02 +00:00
|
|
|
gfxGlyphExtents(const gfxGlyphExtents& aOther) = delete;
|
|
|
|
gfxGlyphExtents& operator=(const gfxGlyphExtents& aOther) = delete;
|
2014-09-16 09:58:12 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|