blob: 2efb47d1983bd810ffd223245fd68c36fbf64c7a [file] [log] [blame]
// Copyright 2021 Google LLC.
#include "experimental/sktext/include/Processor.h"
#include "experimental/sktext/src/Shaper.h"
namespace skia {
namespace text {
// TODO: calculate intrinsic sizes
// Shape the text in one line
bool Shaper::process() {
auto text(fProcessor->fText);
for (auto& block : fProcessor->fFontBlocks) {
SkFont font(this->createFont(block));
SkShaper::TrivialFontRunIterator fontIter(font, text.size());
SkShaper::TrivialLanguageRunIterator langIter(text.c_str(), text.size());
std::unique_ptr<SkShaper::BiDiRunIterator> bidiIter(
SkShaper::MakeSkUnicodeBidiRunIterator(
fProcessor->fUnicode.get(), text.c_str(), text.size(), fDefaultTextDirection == TextDirection::kLtr ? 0 : 1));
std::unique_ptr<SkShaper::ScriptRunIterator> scriptIter(
SkShaper::MakeSkUnicodeHbScriptRunIterator(fProcessor->fUnicode.get(), text.c_str(), text.size()));
auto shaper = SkShaper::MakeShapeDontWrapOrReorder();
if (shaper == nullptr) {
// For instance, loadICU does not work. We have to stop the process
return false;
}
shaper->shape(text.c_str(), text.size(),
fontIter, *bidiIter, *scriptIter, langIter,
std::numeric_limits<SkScalar>::max(), this);
}
return true;
}
void Shaper::commitRunBuffer(const RunInfo&) {
fCurrentRun->commit();
fProcessor->fRuns.emplace_back(std::move(*fCurrentRun));
}
SkFont Shaper::createFont(const FontBlock& block) {
sk_sp<SkTypeface> typeface = matchTypeface(block.fFontFamily, block.fFontStyle);
SkFont font(std::move(typeface), block.fFontSize);
font.setEdging(SkFont::Edging::kAntiAlias);
font.setHinting(SkFontHinting::kSlight);
font.setSubpixel(true);
return font;
}
sk_sp<SkTypeface> Shaper::matchTypeface(const SkString& fontFamily, SkFontStyle fontStyle) {
sk_sp<SkFontStyleSet> set(fFontManager->matchFamily(fontFamily.c_str()));
if (!set || set->count() == 0) {
return nullptr;
}
sk_sp<SkTypeface> match(set->matchStyle(fontStyle));
if (match) {
return match;
}
return nullptr;
}
} // namespace text
} // namespace skia