mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-23 05:19:56 +00:00
Merge pull request #19531 from hrydgard/fix-text-perf-problem
Improve performance of UI text rendering
This commit is contained in:
commit
beed90ba8b
@ -521,7 +521,6 @@ void DrawBuffer::MeasureTextRect(FontID font_id, std::string_view text, const Bo
|
||||
return;
|
||||
}
|
||||
|
||||
std::string toMeasure = std::string(text);
|
||||
int wrap = align & (FLAG_WRAP_TEXT | FLAG_ELLIPSIZE_TEXT);
|
||||
if (wrap) {
|
||||
const AtlasFont *font = fontAtlas_->getFont(font_id);
|
||||
@ -532,10 +531,12 @@ void DrawBuffer::MeasureTextRect(FontID font_id, std::string_view text, const Bo
|
||||
*h = 0.0f;
|
||||
return;
|
||||
}
|
||||
std::string toMeasure = std::string(text);
|
||||
AtlasWordWrapper wrapper(*font, fontscalex, toMeasure, bounds.w, wrap);
|
||||
toMeasure = wrapper.Wrapped();
|
||||
} else {
|
||||
MeasureText(font_id, text, w, h);
|
||||
}
|
||||
MeasureText(font_id, toMeasure, w, h);
|
||||
}
|
||||
|
||||
void DrawBuffer::DrawTextShadow(FontID font, std::string_view text, float x, float y, Color color, int flags) {
|
||||
|
@ -18,8 +18,6 @@ TextDrawer::TextDrawer(Draw::DrawContext *draw) : draw_(draw) {
|
||||
// These probably shouldn't be state.
|
||||
dpiScale_ = CalculateDPIScale();
|
||||
}
|
||||
TextDrawer::~TextDrawer() {
|
||||
}
|
||||
|
||||
float TextDrawerWordWrapper::MeasureWidth(std::string_view str) {
|
||||
float w, h;
|
||||
@ -123,13 +121,49 @@ void TextDrawer::DrawString(DrawBuffer &target, std::string_view str, float x, f
|
||||
target.Flush(true);
|
||||
}
|
||||
|
||||
void TextDrawer::MeasureStringRect(std::string_view str, const Bounds &bounds, float *w, float *h, int align) {
|
||||
std::string toMeasure = std::string(str);
|
||||
int wrap = align & (FLAG_WRAP_TEXT | FLAG_ELLIPSIZE_TEXT);
|
||||
if (wrap) {
|
||||
WrapString(toMeasure, toMeasure.c_str(), bounds.w, wrap);
|
||||
void TextDrawer::MeasureString(std::string_view str, float *w, float *h) {
|
||||
if (str.empty()) {
|
||||
*w = 0.0;
|
||||
*h = 0.0;
|
||||
return;
|
||||
}
|
||||
|
||||
CacheKey key{ std::string(str), fontHash_ };
|
||||
|
||||
TextMeasureEntry *entry;
|
||||
auto iter = sizeCache_.find(key);
|
||||
if (iter != sizeCache_.end()) {
|
||||
entry = iter->second.get();
|
||||
} else {
|
||||
entry = new TextMeasureEntry();
|
||||
float extW, extH;
|
||||
MeasureStringInternal(str, &extW, &extH);
|
||||
entry->width = extW;
|
||||
entry->height = extH;
|
||||
// Hm, use the old calculation?
|
||||
// int h = i == lines.size() - 1 ? entry->height : metrics.tmHeight + metrics.tmExternalLeading;
|
||||
sizeCache_[key] = std::unique_ptr<TextMeasureEntry>(entry);
|
||||
}
|
||||
|
||||
entry->lastUsedFrame = frameCount_;
|
||||
*w = entry->width * fontScaleX_ * dpiScale_;
|
||||
*h = entry->height * fontScaleY_ * dpiScale_;
|
||||
}
|
||||
|
||||
void TextDrawer::MeasureStringRect(std::string_view str, const Bounds &bounds, float *w, float *h, int align) {
|
||||
int wrap = align & (FLAG_WRAP_TEXT | FLAG_ELLIPSIZE_TEXT);
|
||||
|
||||
float plainW, plainH;
|
||||
MeasureString(str, &plainW, &plainH);
|
||||
|
||||
if (wrap && plainW > bounds.w) {
|
||||
std::string toMeasure = std::string(str);
|
||||
WrapString(toMeasure, toMeasure.c_str(), bounds.w, wrap);
|
||||
MeasureString(toMeasure, w, h);
|
||||
} else {
|
||||
*w = plainW;
|
||||
*h = plainH;
|
||||
}
|
||||
MeasureString(toMeasure, w, h);
|
||||
}
|
||||
|
||||
void TextDrawer::DrawStringRect(DrawBuffer &target, std::string_view str, const Bounds &bounds, uint32_t color, int align) {
|
||||
@ -186,7 +220,7 @@ void TextDrawer::OncePerFrame() {
|
||||
}
|
||||
|
||||
// Drop old strings. Use a prime number to reduce clashing with other rhythms
|
||||
if (frameCount_ % 23 == 0) {
|
||||
if (frameCount_ % 63 == 0) {
|
||||
for (auto iter = cache_.begin(); iter != cache_.end();) {
|
||||
if (frameCount_ - iter->second->lastUsedFrame > 100) {
|
||||
if (iter->second->texture)
|
||||
|
@ -42,14 +42,14 @@ struct TextMeasureEntry {
|
||||
|
||||
class TextDrawer {
|
||||
public:
|
||||
virtual ~TextDrawer();
|
||||
virtual ~TextDrawer() = default;
|
||||
|
||||
virtual bool IsReady() const { return true; }
|
||||
virtual uint32_t SetFont(const char *fontName, int size, int flags) = 0;
|
||||
virtual void SetFont(uint32_t fontHandle) = 0; // Shortcut once you've set the font once.
|
||||
void SetFontScale(float xscale, float yscale);
|
||||
virtual void MeasureString(std::string_view str, float *w, float *h) = 0;
|
||||
virtual void MeasureStringRect(std::string_view str, const Bounds &bounds, float *w, float *h, int align = ALIGN_TOPLEFT);
|
||||
void MeasureString(std::string_view str, float *w, float *h);
|
||||
void MeasureStringRect(std::string_view str, const Bounds &bounds, float *w, float *h, int align = ALIGN_TOPLEFT);
|
||||
|
||||
void DrawString(DrawBuffer &target, std::string_view str, float x, float y, uint32_t color, int align = ALIGN_TOPLEFT);
|
||||
void DrawStringRect(DrawBuffer &target, std::string_view str, const Bounds &bounds, uint32_t color, int align);
|
||||
@ -69,6 +69,9 @@ public:
|
||||
|
||||
protected:
|
||||
TextDrawer(Draw::DrawContext *draw);
|
||||
|
||||
virtual void MeasureStringInternal(std::string_view str, float *w, float *h) = 0;
|
||||
|
||||
void ClearCache();
|
||||
|
||||
virtual bool SupportsColorEmoji() const = 0;
|
||||
|
@ -75,41 +75,23 @@ void TextDrawerAndroid::SetFont(uint32_t fontHandle) {
|
||||
}
|
||||
}
|
||||
|
||||
void TextDrawerAndroid::MeasureString(std::string_view str, float *w, float *h) {
|
||||
if (str.empty()) {
|
||||
*w = 0.0;
|
||||
*h = 0.0;
|
||||
return;
|
||||
}
|
||||
|
||||
CacheKey key{ std::string(str), fontHash_ };
|
||||
TextMeasureEntry *entry;
|
||||
auto iter = sizeCache_.find(key);
|
||||
if (iter != sizeCache_.end()) {
|
||||
entry = iter->second.get();
|
||||
void TextDrawerAndroid::MeasureStringInternal(std::string_view str, float *w, float *h) {
|
||||
float scaledSize = 14;
|
||||
auto iter = fontMap_.find(fontHash_);
|
||||
if (iter != fontMap_.end()) {
|
||||
scaledSize = iter->second.size;
|
||||
} else {
|
||||
float scaledSize = 14;
|
||||
auto iter = fontMap_.find(fontHash_);
|
||||
if (iter != fontMap_.end()) {
|
||||
scaledSize = iter->second.size;
|
||||
} else {
|
||||
ERROR_LOG(Log::G3D, "Missing font");
|
||||
}
|
||||
std::string text(str);
|
||||
auto env = getEnv();
|
||||
// Unfortunate that we can't create a jstr from a std::string_view directly.
|
||||
jstring jstr = env->NewStringUTF(text.c_str());
|
||||
uint32_t size = env->CallStaticIntMethod(cls_textRenderer, method_measureText, jstr, scaledSize);
|
||||
env->DeleteLocalRef(jstr);
|
||||
|
||||
entry = new TextMeasureEntry();
|
||||
entry->width = (size >> 16);
|
||||
entry->height = (size & 0xFFFF);
|
||||
sizeCache_[key] = std::unique_ptr<TextMeasureEntry>(entry);
|
||||
ERROR_LOG(Log::G3D, "Missing font");
|
||||
}
|
||||
entry->lastUsedFrame = frameCount_;
|
||||
*w = entry->width * fontScaleX_ * dpiScale_;
|
||||
*h = entry->height * fontScaleY_ * dpiScale_;
|
||||
std::string text(str);
|
||||
auto env = getEnv();
|
||||
// Unfortunate that we can't create a jstr from a std::string_view directly.
|
||||
jstring jstr = env->NewStringUTF(text.c_str());
|
||||
uint32_t size = env->CallStaticIntMethod(cls_textRenderer, method_measureText, jstr, scaledSize);
|
||||
env->DeleteLocalRef(jstr);
|
||||
|
||||
*w = (size >> 16);
|
||||
*h = (size & 0xFFFF);
|
||||
}
|
||||
|
||||
bool TextDrawerAndroid::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) {
|
||||
|
@ -21,10 +21,10 @@ public:
|
||||
bool IsReady() const override;
|
||||
uint32_t SetFont(const char *fontName, int size, int flags) override;
|
||||
void SetFont(uint32_t fontHandle) override; // Shortcut once you've set the font once.
|
||||
void MeasureString(std::string_view str, float *w, float *h) override;
|
||||
bool DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) override;
|
||||
|
||||
protected:
|
||||
void MeasureStringInternal(std::string_view str, float *w, float *h) override;
|
||||
bool SupportsColorEmoji() const override { return true; }
|
||||
|
||||
void ClearFonts() override;
|
||||
|
@ -18,10 +18,10 @@ public:
|
||||
|
||||
uint32_t SetFont(const char *fontName, int size, int flags) override;
|
||||
void SetFont(uint32_t fontHandle) override; // Shortcut once you've set the font once.
|
||||
void MeasureString(std::string_view str, float *w, float *h) override;
|
||||
bool DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) override;
|
||||
|
||||
protected:
|
||||
void MeasureStringInternal(std::string_view str, float *w, float *h) override;
|
||||
bool SupportsColorEmoji() const override { return true; }
|
||||
|
||||
void ClearFonts() override;
|
||||
|
@ -117,50 +117,35 @@ void TextDrawerCocoa::ClearFonts() {
|
||||
fontMap_.clear();
|
||||
}
|
||||
|
||||
void TextDrawerCocoa::MeasureString(std::string_view str, float *w, float *h) {
|
||||
CacheKey key{ std::string(str), fontHash_ };
|
||||
|
||||
TextMeasureEntry *entry;
|
||||
auto iter = sizeCache_.find(key);
|
||||
if (iter != sizeCache_.end()) {
|
||||
entry = iter->second.get();
|
||||
} else {
|
||||
// INFO_LOG(Log::System, "Measuring %.*s", (int)str.length(), str.data());
|
||||
|
||||
auto iter = fontMap_.find(fontHash_);
|
||||
NSDictionary *attributes = nil;
|
||||
if (iter != fontMap_.end()) {
|
||||
attributes = iter->second->attributes;
|
||||
}
|
||||
|
||||
std::vector<std::string_view> lines;
|
||||
SplitString(str, '\n', lines);
|
||||
|
||||
int extW = 0, extH = 0;
|
||||
for (auto &line : lines) {
|
||||
NSString *string = [[NSString alloc] initWithBytes:line.data() length:line.size() encoding: NSUTF8StringEncoding];
|
||||
NSAttributedString* as = [[NSAttributedString alloc] initWithString:string attributes:attributes];
|
||||
CTLineRef ctline = CTLineCreateWithAttributedString((CFAttributedStringRef)as);
|
||||
CGFloat ascent, descent, leading;
|
||||
double fWidth = CTLineGetTypographicBounds(ctline, &ascent, &descent, &leading);
|
||||
|
||||
size_t width = (size_t)ceilf(fWidth);
|
||||
size_t height = (size_t)ceilf(ascent + descent);
|
||||
|
||||
if (width > extW)
|
||||
extW = width;
|
||||
extH += height;
|
||||
}
|
||||
|
||||
entry = new TextMeasureEntry();
|
||||
entry->width = extW;
|
||||
entry->height = extH;
|
||||
sizeCache_[key] = std::unique_ptr<TextMeasureEntry>(entry);
|
||||
void TextDrawerCocoa::MeasureStringInternal(std::string_view str, float *w, float *h) {
|
||||
// INFO_LOG(Log::System, "Measuring %.*s", (int)str.length(), str.data());
|
||||
auto iter = fontMap_.find(fontHash_);
|
||||
NSDictionary *attributes = nil;
|
||||
if (iter != fontMap_.end()) {
|
||||
attributes = iter->second->attributes;
|
||||
}
|
||||
|
||||
entry->lastUsedFrame = frameCount_;
|
||||
*w = entry->width * fontScaleX_ * dpiScale_;
|
||||
*h = entry->height * fontScaleY_ * dpiScale_;
|
||||
std::vector<std::string_view> lines;
|
||||
SplitString(str, '\n', lines);
|
||||
|
||||
int extW = 0, extH = 0;
|
||||
for (auto &line : lines) {
|
||||
NSString *string = [[NSString alloc] initWithBytes:line.data() length:line.size() encoding: NSUTF8StringEncoding];
|
||||
NSAttributedString* as = [[NSAttributedString alloc] initWithString:string attributes:attributes];
|
||||
CTLineRef ctline = CTLineCreateWithAttributedString((CFAttributedStringRef)as);
|
||||
CGFloat ascent, descent, leading;
|
||||
double fWidth = CTLineGetTypographicBounds(ctline, &ascent, &descent, &leading);
|
||||
|
||||
size_t width = (size_t)ceilf(fWidth);
|
||||
size_t height = (size_t)ceilf(ascent + descent);
|
||||
|
||||
if (width > extW)
|
||||
extW = width;
|
||||
extH += height;
|
||||
}
|
||||
|
||||
*w = extW;
|
||||
*h = extH;
|
||||
}
|
||||
|
||||
bool TextDrawerCocoa::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) {
|
||||
|
@ -51,27 +51,13 @@ void TextDrawerQt::SetFont(uint32_t fontHandle) {
|
||||
}
|
||||
}
|
||||
|
||||
void TextDrawerQt::MeasureString(std::string_view str, float *w, float *h) {
|
||||
CacheKey key{ std::string(str), fontHash_ };
|
||||
void TextDrawerQt::MeasureStringInternal(std::string_view str, float *w, float *h) {
|
||||
QFont* font = fontMap_.find(fontHash_)->second;
|
||||
QFontMetrics fm(*font);
|
||||
QSize size = fm.size(0, QString::fromUtf8(str.data(), str.length()));
|
||||
|
||||
TextMeasureEntry *entry;
|
||||
auto iter = sizeCache_.find(key);
|
||||
if (iter != sizeCache_.end()) {
|
||||
entry = iter->second.get();
|
||||
} else {
|
||||
QFont* font = fontMap_.find(fontHash_)->second;
|
||||
QFontMetrics fm(*font);
|
||||
QSize size = fm.size(0, QString::fromUtf8(str.data(), str.length()));
|
||||
|
||||
entry = new TextMeasureEntry();
|
||||
entry->width = size.width();
|
||||
entry->height = size.height();
|
||||
sizeCache_[key] = std::unique_ptr<TextMeasureEntry>(entry);
|
||||
}
|
||||
|
||||
entry->lastUsedFrame = frameCount_;
|
||||
*w = entry->width * fontScaleX_ * dpiScale_;
|
||||
*h = entry->height * fontScaleY_ * dpiScale_;
|
||||
*w = size.width();
|
||||
*h = size.height();
|
||||
}
|
||||
|
||||
bool TextDrawerQt::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) {
|
||||
|
@ -16,10 +16,10 @@ public:
|
||||
|
||||
uint32_t SetFont(const char *fontName, int size, int flags) override;
|
||||
void SetFont(uint32_t fontHandle) override; // Shortcut once you've set the font once.
|
||||
void MeasureString(std::string_view str, float *w, float *h) override;
|
||||
bool DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) override;
|
||||
|
||||
protected:
|
||||
void MeasureStringInternal(std::string_view str, float *w, float *h) override;
|
||||
bool SupportsColorEmoji() const override { return false; }
|
||||
|
||||
void ClearFonts() override;
|
||||
|
@ -186,15 +186,13 @@ void TextDrawerSDL::PrepareFallbackFonts(std::string_view locale) {
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t TextDrawerSDL::CheckMissingGlyph(const std::string& text) {
|
||||
uint32_t TextDrawerSDL::CheckMissingGlyph(std::string_view text) {
|
||||
TTF_Font *font = fontMap_.find(fontHash_)->second;
|
||||
UTF8 utf8Decoded(text.c_str());
|
||||
UTF8 utf8Decoded(text);
|
||||
|
||||
uint32_t missingGlyph = 0;
|
||||
for (int i = 0; i < text.length(); ) {
|
||||
while (!utf8Decoded.end()) {
|
||||
uint32_t glyph = utf8Decoded.next();
|
||||
i = utf8Decoded.byteIndex();
|
||||
|
||||
if (!TTF_GlyphIsProvided32(font, glyph)) {
|
||||
missingGlyph = glyph;
|
||||
break;
|
||||
@ -279,39 +277,28 @@ void TextDrawerSDL::SetFont(uint32_t fontHandle) {
|
||||
}
|
||||
}
|
||||
|
||||
void TextDrawerSDL::MeasureString(std::string_view str, float *w, float *h) {
|
||||
CacheKey key{ std::string(str), fontHash_ };
|
||||
void TextDrawerSDL::MeasureStringInternal(std::string_view str, float *w, float *h) {
|
||||
TTF_Font *font = fontMap_.find(fontHash_)->second;
|
||||
int ptSize = TTF_FontHeight(font) / 1.35;
|
||||
|
||||
TextMeasureEntry *entry;
|
||||
auto iter = sizeCache_.find(key);
|
||||
if (iter != sizeCache_.end()) {
|
||||
entry = iter->second.get();
|
||||
} else {
|
||||
TTF_Font *font = fontMap_.find(fontHash_)->second;
|
||||
int ptSize = TTF_FontHeight(font) / 1.35;
|
||||
|
||||
uint32_t missingGlyph = CheckMissingGlyph(key.text);
|
||||
uint32_t missingGlyph = CheckMissingGlyph(str);
|
||||
|
||||
if (missingGlyph) {
|
||||
int fallbackFont = FindFallbackFonts(missingGlyph, ptSize);
|
||||
if (fallbackFont >= 0) {
|
||||
font = fallbackFonts_[fallbackFont];
|
||||
}
|
||||
if (missingGlyph) {
|
||||
int fallbackFont = FindFallbackFonts(missingGlyph, ptSize);
|
||||
if (fallbackFont >= 0) {
|
||||
font = fallbackFonts_[fallbackFont];
|
||||
}
|
||||
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
TTF_SizeUTF8(font, key.text.c_str(), &width, &height);
|
||||
|
||||
entry = new TextMeasureEntry();
|
||||
entry->width = width;
|
||||
entry->height = height;
|
||||
sizeCache_[key] = std::unique_ptr<TextMeasureEntry>(entry);
|
||||
}
|
||||
|
||||
entry->lastUsedFrame = frameCount_;
|
||||
*w = entry->width * fontScaleX_ * dpiScale_;
|
||||
*h = entry->height * fontScaleY_ * dpiScale_;
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
|
||||
// Unfortunately we need to zero-terminate here.
|
||||
std::string text(str);
|
||||
TTF_SizeUTF8(font, text.c_str(), &width, &height);
|
||||
|
||||
*w = width;
|
||||
*h = height;
|
||||
}
|
||||
|
||||
bool TextDrawerSDL::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) {
|
||||
|
@ -19,16 +19,17 @@ public:
|
||||
|
||||
uint32_t SetFont(const char *fontName, int size, int flags) override;
|
||||
void SetFont(uint32_t fontHandle) override; // Shortcut once you've set the font once.
|
||||
void MeasureString(std::string_view str, float *w, float *h) override;
|
||||
bool DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) override;
|
||||
|
||||
protected:
|
||||
void MeasureStringInternal(std::string_view str, float *w, float *h) override;
|
||||
|
||||
bool SupportsColorEmoji() const override { return false; }
|
||||
void ClearFonts() override;
|
||||
|
||||
private:
|
||||
void PrepareFallbackFonts(std::string_view locale);
|
||||
uint32_t CheckMissingGlyph(const std::string& text);
|
||||
uint32_t CheckMissingGlyph(std::string_view text);
|
||||
int FindFallbackFonts(uint32_t missingGlyph, int ptSize);
|
||||
|
||||
std::map<uint32_t, _TTF_Font *> fontMap_;
|
||||
|
@ -204,48 +204,34 @@ void TextDrawerUWP::SetFont(uint32_t fontHandle) {
|
||||
}
|
||||
}
|
||||
|
||||
void TextDrawerUWP::MeasureString(std::string_view str, float *w, float *h) {
|
||||
CacheKey key{ std::string(str), fontHash_ };
|
||||
|
||||
TextMeasureEntry *entry;
|
||||
auto iter = sizeCache_.find(key);
|
||||
if (iter != sizeCache_.end()) {
|
||||
entry = iter->second.get();
|
||||
} else {
|
||||
IDWriteTextFormat* format = nullptr;
|
||||
auto iter = fontMap_.find(fontHash_);
|
||||
if (iter != fontMap_.end()) {
|
||||
format = iter->second->textFmt;
|
||||
}
|
||||
if (!format) return;
|
||||
|
||||
std::wstring wstr = ConvertUTF8ToWString(ReplaceAll(std::string(str), "\n", "\r\n"));
|
||||
|
||||
format->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_LEADING);
|
||||
|
||||
IDWriteTextLayout* layout;
|
||||
m_dwriteFactory->CreateTextLayout(
|
||||
(LPWSTR)wstr.c_str(),
|
||||
(int)wstr.size(),
|
||||
format,
|
||||
MAX_TEXT_WIDTH,
|
||||
MAX_TEXT_HEIGHT,
|
||||
&layout
|
||||
);
|
||||
|
||||
DWRITE_TEXT_METRICS metrics;
|
||||
layout->GetMetrics(&metrics);
|
||||
layout->Release();
|
||||
|
||||
entry = new TextMeasureEntry();
|
||||
entry->width = (int)(metrics.width + 1.0f);
|
||||
entry->height = (int)(metrics.height + 1.0f);
|
||||
sizeCache_[key] = std::unique_ptr<TextMeasureEntry>(entry);
|
||||
void TextDrawerUWP::MeasureStringInternal(std::string_view str, float *w, float *h) {
|
||||
IDWriteTextFormat* format = nullptr;
|
||||
auto iter = fontMap_.find(fontHash_);
|
||||
if (iter != fontMap_.end()) {
|
||||
format = iter->second->textFmt;
|
||||
}
|
||||
if (!format) return;
|
||||
|
||||
entry->lastUsedFrame = frameCount_;
|
||||
*w = entry->width * fontScaleX_ * dpiScale_;
|
||||
*h = entry->height * fontScaleY_ * dpiScale_;
|
||||
std::wstring wstr = ConvertUTF8ToWString(ReplaceAll(std::string(str), "\n", "\r\n"));
|
||||
|
||||
format->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_LEADING);
|
||||
|
||||
IDWriteTextLayout* layout;
|
||||
m_dwriteFactory->CreateTextLayout(
|
||||
(LPWSTR)wstr.c_str(),
|
||||
(int)wstr.size(),
|
||||
format,
|
||||
MAX_TEXT_WIDTH,
|
||||
MAX_TEXT_HEIGHT,
|
||||
&layout
|
||||
);
|
||||
|
||||
DWRITE_TEXT_METRICS metrics;
|
||||
layout->GetMetrics(&metrics);
|
||||
layout->Release();
|
||||
|
||||
*w = (int)(metrics.width + 1.0f);
|
||||
*h = (int)(metrics.height + 1.0f);
|
||||
}
|
||||
|
||||
bool TextDrawerUWP::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) {
|
||||
|
@ -21,10 +21,10 @@ public:
|
||||
|
||||
uint32_t SetFont(const char *fontName, int size, int flags) override;
|
||||
void SetFont(uint32_t fontHandle) override; // Shortcut once you've set the font once.
|
||||
void MeasureString(std::string_view str, float *w, float *h) override;
|
||||
bool DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) override;
|
||||
|
||||
protected:
|
||||
void MeasureStringInternal(std::string_view str, float *w, float *h) override;
|
||||
bool SupportsColorEmoji() const override { return true; }
|
||||
void ClearFonts() override;
|
||||
|
||||
|
@ -120,46 +120,30 @@ void TextDrawerWin32::SetFont(uint32_t fontHandle) {
|
||||
}
|
||||
}
|
||||
|
||||
void TextDrawerWin32::MeasureString(std::string_view str, float *w, float *h) {
|
||||
CacheKey key{ std::string(str), fontHash_ };
|
||||
|
||||
TextMeasureEntry *entry;
|
||||
auto iter = sizeCache_.find(key);
|
||||
if (iter != sizeCache_.end()) {
|
||||
entry = iter->second.get();
|
||||
} else {
|
||||
auto iter = fontMap_.find(fontHash_);
|
||||
if (iter != fontMap_.end()) {
|
||||
SelectObject(ctx_->hDC, iter->second->hFont);
|
||||
}
|
||||
|
||||
std::string toMeasure(str);
|
||||
|
||||
std::vector<std::string_view> lines;
|
||||
SplitString(toMeasure, '\n', lines);
|
||||
|
||||
int extW = 0, extH = 0;
|
||||
for (auto &line : lines) {
|
||||
SIZE size;
|
||||
std::wstring wstr = ConvertUTF8ToWString(line);
|
||||
GetTextExtentPoint32(ctx_->hDC, wstr.c_str(), (int)wstr.size(), &size);
|
||||
|
||||
if (size.cx > extW)
|
||||
extW = size.cx;
|
||||
extH += size.cy;
|
||||
}
|
||||
|
||||
entry = new TextMeasureEntry();
|
||||
entry->width = extW;
|
||||
entry->height = extH;
|
||||
// Hm, use the old calculation?
|
||||
// int h = i == lines.size() - 1 ? entry->height : metrics.tmHeight + metrics.tmExternalLeading;
|
||||
sizeCache_[key] = std::unique_ptr<TextMeasureEntry>(entry);
|
||||
void TextDrawerWin32::MeasureStringInternal(std::string_view str, float *w, float *h) {
|
||||
auto iter = fontMap_.find(fontHash_);
|
||||
if (iter != fontMap_.end()) {
|
||||
SelectObject(ctx_->hDC, iter->second->hFont);
|
||||
}
|
||||
|
||||
entry->lastUsedFrame = frameCount_;
|
||||
*w = entry->width * fontScaleX_ * dpiScale_;
|
||||
*h = entry->height * fontScaleY_ * dpiScale_;
|
||||
std::string toMeasure(str);
|
||||
|
||||
std::vector<std::string_view> lines;
|
||||
SplitString(toMeasure, '\n', lines);
|
||||
|
||||
int extW = 0, extH = 0;
|
||||
for (auto &line : lines) {
|
||||
SIZE size;
|
||||
std::wstring wstr = ConvertUTF8ToWString(line);
|
||||
GetTextExtentPoint32(ctx_->hDC, wstr.c_str(), (int)wstr.size(), &size);
|
||||
|
||||
if (size.cx > extW)
|
||||
extW = size.cx;
|
||||
extH += size.cy;
|
||||
}
|
||||
|
||||
*w = extW;
|
||||
*h = extH;
|
||||
}
|
||||
|
||||
bool TextDrawerWin32::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) {
|
||||
|
@ -21,10 +21,10 @@ public:
|
||||
|
||||
uint32_t SetFont(const char *fontName, int size, int flags) override;
|
||||
void SetFont(uint32_t fontHandle) override; // Shortcut once you've set the font once.
|
||||
void MeasureString(std::string_view str, float *w, float *h) override;
|
||||
bool DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) override;
|
||||
|
||||
protected:
|
||||
void MeasureStringInternal(std::string_view str, float *w, float *h) override;
|
||||
bool SupportsColorEmoji() const override { return false; }
|
||||
void ClearFonts() override;
|
||||
|
||||
|
@ -571,7 +571,7 @@ public:
|
||||
TaskPriority Priority() const override {
|
||||
return TaskPriority::NORMAL;
|
||||
}
|
||||
virtual void Run() {
|
||||
virtual void Run() override {
|
||||
mixer_->LoadSamplesOnThread();
|
||||
}
|
||||
private:
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 563230b1c249774b4852c944dc7cdcb952c9e8e8
|
||||
Subproject commit 32917bdddf4982e62047862c6633e7671aaaf2cb
|
Loading…
Reference in New Issue
Block a user