Tag Archives: Fonts

NativeScript Fonter revisited again (using DuoTone FontAwesome)

In a prior post I discussed using fonts in NativeScript. This morning I saw an issue in the NativeScript github repo about how to use the Font Awesome Duotone fonts.

Since I love puzzles, and I know the NativeScript font system fairly well, and I also own a subscription to the commercial Font Awesome -- I figured I could easily see if I can make it work. Immediately, I had a idea on how to solve the issue.

So I downloaded both the WebFonts and the Desktop fonts. Interestingly, enough the Desktop fonts actually have a warning that links to a post about Duotone fonts and the issues with the desktop... So after I read that post; it basically confirmed my understanding on how this font works and exactly how to make this work inside NativeScript.

So first things first, you need to update your app.css file; you want to add something like this to it:

.fad {
   font-family: fa-duotone-900, Font Awesome 5 Duotone;
   font-weight: 900;
}

.fad-op {
   opacity: .4;
}

Why TWO names for font-family?

If you recall from my prior fonter post; you want to create the rule that has the name of the actual font file without the .TTF or .OTF extension. So since the font folder looks like this:

The last file in the example fonts folder, is fa-duotone-900.ttf; straight from the web download zip file that I downloaded this morning.

So you see the rule is:

   font-family: fa-duotone-900, Font Awesome 5 Duotone;

This allows NativeScript to find the actual file name, in a lot of cases it can use just the filename to work its magic. However on iOS specifically, we want to include the actual internal font name. So double clicking on the font gives us this image under linux.

Under macintosh the title bar also shows the exact same information. So that is why I then typed "Font Awesome 5 Duotone" as the second part of the rule -- this must EXACTLY match. The two names covers all the cases we need, font file name to load it and actual internal font name to reference it later.

The second css rule we just added was fad-op, it is so that we can have some opacity for which ever section of the font we want or need opacity on.

We can do no opacity, solid/solid, and it would look like this:
Notice both parts are solid.

Now if we add opacity to section two; you can see the beak, legs on the bird are slightly transparent; and the acorn body is partially transparent.

Finally if we reverse the opacity to make section one have the opacity it looks like this:

You can also apply any opacity you want like 0.10 looks like this

And you can apply opacity to both sections and it looks like this:

All of them are using the EXACT same colors; just a difference in opacity. The sky is the limit; you are free to color and apply opacity on whatever amounts to each of the two sections.

So how do we do this magic?

Well technically the hard part is already done, that awesome css rule and dropping the font file into the app/fonts folder has 99% of the work done for us. The rest is simple stuff.

So the next thing you need to know is; which duotone icons do you want to use?

So first we need to know what is available for duotone; so we go to the font awesome icon page; and select the duotone filter. Once we have that; we can choose something; so lets look at the crow.

The crow at the top of the page lists this information:

Now at this point we can't really use "fa-crow" just because NativeScript doesn't know what that is; but the two pieces of information we do need to know to make it work is the f520 and the 10f520 these are the unicode values for the two sections of the icon we want.

So our xml needs to look like this:

 
  

This gives us the two characters in the same location on the screen. The first character is using the "fad" css rule; along with the text color blue. The second character is also using the "fad" css rule, and it adds the red text color and the "fad-op" rule for opacity.

Which gives us the duotone bird:

The key item is that you want the characters to print over each other; Gridlayout by default allows you to put multiple items in the same row and column. Since the characters are the same size; they by default will automatically line up and work.

Angular Flavor Issue

Angular's HTML parser has an issue which characters in the upper unicode -- it is great with any unicode value 65535 and below. Which of course if you have seen the first character of each of these duotone values is < 0xffff (65535). However the second character starts in the 0x100000 (1048576) range which is a lot larger than 0xffff. Unfortunately this means that in Angular even though you pass in 0x10f520 you actually get 0xf520 assigned. If you are paying really close attention, this is the same value as the very first code. So in angular you get two labels with the exact same unicode value. So how do we fix this?

Well ultimately; the underlying Angular parser should be fixed -- so if one of you wants to tackle this, track down where in the parser it breaks and push a PR; that would make a lot of people in the Angular community happy! However, since this is not something I am going to tackle and I still want you to be able to use Duotone fonts, I will present an alternate method to how to fix this on Angular.

In Angular; we can do it one of two ways; automagically; or direct assign. I prefer the automagically; so this is the HTML that we have:

<Label col="1" text="&#xf6ae;" class="larger fad "></Label>
<Label col="1" text="&#x10f6ae;" class="larger fad blue fad-op" (loaded)="fixAngularParsingIssue($event)"></Label>

As you can see it is identical to the above NS-Core XML, except I added the (loaded) event. This event fires once in the lifecycle of the Label. And runs my handy dandy "fixAngularParsingIssue" function.

fixAngularParsingIssue(args: any): void {
  let field = args.object;
  let val = field.text.codePointAt(0);

  // Check to see if this is already a valid unicode string above 0xffff.
  if (val > 65535) { return; }

  // We found a character we need to change...
  val = val | 0x100000;
  field.text = String.fromCodePoint(val);
}

The function is straight forward; we grab the current text value; verify it is actually still less than the unicode value we want as the parser could get fixed in a future version. Then we take that value and add our missing 0x100000; and then re-assign the text. Now this function could instead be written to take the actual value you want to assign rather than computing it, but I prefer simplicity as then I can just add this function to all labels that need it and just not think about it.

Angular Directive

