Skip to content

Commit

Permalink
Fix SkiaFontManager with proper default font & SkFont wrapper (new Sk…
Browse files Browse the repository at this point in the history
…iaFont)

The text handling API still needs a lot of work (e.g. a way to publish
SkTextBlobs and iterate runs/chars, paint each char with a different
SkPaint, etc.)
  • Loading branch information
dacap committed Feb 9, 2024
1 parent 8d2b01c commit b7af11a
Show file tree
Hide file tree
Showing 14 changed files with 348 additions and 106 deletions.
10 changes: 8 additions & 2 deletions cmake/FindSkia.cmake
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (C) 2019-2022 Igara Studio S.A.
# Copyright (C) 2019-2024 Igara Studio S.A.
#
# This file is released under the terms of the MIT license.
# Read LICENSE.txt for more information.
Expand Down Expand Up @@ -36,7 +36,8 @@ else()
find_library(SKIA_OPENGL_LIBRARY opengl NAMES GL)
endif()

# SkShaper module + freetype + harfbuzz + zlib
# Skia modules
find_library(SKUNICODE_LIBRARY skunicode PATH "${SKIA_LIBRARY_DIR}")
find_library(SKSHAPER_LIBRARY skshaper PATH "${SKIA_LIBRARY_DIR}")

# Check that Skia is compiled for the same CPU architecture
Expand Down Expand Up @@ -223,5 +224,10 @@ if(UNIX AND NOT APPLE)
${FONTCONFIG_LIBRARY})
endif()

add_library(skunicode INTERFACE)
target_link_libraries(skunicode INTERFACE ${SKUNICODE_LIBRARY})

