For PlayN, can someone provide a simple code example showing how to load a font file? - playn

I'm looking for a simple example that loads a ttf file (in my case, Inconsolata.ttf) and creates a text layer.
Is it possible to do this in a platform-agnostic way? From this response here, I get the impression it is not.
I am working on a simple proof-of-concept using the TextDemo sample from the playn-samples showcase as a reference.
I'm presently a little confused on how to register the ttf file. Here's my code:
private void testCustomFont() {
// text
String text = "Hello, Cleveland!";
// load font
String fontName = "Inconsolata";
Font.Style fontStyle = Font.Style.BOLD;
Float fontSize = 24f;
Font myFont = graphics().createFont(fontName, fontStyle, fontSize);
// format text
Integer fontColor = Color.rgb(0, 0, 255);
TextFormat textFormat = new TextFormat().withFont(myFont).withTextColor(fontColor);
// create font image layer
ImageLayer textLayer = graphics().createImageLayer();
TextLayout textLayout = graphics().layoutText(text, textFormat);
CanvasImage textImage = graphics().createImage((int)Math.ceil(textLayout.width()),
(int)Math.ceil(textLayout.height()));
textImage.canvas().drawText(textLayout, 0, 0);
textLayer.setImage(textImage);
// position text layer and add to root layer
textLayer.setTranslation(20, 20);
graphics().rootLayer().add(textLayer);
}
The projects is laid out like so:
/project
├── core
│   └── MyProject.java
└── resources
   └── fonts
└── Inconsolata.ttf
This displays the text but, as expected, not in the desired typeface.

Ideally, I would have like font-loading to have worked like image-loading with the asset manager:
String fontPath = "fonts/Inconsolata.ttf";
Font.Style fontStyle = Font.Style.BOLD;
Float fontSize = 24f;
Font myFont = assetManager().getFont(fontPath, fontStyle, fontSize);
That wasn't possible, so I looked into doing something like this:
private void registerFont() {
if (platformType().equals(Platform.Type.JAVA)) {
Platform platform = Platform.getJavaPlatformApi();
platform.assets().setPathPrefix("com/klenwell/myproject/resources");
platform.graphics().registerFont("Inconsolata", "fonts/Inconsolata.ttf");
}
else if (platformType().equals(Platform.Type.ANDROID)) {
Platform platform = Platform.getAndroidPlatformApi();
platform.assets().setPathPrefix("com/klenwell/myproject/resources");
platform.graphics().registerFont("Inconsolata", "fonts/Inconsolata.ttf");
}
else if (platformType().equals(Platform.Type.HTML)) {
// rely on CSS setting in HTML host file
}
}
But there is no method like getJavaPlatformApi in the core Platform class. So as noted here, "you have to register the font manually on each backend that you intend to use."
Following the example of the TextDemo sample, this is how I would load the font in my example above for the Java and HTML platforms:
Java Platform
Update game class in Java dir:
public class MyProjectJava {
public static void main(String[] args) {
JavaPlatform platform = JavaPlatform.register();
platform.assets().setPathPrefix("com/klenwell/myproject/resources");
platform.graphics().registerFont("Inconsolata", "fonts/Inconsolata.ttf");
PlayN.run(new MyProject());
}
}
HTML Platform
Edit the HTML host file under HTML snapshot directory:
<!DOCTYPE html>
<html>
<head>
<title>MyProject Font Loading Example</title>
<style>
#font-face {
font-family: "Inconsolata";
src: url(myproject/resources/fonts/Inconsolata.ttf);
}
</style>
</head>
<body bgcolor="black">
<script src="myproject/myproject.nocache.js"></script>
</body>
</html>
Android Platform
To Be Announced
iOS Platform
To Be Announced
I haven't yet ventured into Android or iOS compilation yet, so I can't offer an example of those at present.

It seems like your question is covered on the PlayN wiki's custom fonts page.
PlayN supports the use of custom fonts, but such fonts need to be integrated specially for each of the different backends that you wish to use in your game. TrueType (.ttf) fonts are supported by all backends. OpenType (.otf) fonts are supported by some backends (iOS, HTML5, Android).
The main steps seem to be:
Add the font file as an asset.
Register the font separately for each back end using platform.graphics().registerFont().
Create a font object using PlayN.graphics().createFont(), and then use it as normal.

