mono / SkiaSharp

SkiaSharp is a cross-platform 2D graphics API for .NET platforms based on Google's Skia Graphics Library. It provides a comprehensive 2D API that can be used across mobile, server and desktop models to render images.
MIT License
4.26k stars 530 forks source link

SkiaSharp.HarfBuzz on Android - result from Shape() - SKShaper.Result.Codepoints are all 0 #528

Open michaldobrodenka opened 6 years ago

michaldobrodenka commented 6 years ago

I'm trying to use HarfBuzz to support RTL, but when I try it on Android, shaper.Shape result CodePoints are all 0. Result.Points seems to have some values (but far from each other). Maybe some problem with TypeFace decoding or something.

When testing on WPF or iOS, everything seems ok.

HarfBuzzDemo.zip

VS bug #736293

michaldobrodenka commented 6 years ago

I've tried also older versions of SkiaSharp and SkiaSharp.HarfBuzz, on emulator (x86) and phone (LG G4 ARMv8) and could not get usable result from Shape() (on Android).

I also tried combinations with other fonts, in otf or ttf files.

michaldobrodenka commented 6 years ago

This line: HarfBuzzApi.hb_shape(Handle, buffer.Handle, IntPtr.Zero, 0);

set all buffer.GlipInfo.CodePoints from utf8 to 0, but I don't know how to debug c++ code. Is it possible in VS2017?

mattleibow commented 6 years ago

Sorry for the late reply, still traveling. Just one thing to check... It it actually using the font? If you draw normal strings, is it the custom font?

I haven't had a chance to look at the sample yet, but make sure you are loading the font and skia renders basic characters. Then try the shaping using simple Latin characters and see if that works.

michaldobrodenka commented 6 years ago

I'm trying with arial ttf and otf fonts, using only Latin characters ("Hello World!"). I've tested SF-UI-Display-Bold.otf, Roboto-Medium.ttf

//canvas.DrawText("Hello world!", new SKPoint(10, 300), paint); // OK
var shaper = new SKShaper(paint.Typeface);
//canvas.DrawShapedText(shaper, "Hello world!", 10, 300, paint); // NOT OK

var result = shaper.Shape("Hello world!", 10, 300, paint); // result.Codepoints are all 0

I was able to build SkiaSharp.HarfBuzz and libHarfBuzz.so but it seems that problem is on C++ side, I've tried several config.h changes, no luck. Seems like Android version of HarfBuzz can not work with typeface or something like that.

result.Points are pointing to something like default/maximum character width for every letter. result.Points/Codepoints are having correct Length

mattleibow commented 6 years ago

Looking at things still, but the SKTypeface.FromFamilyName("Times New Roman") works... may be font related...

mattleibow commented 6 years ago

Still looking at this. My debugger refuses to find the symbols... Now my Android Studio also doesn't want to even start the app. Supposedly debugging is possible, but I can't quite get the planets to align.

michaldobrodenka commented 6 years ago

I wish I could be helpful somehow. Maybe I will try to align the planets.

mattleibow commented 6 years ago

I have been looking around, but can't find anything. We are using a quite old harfbuzz, so it may be that the font file has something...

What you can try is to build the latest harfbuzz and then use that: https://github.com/harfbuzz/harfbuzz It uses CMake, so it should be fairly straight-forward.

Just note, I called my library libHarfBuzzSharp as I was in a dream world. If you build with CMake, you will get a harfbuzz. I can't swear on just renaming the files, but you can try that. Maybe that will work and all the problems go away.

I do want to update harfbuzz, but haven't quite had the chance just yet.

michaldobrodenka commented 6 years ago

Thank you very much for your effort!

For current release I will probably just try to workaround it on Android with SKTypeface.FromFamilyName(some similar font) and ```#ifdef```` (at least we have workaround) .

I've tried to fix it, it seems, that there is problem in cooperation between C++/C# on Android with blobs/stream or something like that. But not sure.

New version could help, but the same version works OK on iOS/Windows. If I find some thime, I'll try to update and see if it helps.

michaldobrodenka commented 6 years ago

Got much nicer workaround!

Using:

using (var data = SKData.Create(stream))
{
     result = SKTypeface.FromData(data);
}

instead of: result = SKTypeface.FromStream(stream);

And it works!

azeemchaudhrry commented 5 years ago

Thanks @michaldobrodenka your suggestion solve the problem on xamarin android.

mattleibow commented 5 years ago

Thanks for that comment @michaldobrodenka , I will investigate further.