Bug 1823215 - Add API to ElementOrArray to support use in gfxTextRun to store the glyph run(s). r=gfx-reviewers,lsalzman

Depends on D172938

Differential Revision: https://phabricator.services.mozilla.com/D172939
This commit is contained in:
Jonathan Kew 2023-03-19 16:36:06 +00:00
Родитель ce6caaeacf
Коммит 3bdedbad5b
1 изменённых файлов: 63 добавлений и 1 удалений

Просмотреть файл

@ -419,7 +419,8 @@ namespace mozilla {
// Container for either a single element of type T, or an nsTArray<T>.
// Provides a minimal subset of nsTArray's API, just enough to support use
// by ContextState for the clipsAndTransforms list.
// by ContextState for the clipsAndTransforms list, and by gfxTextRun for
// its mGlyphRuns.
// Using this instead of a simple nsTArray avoids an extra allocation in the
// common case where no more than one element is ever added to the list.
// Unlike an AutoTArray<..., 1>, this class is memmovable and therefore can
@ -435,6 +436,13 @@ class ElementOrArray {
Array,
} mTag;
// gfxTextRun::SortGlyphRuns and SanitizeGlyphRuns directly access the array.
friend class gfxTextRun;
nsTArray<T>& Array() {
MOZ_DIAGNOSTIC_ASSERT(mTag == Tag::Array);
return mArray;
}
public:
// Construct as an empty array.
ElementOrArray() : mTag(Tag::Array) { new (&mArray) nsTArray<T>(); }
@ -499,6 +507,55 @@ class ElementOrArray {
return mTag == Tag::Element ? false : mArray.IsEmpty();
}
void TruncateLength(uint32_t aLength = 0) {
MOZ_DIAGNOSTIC_ASSERT(aLength <= Length());
switch (mTag) {
case Tag::Element:
if (aLength == 0) {
// Destroy the single element, and convert to an empty array.
mElement.~T();
mTag = Tag::Array;
new (&mArray) nsTArray<T>();
}
break;
case Tag::Array:
mArray.TruncateLength(aLength);
break;
}
}
void Clear() {
switch (mTag) {
case Tag::Element:
mElement.~T();
mTag = Tag::Array;
new (&mArray) nsTArray<T>();
break;
case Tag::Array:
mArray.Clear();
break;
}
}
// Convert from Array to Element storage. Only to be used when the current
// state is a single-element array!
void ConvertToElement() {
MOZ_DIAGNOSTIC_ASSERT(mTag == Tag::Array && mArray.Length() == 1);
T temp = std::move(mArray[0]);
mArray.~nsTArray();
mTag = Tag::Element;
new (&mElement) T(std::move(temp));
}
const T& operator[](uint32_t aIndex) const {
MOZ_DIAGNOSTIC_ASSERT(aIndex < Length());
return mTag == Tag::Element ? mElement : mArray[aIndex];
}
T& operator[](uint32_t aIndex) {
MOZ_DIAGNOSTIC_ASSERT(aIndex < Length());
return mTag == Tag::Element ? mElement : mArray[aIndex];
}
// Simple iterators to support range-for loops.
const T* begin() const {
return mTag == Tag::Array ? mArray.IsEmpty() ? nullptr : &*mArray.begin()
@ -515,6 +572,11 @@ class ElementOrArray {
T* end() {
return mTag == Tag::Array ? begin() + mArray.Length() : &mElement + 1;
}
size_t ShallowSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) {
return mTag == Tag::Array ? mArray.ShallowSizeOfExcludingThis(aMallocSizeOf)
: 0;
}
};
struct StyleAbsoluteColor;