You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
200 lines
6.3 KiB
200 lines
6.3 KiB
// Copyright 2021 Google LLC.
|
|
#ifndef Processor_DEFINED
|
|
#define Processor_DEFINED
|
|
|
|
#include <string>
|
|
#include "experimental/sktext/include/Types.h"
|
|
#include "experimental/sktext/src/Line.h"
|
|
#include "experimental/sktext/src/TextRun.h"
|
|
#include "include/core/SkCanvas.h"
|
|
#include "include/core/SkFontMgr.h"
|
|
#include "include/core/SkFontStyle.h"
|
|
#include "include/core/SkPaint.h"
|
|
#include "include/core/SkSize.h"
|
|
#include "include/core/SkString.h"
|
|
#include "include/core/SkTextBlob.h"
|
|
#include "modules/skshaper/src/SkUnicode.h"
|
|
|
|
namespace skia {
|
|
namespace text {
|
|
|
|
class Block {
|
|
public:
|
|
enum BlockType {
|
|
kFont,
|
|
kDecor,
|
|
kFormat,
|
|
};
|
|
Block(BlockType type, TextRange range)
|
|
: fType(type)
|
|
, fRange(range) { }
|
|
BlockType fType;
|
|
TextRange fRange;
|
|
};
|
|
|
|
class FontBlock : public Block {
|
|
public:
|
|
FontBlock(const SkString& family, SkScalar size, SkFontStyle style, TextRange range)
|
|
: Block(Block::kFont, range)
|
|
, fFontFamily(family)
|
|
, fFontSize(size)
|
|
, fFontStyle(style) { }
|
|
SkString fFontFamily;
|
|
SkScalar fFontSize;
|
|
SkFontStyle fFontStyle;
|
|
|
|
// TODO: Features
|
|
};
|
|
|
|
class DecorBlock : public Block {
|
|
public:
|
|
DecorBlock(const SkPaint* foreground, const SkPaint* background, TextRange range)
|
|
: Block(Block::kDecor, range)
|
|
, fForegroundColor(foreground)
|
|
, fBackgroundColor(background) { }
|
|
|
|
DecorBlock(TextRange range)
|
|
: DecorBlock(nullptr, nullptr, range) { }
|
|
|
|
const SkPaint* fForegroundColor;
|
|
const SkPaint* fBackgroundColor;
|
|
// Everything else
|
|
};
|
|
|
|
class TextFormatStyle {
|
|
public:
|
|
TextFormatStyle(TextAlign textAlign, TextDirection defaultTextDirection)
|
|
: fTextAlign(textAlign), fDefaultTextDirection(defaultTextDirection) { }
|
|
TextAlign fTextAlign;
|
|
TextDirection fDefaultTextDirection;
|
|
};
|
|
|
|
class TextFontStyle {
|
|
public:
|
|
TextFontStyle(TextDirection textDirection, sk_sp<SkFontMgr> fontManager)
|
|
: fTextDirection(textDirection), fFontManager(fontManager) { }
|
|
TextDirection fTextDirection;
|
|
sk_sp<SkFontMgr> fFontManager;
|
|
};
|
|
|
|
class TextOutput {
|
|
public:
|
|
TextOutput(sk_sp<SkTextBlob> textBlob, const SkPaint& paint, SkSize offset) : fTextBlob(std::move(textBlob)), fPaint(paint), fOffset(offset) { }
|
|
sk_sp<SkTextBlob> fTextBlob;
|
|
SkPaint fPaint;
|
|
SkSize fOffset;
|
|
};
|
|
|
|
class Processor {
|
|
|
|
public:
|
|
|
|
Processor(const SkString& text)
|
|
: fText(text)
|
|
, fUnicode(nullptr) {}
|
|
|
|
~Processor() = default;
|
|
|
|
// All the Unicode information
|
|
SkUnicode* getUnicode() { return fUnicode == nullptr ? nullptr : fUnicode.get(); }
|
|
|
|
// Once the text is measured you can get approximate sizing for it
|
|
bool shape(TextFontStyle fontStyle, SkTArray<FontBlock, true> fontBlocks);
|
|
|
|
// Once the text is fit into the required box you can get the real sizes for it
|
|
bool wrap(SkScalar width, SkScalar height);
|
|
|
|
// Once the text is formatted you can get it's glyphs info line by line
|
|
bool format(TextFormatStyle textFormatStyle);
|
|
|
|
// Once the text is decorated you can iterate it by segments (intersect of run, decor block and line)
|
|
bool decorate(SkTArray<DecorBlock, true> decorBlocks);
|
|
|
|
bool hasProperty(size_t index, CodeUnitFlags flag) {
|
|
return (fCodeUnitProperties[index] & flag) == flag;
|
|
}
|
|
|
|
bool isHardLineBreak(size_t index) {
|
|
return this->hasProperty(index, CodeUnitFlags::kHardLineBreakBefore);
|
|
}
|
|
|
|
bool isSoftLineBreak(size_t index) {
|
|
return index != 0 && this->hasProperty(index, CodeUnitFlags::kSoftLineBreakBefore);
|
|
}
|
|
|
|
bool isWhitespaces(TextRange range) {
|
|
if (range.leftToRight()) {
|
|
for (auto i = range.fStart; i < range.fEnd; ++i) {
|
|
if (!this->hasProperty(i, CodeUnitFlags::kPartOfWhiteSpace)) {
|
|
return false;
|
|
}
|
|
}
|
|
} else {
|
|
for (auto i = range.fStart; i > range.fEnd; --i) {
|
|
if (!this->hasProperty(i, CodeUnitFlags::kPartOfWhiteSpace)) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool isClusterEdge(size_t index) {
|
|
return this->hasProperty(index, CodeUnitFlags::kGraphemeStart) ||
|
|
this->hasProperty(index, CodeUnitFlags::kGlyphStart);
|
|
}
|
|
|
|
void adjustLeft(size_t* index) {
|
|
SkASSERT(index != nullptr);
|
|
while (*index != 0) {
|
|
if (isClusterEdge(*index)) {
|
|
return;
|
|
}
|
|
--index;
|
|
}
|
|
}
|
|
|
|
TextRun& run(const size_t index) { return fRuns[index]; }
|
|
|
|
// Simplification (using default font manager, default font family and default everything possible)
|
|
static bool drawText(const char* text, SkCanvas* canvas, SkScalar x, SkScalar y);
|
|
static bool drawText(const char* text, SkCanvas* canvas, SkScalar width);
|
|
static bool drawText(const char* text, SkCanvas* canvas, TextFormatStyle textFormat, SkColor foreground, SkColor background, const SkString& fontFamily, SkScalar fontSize, SkFontStyle fontStyle, SkScalar x, SkScalar y);
|
|
static bool drawText(const char* text, SkCanvas* canvas,
|
|
TextFormatStyle textFormat, SkColor foreground, SkColor background, const SkString& fontFamily, SkScalar fontSize, SkFontStyle fontStyle,
|
|
SkSize reqSize, SkScalar x, SkScalar y);
|
|
|
|
void sortDecorBlocks(SkTArray<DecorBlock, true>& decorBlocks);
|
|
|
|
bool computeCodeUnitProperties();
|
|
|
|
void markGlyphs();
|
|
|
|
// Iterating through the output glyphs and breaking the runs by units flag (no breaking if units == CodeUnitFlags::kNonExistingFlag)
|
|
template<typename Visitor>
|
|
void iterateByVisualOrder(CodeUnitFlags units, Visitor visitor);
|
|
template<typename Visitor>
|
|
void iterateByVisualOrder(SkTArray<DecorBlock, true>& decorBlocks, Visitor visitor);
|
|
|
|
private:
|
|
friend class TextIterator;
|
|
friend class Shaper;
|
|
friend class Wrapper;
|
|
|
|
SkString fText;
|
|
SkTArray<FontBlock, true> fFontBlocks;
|
|
//TextFormatStyle fTextFormatStyle;
|
|
//TextFontStyle fTextFontStyle;
|
|
SkTArray<TextRun, false> fRuns;
|
|
SkTArray<Line, false> fLines;
|
|
SkTArray<TextOutput, false> fTextOutputs;
|
|
|
|
std::unique_ptr<SkUnicode> fUnicode;
|
|
SkTArray<CodeUnitFlags, true> fCodeUnitProperties;
|
|
};
|
|
|
|
} // namespace text
|
|
} // namespace skia
|
|
|
|
#endif // Processor_DEFINED
|