I suggested in the issue that someone create a directive; and Pandishpan spent the time and converted my simple code into a directive for Angular making it even easier to use in angular! Thank you for your awesome work! So now, all you have to do is apply the "labelDuoTone" directive to the html, and it handles the rest of the work for you.

You can grab the code for the angular directive in the github issue here.

NativeScript Core demo application

You can download the NativeScript-Core fonter application from the github repo, https://github.com/NathanaelA/fonter

Please note the fa-duotone-900.ttf font is NOT shipped with the demo; you must download it yourself and copy it into the app/fonts folder.

Android (on left) and iOS (on right) looks like this:

Android
iOS


Fonter - Revisited (iOS & Android NativeScript Fonts)

In my prior post on fonter, I walked though how to use the text fonts.  Several things have changed from that point in time; including iOS now auto-registers the fonts.  So I want to revisit the information and cover what needs to happen with NativeScript 1.5.1 and newer.

Setup
font-folderThe folder structure is still the same; you still have to create and use the fonts folder inside your app folder.  All font files are placed in that folder.  Remember this folder is a folder you will have to initially create as it is not created for you by NativeScript when it creates the project for you.

CSS Rules
In the CSS rules, the first font declaration is the one you want to have auto-register.  It is the filename of the actual file without the .ttf.  So if the file name is called JosefinSans-Regular.ttf, then the CSS rule would be:

.JosefinSans {
    font-family:JosefinSans-Regular,Josefin Sans;
}

The second declaration is the actual internal font name.   Android only needs the first declaration; on iOS you might need to have them both.  In most cases iOS does appear now to be able to use the font filename; however I have found in some case it still requires the actual internal font name -- so I recommend you include both since it is simpler and you make sure it will work on iOS and Android.

To figure out the internal font name for iOS the procedure is the same as I outlined before; double click on the font, and then look for the font name in the place I highlighted.

font-titlebar-winfont-titlebar-osx

Using Fonts
The key to using fonts is to use the class or cssclass in the Declaritive XML; so a Label then has attache <Label text="Cool Text" class="JosefinSans"/> would cause the .JosefinSans css rule to be applied to this Label. Which would mean the "Cool Text" would use the Josefin Sans font since that is what we put in the .JosefinSans css rule above.  This the same for all types of fonts, you create the CSS rule with a font-family and then apply it to the Declarative UI element with the cssclass/class on it.

Using Icon Fonts
The new version of Fonter includes not only the three standard text fonts; but I also include three different icon fonts.

  • Google's Material Design
  • Fontastic
  • Material-Design-Iconic

Using Google Material Design Fonts
Lets tackle Google's Material Design first, the thing you need to do is go to to the Material Design website. On this website you can look through the different icons.  So in the second row of icons you should see a picture of the android.  Click on it and you will see at the bottom of the screen a blue bar appear.

GoogleOnce the blue bar appears; click the bottom right corner (highlighted in red) where it says Icon Font.  It will popup a bit more and show the entire grey screen, and you should see towards the bottom of the screen some text that I highlighed in blue that looks like this: <i class="material-icons">&#xE859;</i>.   You see the bolded value?   That is what you need to copy to use this icon in your nativescript application.

Fontawesome
Now we need to go to the Fontawesome website.  In this case it is much simpler, scroll the cheatsheet until you find the icon you want to use.  Then copy the &#x.... number.  For example at the top the fa-500px icon would be &#xf26e;. Pretty simple to find on Fontawesome's site.

Material-Design-Iconic
GMDThe final site we need to go to is the Material Design Iconic website.  Just like the Google site; you need to click on the icon to see the code.  So find the icon you want and click on it.  And you should see something like this.

The text highlighted in red is the important information.  For this icon is say f33b. You prefix that with the &#x and append a semicolon so it will be &#xf33b;.  And that gives you the code for Google-Material-Iconic

Using the Codes
As you can see all three codes use the same format; NativeScript can use the html entity codes inside the XML to display the characters.   So as an example I am going to show you how I use the FontAwesom font; My XML is:

<Label android:text=" &#xf17b; " ios:text=" &#xf179; " cssClass="FontAwesome"/>

As you might notice, on Android I am showing the Android picture, on iOS I'm showing the Apple logo.   My app.css is this:

.FontAwesome {
    font-family: FontAwesome;
}

That is all that is required to make it work.  Proper CSS, XML, and finally the font in the app/fonts folder.

Now their is one other thing that also gets frequently asked, is how do you do the same things from JavaScript like for a bound control.  Well first you still need a control that has the proper CSS applied to it.   To assign a icon character from JavaScript can be done one of two ways.

Option 1:
var myChar = "\uf33b";

Option 2:
var myChar = String.fromCharCode(parseInt('f33b', 16));

In Javascript you can use \uXXXX where the XXXX is the 4 hex characters after the &#x, the \u acts in JavaScript just like the &#x does in XML.  The other options is to use the String.fromCharCode(parseInt('XXXX',16)) and use the same XXXX as the \u would require.  We have to convert the String hexadecimal values into an integer value for this to work.  However if you manually convert it yourself, then you can eliminate the parseInt() code.   So in this case 0xf33b = 62267, so you can do var myChar = String.fromCharCode(62267);

fonter-androidYou can download the full demo application fonter, which has all 6 fonts, all the css and the xml used to display properly on iOS and Android.

Please note; this REQUIRES the latest tns-core-modules; 1.5.1 on iOS and v1.5.0 or greater on Android.   If you are using an earlier version of the core modules then you should read my prior fonter post from how you need to setup the iOS registration.

If you have any other ideas for blog posts; feel free to comment.