Related

FontAwesome in Xamarin forms UWP

I have a Custom renderer working in Android with Fontawesome.
I was following this guide using font awesome in UWP
With a custom Label type to try to get Fontawesome working in UWP.
public class FontAwesomeLabel: Xamarin.Forms.Label {
public FontAwesomeLabel() {
switch (Device.RuntimePlatform)
{
case Device.UWP:
FontFamily = #"/Assets/FontAwesome.otf#FontAwesome";
break;
}
}
}
The fonts
were loaded as both ttf and otf. I have tried both types.
They Assest fonts have build action "Content"
mainView.Children.Add( new FontAwesomeLabel()
{Text = FaConstPool.FASearch ,FontSize = 40});
public static string FASearch = "\uf002";
Only works on Android and not in UWP
I see a strange box and not the expected Fontawesome icon as for Android.
Any ideas what i have done wrong ?
The solution to the problem turned out to be in UWP, use the correct font family name.
Font Awesome 5 Free Solid
and not just "FontAwesome"
// FontFamily = #"/Assets/FontAwesome.otf#FontAwesome"; // incorrect font family name
FontFamily = #"/Assets/Fonts/FontAwesome.otf#Font Awesome 5 Free Solid";
For anyone interested in details:
I downloaded a font editor to check the internal font name and font family name. I made the mistake of code copying blog posts that used values from similar/older fonts. See image for actual content.
There are 2 types of solution I got to work:
1) A custom control in shared code /.netStandard Common project.
2) a custom renderer
Solution 1: Custom Label
public class FontAwesomeLabel: Xamarin.Forms.Label
{
public FontAwesomeLabel()
{
switch (Device.RuntimePlatform)
{
case Device.UWP:
// make sure the correct font family name is used. Check in a font editor
this.FontFamily = #"/Assets/Fonts/FontAwesome.otf#Font Awesome 5 Free Solid";
break;
}
}
}
Solution 2: Customer renderer on Standard Control
[assembly: ExportRenderer(typeof(Label), typeof(FontAwesomeLabelRenderer))]
namespace Oxando.UWP.CustomRenderers
{
public class FontAwesomeLabelRenderer : LabelRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
if (Control != null)
{
// on UWP be sure use the Font Family name.
// get a font editor and check the name, if it doesnt match UWP wont load it
if (FontAwesomeUtil.CheckIsFA(e.NewElement.Text))
{
Control.FontFamily = new FontFamily("/Assets/Fonts/FontAwesome.otf#Font Awesome 5 Free Solid");
}
}
}
}
internal static class FontAwesomeUtil
{
public static bool CheckIsFA(string text)
{
if (text.Length == 0) return false;
if (text.Length > 1 || text[0] < 0xf000) return false;
return true;
}
}
}
Actual internal names as shown in Font editor
The correct path to add a font on UWP is /Assets/Fonts/FontAwesome.ttf#FontAwesome it seems you have to add the Fonts folder.
Like this:
Additionally you can use Iconize plugin and check this answer:
How can I display a font awesome glyph in XAML/C#

JavaFX - generate compile time error if a class doesn't exist in css

