How to draw the Glyph on canvas from .ttf file [duplicate] - android

This question already has answers here:
Extracting glyph-path information from ttf files
(3 answers)
How to use kerning pairs extracted from a TTF file to correctly show glyphs as Path2D in Java?
(2 answers)
Closed 2 years ago.
Android does not support the Urdu Nastaliq font properly (the word is broken up and the exact shape (Nastaliq) of the word is not made).
I have used Typeface for this as
TextView tx=(TextView)this.findViewById(R.id.tt);
tx.setTypeface(Typeface.createFromAsset(getAssets(),"TTF font Path"));
I am able to get the exact formating of the Nastaliq Font in java using the AWT package like
Font font = Font.createFont(Font.TRUETYPE_FONT, new File("Path for ttf file"));
Font dynamicFont32Pt = font.deriveFont (32f);
JLabel textLabel = new JLabel(textMessage);
textLabel.setFont(dynamicFont32Pt);
But Android also does not support the AWT Package Properly (java.awt.Font.createFont() and deriveFont()), So we decided to make a render engine for the .ttf file for Urdu.
Now my question is-
Can we get the urdu Font (properly) rendering in Android without needing a Rendering Engine?
If not, then
How can I read the .ttf file (All tables like 'glyp', 'head') in Android?
How can I draw a TTF font, that is, a vector font that does not require a PNG?

The answer from the Extracting glyph-path information from ttf files question can interest you: basically, it points to the Batik library which has code to parse a TTF file in Java (to transform it to SVG).

You should check my question How to use kerning pairs extracted from a TTF file to correctly show glyphs as Path2D in Java?. Instead of Batik, I recommend using Apache FOP. It is simple and easy to use. The advantage is that you read the font only once and you embed the Glyphs into your app. However, Apache FOP only works for TTF, not for OTF (it is possible too, but I am still working on that). Batik uses Java AWT to render strings. The problem is that your app needs to read the font file each time it runs. In the method I am suggesting you can use an embedded mini vectorized font, or you can use an embedded vectorized string for small texts. The problem of this approach is that widths only work properly in painting time. To be able to use the glyphs you recover from the font file using awt, you need to read the kerning pairs and widths directly from the file to be able to display the text properly. This is explained in the answers to the question. Also check the question How to read kerning pairs table from TTF file in Android?. The advantage of using vectorized glyphs is that your app is independent of font files and operating system.
You can see that I am using this system on Windows, but you can do the same for Android. Fonts are easier to deal with on Windows and most fonts there are TTF. In reality you can develop your vectorized font on Windows and just use the resulting class in Android. That's the beauty of this method. I generate my fonts using println and copying and pasting it in a new class file. I don't even bother in writing a file.

Related

Accessing font data on Android

