Re: Loading custom fonts in skia

331 views
Skip to first unread message

Shachar Langbeheim

unread,
Jan 3, 2020, 7:58:20 AM1/3/20
to skia-discuss
This might be caused by std::string not behaving exactly like an array of chars. Have you tried using char* instead?
Also, I'm in a similar sitaution, and I use Emscripten's file system API ( https://emscripten.org/docs/api_reference/Filesystem-API.html ) to simulate font files and load typefaces using SkTypeface::MakeFromFile.

On Fri, 3 Jan 2020 at 11:36, Name Unknown <dfaul...@gmail.com> wrote:
 I am working on Webassembly+Skia and since there is no default system fonts in web I was wondering whether there is any way to load custom fonts. If possible how would one achieve it?

I have tried this,
static std::map<std::string, sk_sp<SkTypeface>> fontFiles;
static void addFontFile(std::string fontName, std::string fontFile) {
   std::cout << "Adding font file" << std::endl;
   sk_sp<SkData> data = SkData::MakeFromMalloc(fontFile.c_str(), fontFile.length());
   auto typeface = SkTypeface::MakeFromData(data);
   fontFiles[fontName] = typeface;
   if(typeface == nullptr){
     std::cout << "Typeface is null" << std::endl;
   }
}

Whenever I am sending a .ttc file as std::string. Typeface returned is always null.

--
You received this message because you are subscribed to the Google Groups "skia-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to skia-discuss...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/skia-discuss/afa50165-60b1-4fad-b2c6-d877359019e5%40googlegroups.com.

Kevin Lubick

unread,
Jan 3, 2020, 1:05:42 PM1/3/20
to skia-discuss
CanvasKit loads custom fonts without simulating the filesystem using SkFontMgr_New_Custom_Data. Load your fonts via the web as ArrayBuffers, put them onto your WASM heap and then instantiate that.

If you are using CanvasKit, it looks like this to do so from the javascript side.


On Friday, January 3, 2020 at 7:58:20 AM UTC-5, Shachar Langbeheim wrote:
This might be caused by std::string not behaving exactly like an array of chars. Have you tried using char* instead?
Also, I'm in a similar sitaution, and I use Emscripten's file system API ( https://emscripten.org/docs/api_reference/Filesystem-API.html ) to simulate font files and load typefaces using SkTypeface::MakeFromFile.

On Fri, 3 Jan 2020 at 11:36, Name Unknown <dfau...@gmail.com> wrote:
 I am working on Webassembly+Skia and since there is no default system fonts in web I was wondering whether there is any way to load custom fonts. If possible how would one achieve it?

I have tried this,
static std::map<std::string, sk_sp<SkTypeface>> fontFiles;
static void addFontFile(std::string fontName, std::string fontFile) {
   std::cout << "Adding font file" << std::endl;
   sk_sp<SkData> data = SkData::MakeFromMalloc(fontFile.c_str(), fontFile.length());
   auto typeface = SkTypeface::MakeFromData(data);
   fontFiles[fontName] = typeface;
   if(typeface == nullptr){
     std::cout << "Typeface is null" << std::endl;
   }
}

Whenever I am sending a .ttc file as std::string. Typeface returned is always null.

--
You received this message because you are subscribed to the Google Groups "skia-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to skia-d...@googlegroups.com.

Bharatvaj H

unread,
Jan 5, 2020, 6:39:39 PM1/5/20
to skia-discuss
Didn't try char* but I am able to get a SkTypeface by passing data as uint8_t* from js side by allocating in heap as mentioned by Kevin Lubick


On Friday, January 3, 2020 at 6:28:20 PM UTC+5:30, Shachar Langbeheim wrote:
This might be caused by std::string not behaving exactly like an array of chars. Have you tried using char* instead?
Also, I'm in a similar sitaution, and I use Emscripten's file system API ( https://emscripten.org/docs/api_reference/Filesystem-API.html ) to simulate font files and load typefaces using SkTypeface::MakeFromFile.

On Fri, 3 Jan 2020 at 11:36, Name Unknown <dfau...@gmail.com> wrote:
 I am working on Webassembly+Skia and since there is no default system fonts in web I was wondering whether there is any way to load custom fonts. If possible how would one achieve it?

I have tried this,
static std::map<std::string, sk_sp<SkTypeface>> fontFiles;
static void addFontFile(std::string fontName, std::string fontFile) {
   std::cout << "Adding font file" << std::endl;
   sk_sp<SkData> data = SkData::MakeFromMalloc(fontFile.c_str(), fontFile.length());
   auto typeface = SkTypeface::MakeFromData(data);
   fontFiles[fontName] = typeface;
   if(typeface == nullptr){
     std::cout << "Typeface is null" << std::endl;
   }
}

Whenever I am sending a .ttc file as std::string. Typeface returned is always null.

--
You received this message because you are subscribed to the Google Groups "skia-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to skia-d...@googlegroups.com.

Bharatvaj H

unread,
Jan 5, 2020, 6:44:56 PM1/5/20
to skia-discuss
This works for getting a SkTypeface. But SkFontMgr_New_Custom_Data returns a sk_sp<SkFontMgr> which is not nullptr and has no fonts either.

I am getting this error,
---- failed to open <0> as a font

Kevin Lubick

unread,
Jan 7, 2020, 6:54:52 AM1/7/20
to skia-discuss
Here's the C++ code that CanvasKit calls to instantiate the SkFontMgr: https://github.com/google/skia/blob/master/modules/canvaskit/canvaskit_bindings.cpp#L1112

Are you sure you are setting the sizes of the array buffers correctly? The 2d array of font data can be tricky to do right from the JS side, here's how CanvasKit does it: https://github.com/google/skia/blob/master/modules/canvaskit/font.js#L51

Bharatvaj H

unread,
Jan 8, 2020, 5:09:36 AM1/8/20
to skia-discuss
I tried it. It lets me load .ttf files but not .ttc and .otf.
When loading .ttc or .otf files, it shows either,
index is out of bounds, originating from SkTypeface_FreeType::Scanner::scanFont method
or
---- failed to open <0> <0> as a font
and fails to print family names when fm.dumpFamilies() is executed

This is not the case for .ttf files. fm.dumFamilies() prints the .ttf fontFamily as expected without any warnings or errors

Kevin Lubick

unread,
Jan 13, 2020, 9:44:23 AM1/13/20
to skia-discuss
We can take a look.

kjlu...@google.com

unread,
Jan 27, 2020, 10:09:20 AM1/27/20
to skia-discuss
Sorry for the delay - I just filed a bug here to better keep track of this: https://bugs.chromium.org/p/skia/issues/detail?id=9829

Bharatvaj H

unread,
Jan 28, 2020, 12:29:58 AM1/28/20
to skia-discuss
Great!

kjlu...@google.com

unread,
Jan 29, 2020, 7:42:46 AM1/29/20
to skia-discuss
I just pushed a fix to ToT - if you are still having trouble with fonts after compiling the latest and greatest, could you attach them to that bug? We explicitly do not support Type 1 fonts and don't yet support .woff or .woff2 fonts.

On Tuesday, January 28, 2020 at 12:29:58 AM UTC-5 Bharatvaj H wrote:
Great!

Bharatvaj H

unread,
Feb 3, 2020, 12:11:03 AM2/3/20
to skia-discuss
Hi!, Thanks for the update, with the latest skia, .otf files are working. But .ttf fonts are throwing `index of ouf bounds` error. I have posted the same in the bug tracker

Sowmyyy Reanz

unread,
Oct 9, 2024, 9:04:01 AMOct 9
to skia-discuss
Team, i am trying to use web fonts(.ttf) to render the text using TextStyle , fontcollection and paragraphbuilder
  auto fontCollection = sk_make_sp<skia::textlayout::FontCollection>();
sk_sp<SkFontMgr> customFontMgr = SkFontMgr::RefDefault();
fontCollection->setDefaultFontManager(customFontMgr);
this will have default system fonts and setting those system fonts as family to textstyle it works, 
i have a typeface of custom font created from custom font skdata and set it to textstyle typeface like
textStyle.setTypeface(g_customTypeface);
it does not work , do i need to import my custom fonts to my font collection or how to handle this?
i will attach the code what am trying ,

skia::textlayout::TextStyle textStyle;
textStyle.setFontSize(70);
textStyle.setForegroundColor(paint);
if (g_customTypeface != nullptr) {
textStyle.setTypeface(g_customTypeface);
}
SkTypeface *typeface = textStyle.getTypeface();

if (typeface) {
SkString fontFamilyName;
typeface->getFamilyName(&fontFamilyName);
 textStyle.setFontFamilies({fontFamilyName});
skia::textlayout::ParagraphStyle paraStyle;
paraStyle.setTextAlign(skia::textlayout::TextAlign::kLeft);
auto fontCollection = sk_make_sp<skia::textlayout::FontCollection>();
sk_sp<SkFontMgr> customFontMgr = SkFontMgr::RefDefault();
fontCollection->setDefaultFontManager(customFontMgr);
auto builder =
skia::textlayout::ParagraphBuilderImpl::make(paraStyle, fontCollection);
builder->pushStyle(textStyle);
std::string text = "skia cpp";
builder->addText(text.c_str(), text.length());
auto para = builder->Build();
auto paraWidth = para.get()->getMaxIntrinsicWidth();
para.get()->layout(200);
auto rect = SkRect();
rect.fTop = 300;
rect.fBottom = 800;
rect.fLeft = 200;
rect.fRight = 700;
canvas->save();
canvas->clipRect(rect,true);
SkPaint paint1 = SkPaint();
paint1.setColor(SK_ColorWHITE);

canvas->drawPaint(paint1);
para.get()->paint(canvas, 250, 300);
canvas->restore();

jlav...@google.com

unread,
Oct 9, 2024, 9:13:47 AMOct 9
to skia-discuss
There is nothing in the code suggesting that your customFontMgr contains g_customTypeface.
How do you get this g_customTypeface?
The line
textStyle.setTypeface(g_customTypeface);
does not do anything since it's the fontCollection (and fontManager) decide what font to use
based on on the textStyle.fontFamilies list and the other textStyle parameters.

Sowmyyy Reanz

unread,
Oct 10, 2024, 9:02:59 AMOct 10
to skia-discuss
I create a sktypeface and stored in a global variable in g_customTypeface
like,static sk_sp<SkTypeface> g_customTypeface;
JNIEXPORT void JNICALL
Java_com_example_skiaandroidjava_NativeSkiaMethods_sendFontData(JNIEnv *env, jclass thiz, jbyteArray fontData) {
jbyte* buffer = env->GetByteArrayElements(fontData, NULL);
jsize length = env->GetArrayLength(fontData);

sk_sp<SkData> skFontData = SkData::MakeWithoutCopy(buffer, length);
g_customTypeface = SkTypeface::MakeFromData(skFontData);

env->ReleaseByteArrayElements(fontData, buffer, JNI_ABORT);

if (g_customTypeface) {
__android_log_print(ANDROID_LOG_INFO, "skialibrary font", " Custom font loaded successfully");
} else {
__android_log_print(ANDROID_LOG_INFO, "skialibrary font", " Custom font loaded un success");
}
}
fontData - received from android to JNI wrapper class and using that i create a custom typeface;
fontdata is Bilbo web font , i load it and passed to JNI like,
public void loadCustomFont(String fontFileName) throws IOException {
try (InputStream inputStream = selfContext.getAssets().open("Fonts/" + fontFileName)) {
NativeSkiaMethods.sendFontData(inputStream.readAllBytes());// Java 9 and above
} catch (IOException e) {
throw new IOException("Error reading font file: " + fontFileName, e);
}
} 

after setting custom font to textstyle like
if (g_customTypeface != nullptr) {
textStyle.setTypeface(g_customTypeface);
}
SkTypeface *typeface = textStyle.getTypeface();

if (typeface) {
SkString fontFamilyName;
typeface->getFamilyName(&fontFamilyName);
}
loading this fontFamilyName gives the Bilbo name.
yes font collection and font manager decides what font to use , which has only system fonts
how to handle the custom fonts to be applied to  textstyle , paragraphbuilder using font manager

Sowmyyy Reanz

unread,
Oct 10, 2024, 9:03:05 AMOct 10
to skia-discuss
custom font manager , i tried like
class CustomFontMgr : public SkFontMgr {
public:
 SkTypeface* onMatchFamilyStyle(const char familyName[],
const SkFontStyle& style) const override {
if (strcmp(familyName, "Bilbo") == 0) {
return g_customTypeface.get();  
}
return SkFontMgr::onMatchFamilyStyle(familyName, style);  
}
}
but creating this custom manager returns null not created 

so kindly help me to handle custom font for rendering text using Textstyle , fontcollection and paragraph builder(skparagraph)
On Wednesday, October 9, 2024 at 6:43:47 PM UTC+5:30 jlav...@google.com wrote:
Reply all
Reply to author
Forward
0 new messages