Seems to be working now, though need to figure out which font face we can use.

This commit is contained in:
Henrik Rydgård 2024-05-25 15:00:08 +02:00
parent 3965c1ae6b
commit 0bbaaef787
15 changed files with 53 additions and 34 deletions

View File

@ -807,8 +807,6 @@ add_library(Common STATIC
Common/Render/Text/draw_text.h
Common/Render/Text/draw_text_android.cpp
Common/Render/Text/draw_text_android.h
Common/Render/Text/draw_text_cocoa.mm
Common/Render/Text/draw_text_cocoa.h
Common/Render/Text/draw_text_sdl.cpp
Common/Render/Text/draw_text_sdl.h
Common/Render/Text/draw_text_win.cpp
@ -1273,6 +1271,12 @@ if(OPENXR AND NOT ARMV7_DEVICE)
set(nativeExtraLibs ${nativeExtraLibs} openxr_loader)
endif()
if(IOS OR MACOSX)
set(nativeExtra ${nativeExtra}
Common/Render/Text/draw_text_cocoa.mm
Common/Render/Text/draw_text_cocoa.h)
endif()
if(ANDROID)
set(NativeAppSource ${NativeAppSource}
android/jni/app-android.cpp

View File

@ -71,7 +71,7 @@ void TextDrawer::DrawStringRect(DrawBuffer &target, std::string_view str, const
DrawString(target, toDraw.c_str(), x, y, color, align);
}
void TextDrawer::DrawStringBitmapRect(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, const Bounds &bounds, int align) {
bool TextDrawer::DrawStringBitmapRect(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, const Bounds &bounds, int align) {
std::string toDraw(str);
int wrap = align & (FLAG_WRAP_TEXT | FLAG_ELLIPSIZE_TEXT);
if (wrap) {
@ -79,7 +79,7 @@ void TextDrawer::DrawStringBitmapRect(std::vector<uint8_t> &bitmapData, TextStri
WrapString(toDraw, str, rotated ? bounds.h : bounds.w, wrap);
}
DrawStringBitmap(bitmapData, entry, texFormat, toDraw.c_str(), align);
return DrawStringBitmap(bitmapData, entry, texFormat, toDraw.c_str(), align);
}
TextDrawer *TextDrawer::Create(Draw::DrawContext *draw) {

View File

@ -53,8 +53,8 @@ public:
virtual void DrawString(DrawBuffer &target, std::string_view str, float x, float y, uint32_t color, int align = ALIGN_TOPLEFT) = 0;
void DrawStringRect(DrawBuffer &target, std::string_view str, const Bounds &bounds, uint32_t color, int align);
virtual void DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align = ALIGN_TOPLEFT) = 0;
void DrawStringBitmapRect(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, const Bounds &bounds, int align);
virtual bool DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align = ALIGN_TOPLEFT) = 0;
bool DrawStringBitmapRect(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, const Bounds &bounds, int align);
// Use for housekeeping like throwing out old strings.
virtual void OncePerFrame() = 0;

View File

@ -174,10 +174,10 @@ void TextDrawerAndroid::MeasureStringRect(std::string_view str, const Bounds &bo
*h = total_h * fontScaleY_ * dpiScale_;
}
void TextDrawerAndroid::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align) {
bool TextDrawerAndroid::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align) {
if (str.empty()) {
bitmapData.clear();
return;
return false;
}
double size = 0.0;
@ -244,6 +244,7 @@ void TextDrawerAndroid::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextS
}
env->ReleaseIntArrayElements(imageData, jimage, 0);
env->DeleteLocalRef(imageData);
return true;
}
void TextDrawerAndroid::DrawString(DrawBuffer &target, std::string_view str, float x, float y, uint32_t color, int align) {

View File

@ -24,7 +24,7 @@ public:
void MeasureString(std::string_view str, float *w, float *h) override;
void MeasureStringRect(std::string_view str, const Bounds &bounds, float *w, float *h, int align = ALIGN_TOPLEFT) override;
void DrawString(DrawBuffer &target, std::string_view str, float x, float y, uint32_t color, int align = ALIGN_TOPLEFT) override;
void DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align = ALIGN_TOPLEFT) override;
bool DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align = ALIGN_TOPLEFT) override;
// Use for housekeeping like throwing out old strings.
void OncePerFrame() override;

View File