I develop an application in JavaFX. Now i've got the Problem that i would like to generate an error at compile time if a css class, e.g. for a button, which if've set in the code doesn't exist in the corresponding css file.
Example:
main.java
String sCSS = this.getClass().getResource("/main.css").toExternalForm();
scene.getStylesheets().add(sCSS);
Button btn = new Button("Hello JFXWorld...");
btn.getStyleClass().add("button"); // should show compile time error
main.css
.buttonWithWrongName {
-fx-background-color: red; }
My solution would be the following, but I'm looking for advice how I can realize it.
I include an preprocessor or create an new project or something like that which parses the css code and dynamically generates an enum (into a .jar). And this jar i could include into my Project. In the best case ant would trigger the build of the enum automatically if no preprocessor is used.
again an Example:
Css file is the same as above.
{
Do preprocessor stuff for the css file here (parse and create enum) and build it to a jar file.
}
main.java
String sCSS = this.getClass().getResource("/main.css").toExternalForm();
scene.getStylesheets().add(sCSS);
Button btn = new Button("Hello JFXWorld...");
// will throw an compile time error becaus the eMainCSS enum only contains the class ".buttonWithWrongName"
btn.getStyleClass().add(eMainCSS.button.toString());
// works fine
btn.getStyleClass().add(eMainCSS.buttonWithWrongName.toString());
I'm using Eclipse (Neon) and JDK 1.8.0.
I hope there's a solution.
Thank you for the answers.
Best Regards,
Max S.
-- Edit --
Solution:
I've used an Ant WatchTask to watch at all my less files in the project.
If I change something in the less file, ant will run a self written jar file with the file name as parameter. The jar converts the less file to a css file (with less4j) and the css file to a java file (my own parser) which contains the enum.
Note: Youre not allowed to change anything in the enum. Even if you do, after the next changes in the less file, itll be gone.
The result looks like this:
Stylesheet.less:
.button { -fx-stroke-width: (1 + 1); }
#anotherButton { -fx-stroke-width: (1 + 2); }
to Stylesheet.css:
.button { -fx-stroke-width: 2; }
#anotherButton { -fx-stroke-width: 3; }
to Stylesheet.java:
// Auto-generated java file
public enum Stylesheet {
C_BUTTON("button"),
ID_ANOTHERBUTTON("anotherButton");
private final String sValue;
Stylesheet(String sValue) {
this.sValue = sValue;
}
#Override
public String toString() {
return this.sValue;
}
}
Now the compiler will throw an error at the compile time if the class or id which i'm using in javafx doesn`t exist.
Best Regards,
Max S.

Access the Locale in Ruby in CSS files

So i am using CSS, JS and Ruby for a project. Now i have my location set etc, in ruby but i want to access them on my css files. This is to customize views for a particular locale. I have done the following in my controller.
before_filter :set_locale
private
def set_locale
#locale ||= params[:locale] || session[:locale] || I18n.default_locale
I18n.locale = session[:locale] = #locale
end
How do i access this set location in my CSS files? for instance to say that if location is russia then make the height 200 px or something like that.
You can add current locale to html tag as lang.
For example
%html{lang: I18n.locale}
<html lang="en"> or <html lang="ru">
and add specific language style with language prefix
html[lang="en"] {
# for english part
}
html[lang="ru"] {
# for russian part
}
also you can change behavior existing class
.test-title {
html[lang="en"] & {
// specific english style
}
}

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

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;
}
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">
<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.

CSS properties for StyleableTextField htmlText

I've got a StyleableTextField that displays very basic HTML. To format the HTML I currently use a Stylesheet declared in AS3.
This works fine, but is rather inefficient for the designers to edit colors and stuff, so I need to include these tags in my main CSS.
The AS3 CSS declaration looks like this;
_styleSheet = new StyleSheet();
_styleSheet.setStyle("p", {fontSize:'15',color:'#FFFFFF', fontFamily: 'Courier New', fontWeight:'bold'});
This gets assigned to the StyleableTextField using the usual styleSheet = _styleSheet way.
The main CSS file is declared in my main application like this: <fx:Style source="Main.css"/>.
I already have CSS tags for spark components in my CSS, such like the following;
s|TextInput
{
contentBackgroundAlpha: .5;
contentBackgroundColor: #202020;
focusColor: #e1333a;
}
However, I need to address the very instance of StyleableTextfield in the CSS (I've got other's in my app, but only this one displays HTML text).
Has anyone got an idea how to do this?
Working on a mobile project btw.
Flex supports a CSS id selector.
#instanceID
{
...
}
or
ObjectType#instanceID
{
...
}
I haven't been able to test this thoroughly, but it appeared to work for me:
#_objectName
{
p: pstyle;
}
.pstyle
{
fontSize: 15;
...
}

Resources