In the HTML version of my PlayN game, how can I reliably load fonts so text displays on startup?

StackOverflow https://stackoverflow.com/questions/11602718

  •  22-06-2021
  •  | 
  •  

Question

I'm using v1.3.1 of PlayN. This issue is discussed in the following google groups thread but I'm not sure how to implement the suggestions proposed:

https://groups.google.com/forum/?fromgroups#!topic/playn/kiE2iEYJqM0

Perhaps someone can offer some sample code. Currently I'm following the technique referenced in the HTML link in this answer:

https://stackoverflow.com/a/9116829/1093087

My problem: on the home screen of my game, I display some text using loaded fonts. Works fine in Java version. However, in HTML version, the text doesn't display initially. On the next screen, or if I later return to the home screen, text is properly displayed. So I concluded that it was due to the asynchronous loading of fonts as discussed in the google groups thread.

My remedy was to add a splash screen that displays an image for a few seconds, giving the fonts a chance to load, before redirecting to screen with the text on it. But no matter how long I set the delay, the text is still not displayed.

Here's my HTML file which loads my game and the fonts:

<!DOCTYPE html>
<html>
  <head>
    <title>mygamePlayn</title>
    <!-- fonts -->
    <style>
      @font-face {
        font-family: "DroidSans-Bold";
        src: url(mygame/fonts/DroidSans-Bold.ttf);
      }
      @font-face {
        font-family: "UbuntuMono";
        src: url(mygame/fonts/UbuntuMono-Bold.ttf);
      }
    </style>
  </head>
  <body bgcolor="black">
    <script src="mygame/mygame.nocache.js"></script>
  </body>
</html>

Here's my core Java code that generates the text that's not initially displaying (but works otherwise):

public static CanvasImage generateTextImage(String text, String fontName,
    Integer fontSize, Integer fontColor, Style fontStyle, Integer padding) {
    Font font = graphics().createFont(fontName, fontStyle, fontSize);
    TextFormat fontFormat = new TextFormat().withFont(font).withTextColor(fontColor);

    TextLayout layout = graphics().layoutText(text, fontFormat);
    Integer width = (int) layout.width() + padding * 2;
    Integer height = (int) layout.height() + padding * 2;

    CanvasImage textImage = graphics().createImage(width, height);
    textImage.canvas().drawText(layout, padding, padding);

    return textImage;
}
Was it helpful?

Solution

I think I've finally figured out a solution to my problem. It required using Google WebFont Loader in the following somewhat roundabout fashion:

1) I saved the fonts -- in this case, DroidSans-Bold, Inconsolata, and UbuntuMono-Bold -- in my PlayN project's resources/fonts directory.

2) In resources/css, I add a fonts.css stylesheet where I add the @font-face definitions for my locally saved fonts. My fonts.css file:

@font-face {
    font-family: DroidSans;
    src: url('../fonts/DroidSans-Bold.ttf');
}
@font-face {
    font-family: Inconsolata;
    src: url('../fonts/Inconsolata.ttf');
}
@font-face {
    font-family: UbuntuMono;
    src: url('../fonts/UbuntuMono-Bold.ttf');
}
@font-face {
    font-family: UbuntuMono;
    font-weight: bold;
    src: url('../fonts/UbuntuMono-Bold.ttf');
}

Note: I use the same value for my font-family name as that which I used for the font names in my PlayN code. For example, I load the DroidSans font in my PlayN code like this:

Font font = graphics().createFont("DroidSans", fontStyle, fontSize);

3) I then use Google WebFont Loader in my game's html file (MyGame.html) to load the fonts before the game loads. My MyGame.html file:

<!DOCTYPE html>
<html>
  <head>
    <title>MyGame</title>
    <style>
      body {
        background-color:black;
        color:white;
      }
    </style>

    <!-- Google AJAX Libraries API -->
    <script src="http://www.google.com/jsapi"></script>
    <script>
        google.load("jquery", "1.4.2");
        google.load("webfont", "1");

      WebFontConfig = {
        custom: { families: ['DroidSans', 'UbuntuMono'],
          urls: [ 'mygame/css/fonts.css' ]
        },
        loading: function() {
          console.log("loading fonts");
        },
        fontloading: function(fontFamily, fontDescription) {
          console.log("loading font: " + fontFamily + "-" + fontDescription);
        },
        fontactive: function(fontFamily, fontDescription) {
          console.log(fontFamily + "-" + fontDescription + " is active");        
        },
        fontinactive: function(fontFamily, fontDescription) {
          console.log(fontFamily + "-" + fontDescription + " is INACTIVE");
        },
        active: function() {
          console.log("font-loading complete");
        },
      };

      google.setOnLoadCallback(function() {
        console.log("Google onLoad callback");
        WebFont.load(WebFontConfig);
      });
    </script>

  </head>

  <body>
    <div id="playn-root">
        &nbsp;
        <script src="mygame/mygame.nocache.js"></script>
    </div>
  </body>

</html>

The console logging in the WebFont.load callbacks helped verify that the fonts were successfully loaded before the PlayN game code.

I would have preferred to use WebFont Loader with the fonts served through googleapis.com, but I couldn't figure out how to sync up the references between my PlayN code and the stylesheet. (Now that I look at it, if I didn't want to host the fonts myself, I suppose I could have just used the same url listed in the googleapi.com stylesheets.) Whatever the case, this pattern seems to solve the problem.*

*For Google Chrome. I haven't tested any other browsers.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top