@ -21,7 +21,7 @@ public:
void MeasureString(std::string_view str, float *w, float *h) override;
void MeasureStringRect(std::string_view str, const Bounds &bounds, float *w, float *h, int align = ALIGN_TOPLEFT) override;
void DrawString(DrawBuffer &target, std::string_view str, float x, float y, uint32_t color, int align = ALIGN_TOPLEFT) override;
void DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align = ALIGN_TOPLEFT) override;
bool DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align = ALIGN_TOPLEFT) override;
// Use for housekeeping like throwing out old strings.
void OncePerFrame() override;

View File

@ -41,12 +41,12 @@ public:
void Create() {
// Create an attributed string with string and font information
CGFloat fontSize = height * dpiScale;
CTFontRef font = CTFontCreateWithName(CFSTR("Helvetica Light"), fontSize, nil);
INFO_LOG(G3D, "Creating cocoa typeface '%s' size %d", fname.c_str(), height);
CTFontRef font = CTFontCreateWithName(CFSTR("Helvetica"), fontSize, nil);
attributes = [NSDictionary dictionaryWithObjectsAndKeys:
(id)font, kCTFontAttributeName,
kCFBooleanTrue, kCTForegroundColorFromContextAttributeName,
nil];
//[attributes setValue:kCGColorWhite forKey: kCTForegroundColorAttributeName];
(id)font, kCTFontAttributeName,
kCFBooleanTrue, kCTForegroundColorFromContextAttributeName, // Lets us specify the color later.
nil];
}
void Destroy() {
//CFRelease(font);
@ -261,7 +261,9 @@ void TextDrawerCocoa::DrawString(DrawBuffer &target, std::string_view str, float
// because we need white. Well, we could using swizzle, but not all our backends support that.
TextureDesc desc{};
std::vector<uint8_t> bitmapData;
DrawStringBitmap(bitmapData, *entry, texFormat, str, align);
if (!DrawStringBitmap(bitmapData, *entry, texFormat, str, align)) {
return;
}
desc.initData.push_back(&bitmapData[0]);
desc.type = TextureType::LINEAR2D;
@ -291,17 +293,18 @@ void TextDrawerCocoa::DrawString(DrawBuffer &target, std::string_view str, float
}
}
void TextDrawerCocoa::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align) {
bool TextDrawerCocoa::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align) {
if (str.empty()) {
bitmapData.clear();
return;
return false;
}
NSString* string = [[NSString alloc] initWithBytes:str.data() length:str.size() encoding: NSUTF8StringEncoding];
std::string printable = ReplaceAll(str, "&&", "&");
NSString* string = [[NSString alloc] initWithBytes:printable.data() length:printable.length() encoding: NSUTF8StringEncoding];
auto iter = fontMap_.find(fontHash_);
if (iter == fontMap_.end()) {
return;
return false;
}
NSDictionary* attributes = iter->second->attributes;
NSAttributedString* as = [[NSAttributedString alloc] initWithString:string attributes:attributes];
@ -314,6 +317,12 @@ void TextDrawerCocoa::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStr
// On iOS 4.0 and Mac OS X v10.6 you can pass null for data
size_t width = (size_t)ceilf(fWidth);
size_t height = (size_t)ceilf(ascent + descent);
if (!width || !height) {
WARN_LOG(G3D, "Text '%.*s' caused a zero size image", (int)str.length(), str.data());
return false;
}
uint32_t *bitmap = new uint32_t[width * height];
memset(bitmap, 0, width * height * 4);
@ -387,6 +396,7 @@ void TextDrawerCocoa::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStr
}
delete [] bitmap;
return true;
}
void TextDrawerCocoa::OncePerFrame() {

View File

@ -89,10 +89,10 @@ void TextDrawerQt::MeasureStringRect(std::string_view str, const Bounds &bounds,
*h = (float)size.height() * fontScaleY_ * dpiScale_;
}
void TextDrawerQt::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align) {
bool TextDrawerQt::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align) {
if (str.empty()) {
bitmapData.clear();
return;
return false;
}
QFont *font = fontMap_.find(fontHash_)->second;
@ -101,7 +101,7 @@ void TextDrawerQt::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextString
QImage image((size.width() + 3) & ~3, (size.height() + 3) & ~3, QImage::Format_ARGB32_Premultiplied);
if (image.isNull()) {
bitmapData.clear();
return;
return false;
}
image.fill(0);
@ -136,6 +136,7 @@ void TextDrawerQt::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextString
} else {
_assert_msg_(false, "Bad TextDrawer format");
}
return true;
}
void TextDrawerQt::DrawString(DrawBuffer &target, std::string_view str, float x, float y, uint32_t color, int align) {

View File

@ -19,7 +19,7 @@ public:
void MeasureString(std::string_view str, float *w, float *h) override;
void MeasureStringRect(std::string_view str, const Bounds &bounds, float *w, float *h, int align = ALIGN_TOPLEFT) override;
void DrawString(DrawBuffer &target, std::string_view str, float x, float y, uint32_t color, int align = ALIGN_TOPLEFT) override;
void DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align = ALIGN_TOPLEFT) override;
bool DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align = ALIGN_TOPLEFT) override;
// Use for housekeeping like throwing out old strings.
void OncePerFrame() override;

