blob: 7055b5d702173a4c142b2ad62a6c474bd48b7d8b [file] [log] [blame]
// Copyright 2021 Google LLC.
#ifndef Painter_DEFINED
#define Painter_DEFINED
#include "experimental/sktext/include/Text.h"
#include "experimental/sktext/include/Types.h"
#include "include/core/SkCanvas.h"
namespace skia {
namespace text {
struct DecoratedBlock {
DecoratedBlock(uint32_t count, SkPaint fg, SkPaint bg)
: charCount(count)
, foregroundPaint(std::move(fg))
, backgroundPaint(std::move(bg)) { }
uint32_t charCount;
SkPaint foregroundPaint;
SkPaint backgroundPaint;
};
class TrivialFontChain : public FontChain {
public:
TrivialFontChain(const char* ff, SkScalar size, SkFontStyle fontStyle)
: fTypeface(sk_sp<SkTypeface>(SkFontMgr::RefDefault()->matchFamilyStyle(ff, SkFontStyle::Normal())))
, fSize(size)
, fFontStyle(fontStyle) { }
size_t count() const override { return (size_t)1; }
sk_sp<SkTypeface> operator[](size_t index) const override {
SkASSERT(index == 0);
return fTypeface;
}
float fontSize() const override { return fSize; }
SkString locale() const override { return SkString("en"); }
sk_sp<SkTypeface> getTypeface() const { return fTypeface; }
bool empty() const { return fTypeface == nullptr; }
private:
sk_sp<SkTypeface> fTypeface;
SkScalar fSize;
SkFontStyle fFontStyle;
};
class MultipleFontChain : public FontChain {
public:
MultipleFontChain(std::vector<const char*> ffs, SkScalar size, SkFontStyle fontStyle)
: fSize(size)
, fFontStyle(fontStyle) {
for (auto& ff : ffs) {
auto typeface = SkFontMgr::RefDefault()->matchFamilyStyle(ff, SkFontStyle::Normal());
if (typeface != nullptr) {
fTypefaces.emplace_back(typeface);
}
}
}
size_t count() const override { return fTypefaces.size(); }
sk_sp<SkTypeface> operator[](size_t index) const override {
SkASSERT(index < fTypefaces.size());
return fTypefaces[index];
}
float fontSize() const override { return fSize; }
SkString locale() const override { return SkString("en"); }
bool empty() const { return fTypefaces.empty(); }
private:
std::vector<sk_sp<SkTypeface>> fTypefaces;
SkScalar fSize;
SkFontStyle fFontStyle;
};
class Paint : public Visitor {
public:
void paint(SkCanvas* canvas, SkPoint xy, UnicodeText* unicodeText, WrappedText* wrappedText, SkSpan<DecoratedBlock> decoratedBlocks);
// Simplification (using default font manager, default font family and default everything possible)
static bool drawText(std::u16string text, SkCanvas* canvas, SkScalar x, SkScalar y);
static bool drawText(std::u16string text, SkCanvas* canvas, SkScalar width);
static bool drawText(std::u16string text, SkCanvas* canvas,
TextDirection textDirection, TextAlign textAlign,
SkPaint foreground, SkPaint background,
const SkString& fontFamily, SkScalar fontSize, SkFontStyle fontStyle,
SkScalar x, SkScalar y);
static bool drawText(std::u16string text, SkCanvas* canvas,
TextDirection textDirection, TextAlign textAlign,
SkPaint foreground, SkPaint background,
const SkString& fontFamily, SkScalar fontSize, SkFontStyle fontStyle,
SkSize reqSize, SkScalar x, SkScalar y);
private:
static std::unique_ptr<WrappedText> layout(std::u16string text,
TextDirection textDirection, TextAlign textAlign,
SkSize reqSize,
SkSpan<FontBlock> fontBlocks);
void onGlyphRun(const SkFont& font,
DirTextRange dirTextRange,
SkRect bounds,
TextIndex trailingSpaces,
size_t glyphCount,
const uint16_t glyphs[],
const SkPoint positions[],
const TextIndex clusters[]) override;
// We guarantee that the text range will be inside one of the decorated blocks
DecoratedBlock findDecoratedBlock(TextRange textRange);
SkCanvas* fCanvas;
SkPoint fXY;
SkSpan<FontBlock> fFontBlocks;
SkSpan<DecoratedBlock> fDecoratedBlocks;
};
} // namespace text
} // namespace skia
#endif // Painter_DEFINED