add_library(skshaper INTERFACE)
target_link_libraries(skshaper INTERFACE ${SKSHAPER_LIBRARY})
target_compile_definitions(skshaper INTERFACE
SK_SHAPER_HARFBUZZ_AVAILABLE)
29 changes: 14 additions & 15 deletions examples/complextextlayout.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// LAF Library
// Copyright (c) 2019-2022 Igara Studio S.A.
// Copyright (c) 2019-2024 Igara Studio S.A.
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
Expand Down Expand Up @@ -48,22 +48,22 @@ void draw_window(os::Window* window,

p.color(gfx::rgba(255, 255, 255));

const wchar_t* lines[] = { L"English",
L"Русский язык", // Russian
L"汉语", // Simplified Chinese
L"日本語", // Japanese
L"한국어", // Korean
L"العَرَبِيَّة‎" }; // Arabic
const char* lines[] = { "English",
"Español",
"Русский язык", // Russian
"汉语", // Simplified Chinese
"日本語", // Japanese
"한국어", // Korean
"العَرَبِيَّة‎", // Arabic
"👍❤️😂☺️😯😢😡" }; // Emojis

MyDrawTextDelegate delegate(mousePos);
gfx::Point pos(0, 0);
for (auto line : lines) {
std::string s = base::to_utf8(line);
os::draw_text(
backSurface.get(), font.get(), s,
gfx::rgba(255, 255, 255), gfx::ColorNone,
pos.x, pos.y,
&delegate);
std::string s = line;
os::draw_text_with_shaper(
backSurface.get(), font, s,
pos, &p, os::TextAlign::Left, &delegate);

pos.y += font->height() + 4;
}
Expand All @@ -85,8 +85,7 @@ int app_main(int argc, char* argv[])

os::WindowRef window = system->makeWindow(400, 300);

// TODO use new fonts (SkFont wrappers with system->fontManager())
font = os::instance()->loadTrueTypeFont("/Library/Fonts/Arial Unicode.ttf", 32);
font = system->fontManager()->defaultFont(32);
if (!font) {
std::printf("Font not found\n");
return 1;
Expand Down
9 changes: 6 additions & 3 deletions examples/helloworld.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,18 @@ void draw_window(os::Window* window)
p.style(os::Paint::Fill);
surface->drawRect(rc, p);

os::FontRef font = os::instance()->fontManager()->defaultFont(32);

p.color(gfx::rgba(255, 0, 0)); surface->drawLine(0 , 0, rc.w, rc.h, p);
p.color(gfx::rgba(0, 128, 0)); surface->drawLine(rc.w/2, 0, rc.w/2, rc.h, p);
p.color(gfx::rgba(0, 0, 255)); surface->drawLine(rc.w , 0, 0, rc.h, p);
p.color(gfx::rgba(255, 255, 255));
os::draw_text(surface, nullptr, "Hello World", rc.center(),
&p, os::TextAlign::Center);
os::draw_text(surface, font, "Hello World",
rc.center(), &p, os::TextAlign::Center);

if (window->isGpuAccelerated())
os::draw_text(surface, nullptr, "(GPU)", rc.center()+gfx::Point(0, 24),
os::draw_text(surface, font, "(GPU)",
rc.center()+gfx::Point(0, 40),
&p, os::TextAlign::Center);

// Invalidates the whole window to show it on the screen.
Expand Down
3 changes: 2 additions & 1 deletion examples/listfonts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ int app_main(int argc, char* argv[])
if (argc > 1) {
for (int i=1; i<argc; ++i) {
std::string name = argv[i];
std::printf("%s\n", name.c_str());
std::printf("Font %s:\n", name.c_str());
auto set = fm->matchFamily(name);
if (!set) {
std::printf("Font family '%s' not found\n", argv[i]);
Expand All @@ -92,6 +92,7 @@ int app_main(int argc, char* argv[])
}
// Print all font families
else {
std::printf("Font families (%d):\n", fm->countFamilies());
const int n = fm->countFamilies();
for (int i=0; i<n; ++i) {
std::string name = fm->familyName(i);
Expand Down
6 changes: 4 additions & 2 deletions os/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# LAF OS
# Copyright (C) 2018-2023 Igara Studio S.A.
# Copyright (C) 2018-2024 Igara Studio S.A.
# Copyright (C) 2012-2018 David Capello

######################################################################
Expand Down Expand Up @@ -62,6 +62,8 @@ if(LAF_BACKEND STREQUAL "skia")
skia/skia_color_space.cpp
skia/skia_draw_text.cpp
skia/skia_draw_text_with_shaper.cpp
skia/skia_font.cpp
skia/skia_font_manager.cpp
skia/skia_gl.cpp
skia/skia_surface.cpp
skia/skia_window.cpp)
Expand Down Expand Up @@ -149,7 +151,7 @@ endif()
target_link_libraries(laf-os ${LAF_OS_PLATFORM_LIBS})

if(LAF_BACKEND STREQUAL "skia")
target_link_libraries(laf-os skia skshaper)
target_link_libraries(laf-os skia skunicode skshaper)
endif()

set(_LAF_BACKEND_INITIAL_LINK_FLAGS "")
Expand Down
5 changes: 3 additions & 2 deletions os/draw_text.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// LAF OS Library
// Copyright (C) 2020-2022 Igara Studio S.A.
// Copyright (C) 2020-2024 Igara Studio S.A.
// Copyright (C) 2017 David Capello
//
// This file is released under the terms of the MIT license.
Expand All @@ -20,7 +20,8 @@

namespace os {

gfx::Rect draw_text(Surface* surface, Font* font,
gfx::Rect draw_text(Surface* surface,
Font* font,
const std::string& text,
gfx::Color fg, gfx::Color bg,
int x, int y,
Expand Down
16 changes: 10 additions & 6 deletions os/draw_text.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// LAF OS Library
// Copyright (c) 2022 Igara Studio S.A.
// Copyright (c) 2022-2024 Igara Studio S.A.
// Copyright (C) 2017 David Capello
//
// This file is released under the terms of the MIT license.
Expand All @@ -12,6 +12,7 @@
#include "base/string.h"
#include "gfx/color.h"
#include "gfx/fwd.h"
#include "os/ref.h"

namespace os {

Expand Down Expand Up @@ -49,16 +50,18 @@ namespace os {
// it). It uses FreeType2 library and harfbuzz. Doesn't support RTL
// (right-to-left) languages.
gfx::Rect draw_text(
Surface* surface, Font* font,
Surface* surface,
Font* font,
const std::string& text,
gfx::Color fg, gfx::Color bg,
int x, int y,
DrawTextDelegate* delegate);

// Uses SkTextUtils::Draw() to draw text (doesn't depend on harfbuzz
// or big dependencies, useful to print English text only).
// Uses Skia's SkTextUtils::Draw() to draw text (doesn't depend on
// harfbuzz or big dependencies, useful to print English text only).
void draw_text(
Surface* surface, Font* font,
Surface* surface,
Ref<Font> font,
const std::string& text,
const gfx::Point& pos,
const Paint* paint = nullptr,
Expand All @@ -70,7 +73,8 @@ namespace os {
// you are not going to translate your app to non-English languages
// (prefer os::draw_text() when possible).
void draw_text_with_shaper(
Surface* surface, Font* font,
Surface* surface,
Ref<Font> font,
const std::string& text,
const gfx::Point& pos,
const Paint* paint = nullptr,
Expand Down
4 changes: 3 additions & 1 deletion os/font_manager.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// LAF OS Library
// Copyright (c) 2019-2020 Igara Studio S.A.
// Copyright (c) 2019-2024 Igara Studio S.A.
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
Expand All @@ -8,6 +8,7 @@
#define OS_FONT_MANAGER_H_INCLUDED
#pragma once

#include "os/font.h"
#include "os/font_style_set.h"
#include "os/ref.h"

Expand All @@ -19,6 +20,7 @@ namespace os {
protected:
virtual ~FontManager() { }
public:
virtual Ref<Font> defaultFont(float size = 12) const = 0;
virtual int countFamilies() const = 0;
virtual std::string familyName(int index) const = 0;
virtual Ref<FontStyleSet> familyStyleSet(int index) const = 0;
Expand Down
18 changes: 14 additions & 4 deletions os/skia/skia_draw_text.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// LAF OS Library
// Copyright (C) 2019 Igara Studio S.A.
// Copyright (C) 2019-2024 Igara Studio S.A.
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
Expand All @@ -9,9 +9,12 @@
#endif

#include "os/draw_text.h"
#include "os/font_manager.h"
#include "os/paint.h"
#include "os/skia/skia_font.h"
#include "os/skia/skia_helpers.h"
#include "os/skia/skia_surface.h"
#include "os/system.h"

#include "include/core/SkTextBlob.h"
#include "include/utils/SkTextUtils.h"
Expand All @@ -20,21 +23,28 @@
namespace os {

void draw_text(
Surface* surface, Font* font,
Surface* surface,
Ref<Font> font,
const std::string& text,
const gfx::Point& pos,
const Paint* paint,
const TextAlign textAlign,
DrawTextDelegate* delegate)
{
SkFont skFont; // wrap SkFont with os::Font
if (!font)
font = os::instance()->fontManager()->defaultFont();

if (font->type() != FontType::Native)
return;

SkTextUtils::Draw(
&static_cast<SkiaSurface*>(surface)->canvas(),
text.c_str(), text.size(),
SkTextEncoding::kUTF8,
SkIntToScalar(pos.x),
SkIntToScalar(pos.y),
skFont, (paint ? paint->skPaint(): SkPaint()),
static_cast<SkiaFont*>(font.get())->skFont(),
(paint ? paint->skPaint(): SkPaint()),
(SkTextUtils::Align)textAlign);
}

Expand Down
37 changes: 28 additions & 9 deletions os/skia/skia_draw_text_with_shaper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,46 +10,65 @@

#include "os/draw_text.h"
#include "os/paint.h"
#include "os/skia/skia_font.h"
#include "os/skia/skia_font_manager.h"
#include "os/skia/skia_helpers.h"
#include "os/skia/skia_surface.h"
#include "os/system.h"

#include "include/core/SkCanvas.h"
#include "include/core/SkTextBlob.h"
#include "include/utils/SkTextUtils.h"
#include "modules/skshaper/include/SkShaper.h"

#include "include/core/SkCanvas.h"

#include <cfloat>

namespace os {

void draw_text_with_shaper(
Surface* surface, Font* font,
Surface* surface,
FontRef font,
const std::string& text,
const gfx::Point& pos,
const Paint* paint,
const TextAlign textAlign,
DrawTextDelegate* delegate)
{
SkFont skFont;
auto fontMgr = static_cast<SkiaFontManager*>(os::instance()->fontManager());
if (!fontMgr)
return;

if (!font)
font = fontMgr->defaultFont(12);

if (font->type() != FontType::Native)
return;

SkFont skFont = static_cast<SkiaFont*>(font.get())->skFont();
sk_sp<SkTextBlob> textBlob;
auto shaper = SkShaper::Make();
if (shaper) {
if (auto shaper = SkShaper::Make(fontMgr->skFontMgr())) {
SkTextBlobBuilderRunHandler builder(text.c_str(), { 0, 0 });
shaper->shape(text.c_str(), text.size(), skFont, true, FLT_MAX, &builder);
shaper->shape(
text.c_str(), text.size(),
skFont,
true,
FLT_MAX,
&builder);
textBlob = builder.makeBlob();
}
else {
textBlob = SkTextBlob::MakeFromText(text.c_str(), text.size(), skFont, SkTextEncoding::kUTF8);
textBlob = SkTextBlob::MakeFromText(text.c_str(), text.size(),
skFont, SkTextEncoding::kUTF8);
}

if (textBlob)
if (textBlob) {
static_cast<SkiaSurface*>(surface)->canvas()
.drawTextBlob(
textBlob,
SkIntToScalar(pos.x),
SkIntToScalar(pos.y),
(paint ? paint->skPaint(): SkPaint()));
}
}

} // namespace os
Loading

0 comments on commit b7af11a

Please sign in to comment.