View File

@ -416,10 +416,10 @@ void TextDrawerSDL::DrawString(DrawBuffer &target, std::string_view str, float x
}
}
void TextDrawerSDL::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align) {
bool TextDrawerSDL::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align) {
if (str.empty()) {
bitmapData.clear();
return;
return false;
}
// Replace "&&" with "&"
@ -492,6 +492,7 @@ void TextDrawerSDL::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStrin
SDL_UnlockSurface(text);
SDL_FreeSurface(text);
return true;
}
void TextDrawerSDL::OncePerFrame() {

View File

@ -22,7 +22,7 @@ public:
void MeasureString(std::string_view str, float *w, float *h) override;
void MeasureStringRect(std::string_view str, const Bounds &bounds, float *w, float *h, int align = ALIGN_TOPLEFT) override;
void DrawString(DrawBuffer &target, std::string_view str, float x, float y, uint32_t color, int align = ALIGN_TOPLEFT) override;
void DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align = ALIGN_TOPLEFT) override;
bool DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align = ALIGN_TOPLEFT) override;
// Use for housekeeping like throwing out old strings.
void OncePerFrame() override;

View File

@ -312,10 +312,10 @@ void TextDrawerUWP::MeasureStringRect(std::string_view str, const Bounds &bounds
*h = total_h * fontScaleY_ * dpiScale_;
}
void TextDrawerUWP::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align) {
bool TextDrawerUWP::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align) {
if (!str.empty()) {
bitmapData.clear();
return;
return false;
}
std::wstring wstr = ConvertUTF8ToWString(ReplaceAll(ReplaceAll(str, "\n", "\r\n"), "&&", "&"));
@ -328,7 +328,7 @@ void TextDrawerUWP::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStrin
}
if (!format) {
bitmapData.clear();
return;
return false;
}
if (align & ALIGN_HCENTER)
@ -437,6 +437,7 @@ void TextDrawerUWP::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStrin
}
ctx_->mirror_bmp->Unmap();
return true;
}
void TextDrawerUWP::DrawString(DrawBuffer &target, std::string_view str, float x, float y, uint32_t color, int align) {

View File

@ -24,7 +24,7 @@ public:
void MeasureString(std::string_view str, float *w, float *h) override;
void MeasureStringRect(std::string_view str, const Bounds &bounds, float *w, float *h, int align = ALIGN_TOPLEFT) override;
void DrawString(DrawBuffer &target, std::string_view str, float x, float y, uint32_t color, int align = ALIGN_TOPLEFT) override;
void DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align = ALIGN_TOPLEFT) override;
bool DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align = ALIGN_TOPLEFT) override;
// Use for housekeeping like throwing out old strings.
void OncePerFrame() override;

View File

@ -211,10 +211,10 @@ void TextDrawerWin32::MeasureStringRect(std::string_view str, const Bounds &boun
*h = total_h * fontScaleY_ * dpiScale_;
}
void TextDrawerWin32::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align) {
bool TextDrawerWin32::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align) {
if (str.empty()) {
bitmapData.clear();
return;
return false;
}
std::wstring wstr = ConvertUTF8ToWString(ReplaceAll(str, "\n", "\r\n"));
@ -302,6 +302,7 @@ void TextDrawerWin32::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStr
} else {
_assert_msg_(false, "Bad TextDrawer format");
}
return true;
}
void TextDrawerWin32::DrawString(DrawBuffer &target, std::string_view str, float x, float y, uint32_t color, int align) {

View File

@ -24,7 +24,7 @@ public:
void MeasureString(std::string_view str, float *w, float *h) override;
void MeasureStringRect(std::string_view str, const Bounds &bounds, float *w, float *h, int align = ALIGN_TOPLEFT) override;
void DrawString(DrawBuffer &target, std::string_view str, float x, float y, uint32_t color, int align = ALIGN_TOPLEFT) override;
void DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align = ALIGN_TOPLEFT) override;
bool DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align = ALIGN_TOPLEFT) override;
// Use for housekeeping like throwing out old strings.
void OncePerFrame() override;