I have an OpenGL renderer that uses FreeType to render text. I would like to be able to use system fonts packaged with Android. There is a way on iOS to get the ttf font data for system fonts (see accepted answer here: On iOS, can I access the system-provided font's TTF file). Is there something equivalent on Android? Is there an API for getting the source file for a system font based on the font name, ideally without having to do any guesswork about where certain system files are stored?

Custom font for EmojiCompat

I have a small problem regarding the EmojiCompat library which was introduced some weeks ago.
There is a group of people (including me) who don't quite like the new Emoji style, Google has introduced with Oreo.
As I like the good old blob emojis, I recently started updating this emoji font.
Now my problem:
The Android developer page shows that there are two ways of using EmojiCompat.
The first one is using downloadable fonts and the second one is using this bundled emoji font which is based on loading font assets.
I already have a working implementation of EmojiCompatConfig which allows me to load any font I have in my assets-folder and it works with the font provided in the bundled configuration but not with my own font.
The section "Library-Components" [I don't have enough/any reputation, so I can't provide a link to this section...] says the original Noto-Emoji font (which my font is actually based on) is modified in some way (i.e. moving the emojis into another area and adding some "Extra emoji metadata" which isn't really specified anywhere in the documentation).
I already tried to look for some differences using the ttx tool provided by fonttools.
It looks like these modifications are the only ones made.
The modified version differs in both the meta-table not present in the default noto font and in the actual positions the emoji glyphs have - probably because they movede the emojis to the private area.
Does anyone know how to recreate these modifications so I am able to use my own emoji font instead of that new one?
I already tried to search for this issue but I didn't find anything that could help me.
There has already been another post regarding whether or not it would be possible to use the iOS emojis using the downloadable font approach but I don't think these questions are the same...
The script to modify an existing CBDT/CBLC emoji font can be found here: https://android.googlesource.com/platform/external/noto-fonts/+/android-8.0.0_r17/emoji-compat/createfont.py
The "unicode path" that needs to be passed to the script should point to this data: https://android.googlesource.com/platform/external/unicode/+/android-8.0.0_r17

How does the Apple color emoji font work, and is there an Android version?

I saw that on iPhone there is a truetype font called Apple Color Emoji. It contains the emoticons that exist on iPhones which can be used in any application.
I wonder:
How is this font displayed in multicolor?! Truetype fonts can only include black and white glyphs.
Can this font, or one like it, be used on Android phones?
Apple is using a proprietary extension to the OpenType standard. Basically, they just store pre-rasterized color PNGs in a proprietary extension "block" within the TTF file (reference, corroboration).
The only reason this works is because they also provide the full stack between that font extension and the screen (font rasterization, system graphics library, text rendering widgets). There's no standardized way to accomplish this across all platforms/libraries.
The font uses embedded PNGs and they are stored in a sbix table.
Apple Color Emoji cannot be used in Android, but a Google CBLC/CBDT formatted font can.
There are four methods for implementing color in Open Type fonts right now:
Apple's SBIX - Embedded PNGs
Google's CBLC+CBDT - Embedded PNGs
Microsoft's COLR+CPAL - Colored glyphs
Adobe/Mozilla/W3C's SVG+CPAL - SVG in OpenType
The complete list of OpenType tables.
You can disassemble/reassemble the font using ttx from FontTools(pypi, github) for more details.

Android: Find out which font file is appropriate for the characters I want to display

I am maintaining an Android app that people use to display strings in various exotic languages like Tibetan or old Greek. Because Android devices come with very few fonts, users can put font files on the SD card, and the app will use them.
QUESTION: Given a string, how can I automatically decide which font file is the most appropriate, so that this string appears without characters being replaced with squares/boxes?
Notes:
Each string is in one language.
Strings are displayed in a WebView.
Custom fonts work, the only problem is deciding which font file to use.
Instead of a single font, it could provide a list of fonts that are acceptable for that string.
Unnecessary context, for the curious: I am trying to develop this feature:
http://code.google.com/p/ankidroid/issues/detail?id=779
UPDATE: I ended up creating the Antisquare Open Source library based on Mostafa's idea.
It has a getSuitableFonts method which is blazingly fast.
Android by itself does not provide enough for such a task. Loading and rendering fonts in Android happens in Skia, which is written in C. Skia detects if a character can't be found in a font and falls back to another font for such characters (not the whole string). That's how Japanese, Hebrew, or Arabic text is shown in Android and that's exactly why these scripts don't have bold face! (Their font is selected through fallback and fallback only selects one font file.)
Unfortunately, this mechanism is not provided in APIs and you have to build similar thing on your own. It seems complicated, but is easier than it looks. All you have to do is:
Prepare lists of characters available in each font file.
For every string find the font that has more characters of the string.
Getting list of characters in each font
You don't have to do this on-the-fly in your Android app. You can prepare the list of characters in each font and put these lists in your app. I say that because this is way easier with tools that may not be available in Android. I would do that through Python scripting in a font app (most serious font tools have awesome Python scripting environments), but these apps are expensive and are for serious type designers. Since you're an Android developer, I recommend using sfntly, a library in Java and C++. Doing what you need (getting a list of Unicode characters available in a font file) is easy with sfntly. This sample works with CMap tables (tables that hold character to glyph mapping) and should be a good starting point for you.
Now the interesting part is that snftly is in Java and you may be able to include that in your Android app and do everything automatically. That's awesome by I recommend you start by getting familiar with snftly.
Selecting the font
After the previous part you'll have a list of Unicode character for every font, and based on these lists selecting the font file that provides most characters of every string is trivial.

Japanese characters looking like Chinese on Android

PREAMBLE: since API 17 (Android 4.2), there's a method TextView.setTextLocale() that explicitly solves this problem for TextViews and derived classes. Assign a Japanese locale (Locale.JAPAN), and Unihan characters will look Japanese.
I have an application on Android that displays Japanese text in WebViews and TextViews. There are some Chinese characters (kanji) that look, by convention, differently in China and in Japan, but share the same Unicode codepoint. Normally, the browser would rely upon the lang tag to choose the correct glyph. On Android, they all default to their Chinese shapes, and I want Japanese shapes.
The problem is well explained in this article. This article also serves as a perfect illustration of the problem - when watched on Android (up to 2.2), the characters in the "Examples of language-dependent characters" all look the same, and Chinese.
Using the lang="ja" attribute does not help. Switching the whole system locale to Japanese does not help either.
I'm wondering about Android phones that are sold in Japan. Do characters like 直, 今, 化 look Chinese-style on those, too? I'm assuming not.
So the questions are: are there official localized images of Android out there? Can I get one to run on the emulator? Is the DroidSansFallback font still the only CJK-enabled font on those? And if it is, is it the same as on the vanilla USA Android?
I'm kind of hoping that the Japanese glyphs are hidden somewhere deep in the font (Unicode private area or something). If so, I could leverage them...
EDIT: located DroidSansJapanese.ttf, installed it on the emulator by copying into /system/fonts, restarted. It made no difference on the look of the Unihan article. Even the hint area of the Japanese text input (which should know better) displays as if Chinese.
How do I know the typeface name of the DroidSansJapanese.ttf? I have a feeling it's still Droid Sans, same as in the built-in DroidSansFallback font. But if they contain the same typeface, what governs which one should take precedence? One would think - system locale, but apparently not. Fonts in Android are installed just by copying, right?
There are fonts with full Japanese support. I've heard some people talking about DroidSansJapanese.tff and TakaoPGothic.
Found a somewhat cludgey solution.
The DroidSansJapanese.ttf font exists and is available for download, for example, here. I downloaded it, renamed it to DroidSansJapanese.mp3 to avoid the 1MB compressed asset limit, and placed it under assets/web. I then introduced the following CSS statement:
#font-face
{
font-family: "DroidJP";
src:url('DroidSansJapanese.mp3')
}
Then I added 'DroidJP' to the font-family of every relevant CSS style. The way I load my HTML, the assets/web folder is already designated as the base for loading linked content.
Upon careful examination, I found several places in the app where Japanese was in TextViews. For those, I've loaded the typeface like this:
Typeface s_JFont =
Typeface.createFromAsset(Ctxt.getAssets(), "web/DroidSansJapanese.mp3");
and called setTypeface() on every relevant TextView. Now for PROFIT!
This expanded my APK by about 1 MB. There was an alternative way, where I'd store the font in the assets in compressed form - that'd save me about 500 KB of APK size, but then I'd have to expand it to phone memory on the first run, worry about data folder path, and lose compatibility with Android 1.5.
Some credit is due: here and here. Does not work on Android 2.1 (the WebViews, not the TextViews) - that's a known bug.
Now, the question remains - how do I identify devices where the default font already contains the Japanese shapes?
EDIT re: the mp3 hack. I've implemented the chunked solution at first, but then decided to go with font in the assets. The chunked approach has one upside - smaller APK size - and the following downsides:
Consumes more phone memory - you end up storing both compressed font in assets and uncompressed in the data directory
Is incompatible with Android 1.5 on the TextView side - the method Typeface.createFromFile() was introduced in API level 4
Complicates HTML generation - the CSS with the #font-face declaration needs to be parametrised, since the data path is a variable
Slows down the first app startup - you spend time combining the chunks
Storing the font as a compressed asset is not an option either - the font then doesn't show up in WebView, and you can clearly see in LogCat the message about "Data exceeds UNCOMPRESS_DATA_MAX".
Using the following in your onCreate/OnCreateView:
AssetManager am = getContext().getApplicationContext().getAssets();
mDroidSansJapaneseTypeface = Typeface.createFromAsset(am, String.format(Locale.JAPAN, "fonts/%s", "DroidSansJapanese.ttf")); //I put the font file in the assets/fonts/ folder
And then for your textviews:
myTextView.setTypeface(mDroidSansJapaneseTypeface);
myTextView.setTextLocale(Locale.JAPAN);
Be aware that not 100% of all fonts will be displayed in Android. I haven't seen too many problems for Japanese characters, but other CJK characters may appear as blank boxes, no matter what ttf file you use.

Categories

Resources