blob: 09e22fcc5034f116be4a6e1d17e59604683e5f69 [file] [log] [blame]
// Copyright 2021 Google LLC.
#ifndef Types_DEFINED
#define Types_DEFINED
#include <algorithm>
#include <cstddef>
#include "include/core/SkFont.h"
#include "include/core/SkSize.h"
#include "include/core/SkSpan.h"
#include "include/private/SkBitmaskEnum.h"
#include "include/private/SkTo.h"
namespace skia {
namespace text {
enum class TextAlign {
kLeft,
kRight,
kCenter,
kJustify,
kStart,
kEnd,
kNothing,
};
enum class TextDirection {
kRtl,
kLtr,
};
// This enum lists all possible ways to query output positioning
enum class PositionType {
kRandomText,
kGraphemeCluster, // Both the edge of the glyph cluster and the text grapheme
kGlyphCluster,
kGlyph,
kGlyphPart
};
enum class LineBreakType {
kSortLineBreakBefore,
kHardLineBreakBefore,
};
enum class LogicalRunType {
kText,
kLineBreak
};
enum class CodeUnitFlags : uint8_t {
kNoCodeUnitFlag = (1 << 0),
kPartOfWhiteSpace = (1 << 1),
kGraphemeStart = (1 << 2),
kSoftLineBreakBefore = (1 << 3),
kHardLineBreakBefore = (1 << 4),
kAllCodeUnitFlags = ((1 << 5) - 1),
};
enum class GlyphUnitFlags : uint8_t {
kNoGlyphUnitFlag = (1 << 0),
//kPartOfWhiteSpace = (1 << 1),
//kGraphemeStart = (1 << 2),
//kSoftLineBreakBefore = (1 << 3),
//kHardLineBreakBefore = (1 << 4),
kGlyphClusterStart = (1 << 5),
kGraphemeClusterStart = (1 << 6),
};
typedef size_t TextIndex;
typedef size_t GlyphIndex;
typedef size_t RunIndex;
typedef size_t LineIndex;
const size_t EMPTY_INDEX = std::numeric_limits<size_t>::max();
template <typename T>
class Range {
public:
Range() : fStart(0), fEnd(0) { }
Range(T start, T end) : fStart(start) , fEnd(end) { }
bool operator==(Range<T> other) {
return fStart == other.fStart && fEnd == other.fEnd;
}
void clean() {
fStart = 0;
fEnd = 0;
}
bool isEmpty() const {
return fEnd == fStart;
}
bool contains(T index) const {
return index >= fStart && index < fEnd;
}
bool contains(Range<T> range) const {
return range.fStart >= fStart && range.fEnd < fEnd;
}
// For RTL ranges start >= end
int width() const {
return SkToInt(fEnd - fStart);
}
void merge(Range tail) {
SkASSERT(this->fEnd == tail.fStart || this->fStart == tail.fEnd);
this->fStart = std::min(this->fStart, tail.fStart);
this->fEnd = std::max(this->fEnd, tail.fEnd);
}
void intersect(Range other) {
this->fStart = std::max(this->fStart, other.fStart);
this->fEnd = std::min(this->fEnd, other.fEnd);
if (this->fStart > this->fEnd) {
// There is nothing in the intersection; make it empty
this->fEnd = this->fStart;
}
}
template<typename Visitor>
void iterate(Visitor visitor) {
if (this->leftToRight()) {
for (auto index = this->fStart; index < this->fEnd; ++index) {
visitor(index);
}
} else {
for (auto index = this->fStart; index < this->fEnd; --index) {
visitor(index);
}
}
}
T fStart;
T fEnd;
};
typedef Range<TextIndex> TextRange;
typedef Range<GlyphIndex> GlyphRange;
struct DirTextRange : public TextRange {
DirTextRange(TextRange textRange, bool leftToRight)
: TextRange(textRange)
, fLeftToRight(leftToRight) { }
DirTextRange(TextIndex start, TextIndex end, bool leftToRight)
: TextRange(start, end)
, fLeftToRight(leftToRight) { }
bool before(TextIndex index) const {
return fLeftToRight ? index >= fEnd : index < fStart;
}
bool after(TextIndex index) const {
return fLeftToRight ? index < fEnd : index >= fStart;
}
bool left() const {
return fLeftToRight ? fStart : fEnd;
}
bool right() const {
return fLeftToRight ? fEnd : fStart;
}
TextRange normalized() const {
return fLeftToRight ? TextRange(fStart, fEnd) : TextRange(fEnd, fStart);
}
bool fLeftToRight;
};
const Range<size_t> EMPTY_RANGE = Range<size_t>(EMPTY_INDEX, EMPTY_INDEX);
// Blocks
enum BlockType {
kFontChain,
kPlaceholder,
};
struct Placeholder {
SkSize dimensions;
float yOffsetFromBaseline;
};
class FontChain : public SkRefCnt {
public:
// Returns the number of faces in the chain. Always >= 1
virtual size_t count() const = 0;
virtual sk_sp<SkTypeface> operator[](size_t index) const = 0;
virtual float fontSize() const = 0;
virtual SkString locale() const = 0;
};
struct FontBlock {
FontBlock(uint32_t count, sk_sp<FontChain> fontChain)
: type(BlockType::kFontChain)
, charCount(count)
, chain(fontChain) { }
FontBlock() : FontBlock(0, nullptr) { }
FontBlock(FontBlock& block) {
this->type = block.type;
this->charCount = block.charCount;
this->chain = block.chain;
}
~FontBlock() { }
BlockType type;
uint32_t charCount;
union {
sk_sp<FontChain> chain;
Placeholder placeholder;
};
};
struct ResolvedFontBlock {
ResolvedFontBlock(TextRange textRange, sk_sp<SkTypeface> typeface, SkScalar size, SkFontStyle fontStyle)
: textRange(textRange)
, typeface(typeface)
, size(size)
, style(fontStyle) { }
TextRange textRange;
sk_sp<SkTypeface> typeface;
float size;
SkFontStyle style;
};
} // namespace text
} // namespace skia
namespace sknonstd {
template <> struct is_bitmask_enum<skia::text::CodeUnitFlags> : std::true_type {};
template <> struct is_bitmask_enum<skia::text::GlyphUnitFlags> : std::true_type {};
}
#endif