Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement kern (and may kerx?) cross-stream to support GeezaPro Arabic diacritics #1356

Closed
ebraminio opened this issue Nov 4, 2018 · 20 comments
Labels
Chrome Chrome/Chromium project related issues and requests

Comments

@ebraminio
Copy link
Collaborator

ebraminio commented Nov 4, 2018

From https://chromium-review.googlesource.com/c/chromium/src/+/1275945/33/third_party/WebKit/LayoutTests/platform/mac/fast/text/font-fallback-expected.png

util/hb-view /System/Library/Fonts/GeezaPro.ttc الأَبْجَدِيَّةـالعَرَبِيَّة --shaper coretext

util/hb-view /System/Library/Fonts/GeezaPro.ttc الأَبْجَدِيَّةـالعَرَبِيَّة --shaper ot or (with or without --font-funcs=ot)

On 10.13 machine,

CT:
image

OT:
image

3	en	Geeza Pro Regular; 14.0d1e4; 2017-12-05

bash-3.2$ shasum /System/Library/Fonts/GeezaPro.ttc 
ab26ea45dcaa5e1c5a958e42af10e10d330e7334  /System/Library/Fonts/GeezaPro.ttc
@ebraminio ebraminio added the Chrome Chrome/Chromium project related issues and requests label Nov 4, 2018
@ebraminio
Copy link
Collaborator Author

Still arguable maybe, I don't know

@behdad
Copy link
Member

behdad commented Nov 4, 2018

For a font that has no mark positioning data, this is really good already.

@behdad behdad closed this as completed Nov 4, 2018
@ebraminio
Copy link
Collaborator Author

Replaced with high quality images. Maybe kasrah can be put a little higher?

@jfkthame
Copy link
Collaborator

jfkthame commented Nov 4, 2018

From a brief look at the Geeza Pro on my 10.13 system, it appears to include a number of cross-stream kerning subtables (in a 'kern' table, not 'kerx'). I'm guessing these are intended to adjust the height of diacritics; but are they supported by HB yet?

@ebraminio
Copy link
Collaborator Author

Oh thanks @jfkthame, pretty sure that is the issue and Kern table doesn't show any indication of handling cross-stream AFAICS.

diff --git a/src/hb-ot-kern-table.hh b/src/hb-ot-kern-table.hh
index e361330b..9ab64af7 100644
--- a/src/hb-ot-kern-table.hh
+++ b/src/hb-ot-kern-table.hh
@@ -209,9 +209,10 @@ struct KernSubTableFormat1
     };
 
     inline driver_context_t (const KernSubTableFormat1 *table_,
-                            AAT::hb_aat_apply_context_t *c_) :
+                            AAT::hb_aat_apply_context_t *c_, bool is_cross_stream_) :
        c (c_),
        table (table_),
+       is_cross_stream (is_cross_stream_),
        /* Apparently the offset kernAction is from the beginning of the state-machine,
         * similar to offsets in morx table, NOT from beginning of this table, like
         * other subtables in kerx.  Discovered via testing. */
@@ -258,7 +259,9 @@ struct KernSubTableFormat1
          int v = *actions++;
          if (idx < buffer->len && buffer->info[idx].mask & kern_mask)
          {
-           if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
+           bool is_horizontal = HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction);
+           if (is_cross_stream) is_horizontal = !is_horizontal;
+           if (is_horizontal)
            {
              buffer->pos[idx].x_advance += c->font->em_scale_x (v);
              if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
@@ -284,16 +287,16 @@ struct KernSubTableFormat1
     const UnsizedArrayOf<FWORD> &kernAction;
     unsigned int stack[8];
     unsigned int depth;
+    bool is_cross_stream;
   };
 
-  inline bool apply (AAT::hb_aat_apply_context_t *c) const
+  inline bool apply (AAT::hb_aat_apply_context_t *c, bool is_cross_stream) const
   {
     TRACE_APPLY (this);
-
     if (!c->plan->requested_kerning)
       return false;
 
-    driver_context_t dc (this, c);
+    driver_context_t dc (this, c, is_cross_stream);
 
     AAT::StateTableDriver<AAT::MortTypes, EntryData> driver (machine, c->buffer, c->font->face);
     driver.drive (&dc);
@@ -483,12 +486,12 @@ struct KernSubTable
     }
   }
 
-  inline void apply (AAT::hb_aat_apply_context_t *c, unsigned int format) const
+  inline void apply (AAT::hb_aat_apply_context_t *c, unsigned int format, bool is_cross_stream) const
   {
     /* TODO Switch to dispatch(). */
     switch (format) {
     case 0: u.format0.apply (c); return;
-    case 1: u.format1.apply (c); return;
+    case 1: u.format1.apply (c, is_cross_stream); return;
     case 2: u.format2.apply (c); return;
     case 3: u.format3.apply (c); return;
     default:                    return;
@@ -528,6 +531,9 @@ struct KernSubTableWrapper
   inline bool is_supported (void) const
   { return !(thiz()->coverage & T::CheckFlags); }
 
+  inline bool is_cross_stream (void) const
+  { return !(thiz()->coverage & T::CrossStream); }
+
   inline bool is_horizontal (void) const
   { return (thiz()->coverage & T::Direction) == T::CheckHorizontal; }
 
@@ -541,7 +547,7 @@ struct KernSubTableWrapper
   { return is_supported () && is_horizontal () ? get_kerning (left, right) : 0; }
 
   inline void apply (AAT::hb_aat_apply_context_t *c) const
-  { thiz()->subtable.apply (c, thiz()->format); }
+  { thiz()->subtable.apply (c, thiz()->format, is_cross_stream ()); }
 
   inline unsigned int get_size (void) const { return thiz()->length; }

And that made result a little different or better,

Before:
image

After:
image

But the way HB's buffer is ordered, I guess Behdad is better to have a look at this.

@ebraminio ebraminio reopened this Nov 5, 2018
@behdad
Copy link
Member

behdad commented Nov 5, 2018

From a brief look at the Geeza Pro on my 10.13 system, it appears to include a number of cross-stream kerning subtables (in a 'kern' table, not 'kerx'). I'm guessing these are intended to adjust the height of diacritics; but are they supported by HB yet?

Interesting. Never saw a font with those. I'll implement that.

@behdad
Copy link
Member

behdad commented Nov 5, 2018

But the way HB's buffer is ordered, I guess Behdad is better to have a look at this.

That wouldn't be enough. Also, have to disable fallback mark positioning. I'll take a look.

@behdad
Copy link
Member

behdad commented Nov 5, 2018

I hope we don't have to look into kern table to decide if fallback mark positioning should be applied. Currently, looks like we might need to.

@behdad
Copy link
Member

behdad commented Nov 5, 2018

Also, we apply kern table if GPOS kern is missing. That can interact badly with mark positioning. Oh well.

@behdad
Copy link
Member

behdad commented Nov 5, 2018

Maybe kasrah can be put a little higher?

We decided to not move bottom marks up. That helped with Hebrew.

@ebraminio ebraminio changed the title GeezaPro Arabic diacritics doesn't look right Implement kern (and may kerx?) cross-stream to support GeezaPro Arabic diacritics Nov 5, 2018
@ebraminio
Copy link
Collaborator Author

util/hb-shape /System/Library/Fonts/GeezaPro.ttc الأَبْجَدِيَّةـالعَرَبِيَّة --shaper coretext

[u0629.final.tehMarbuta=26+713|u064e_u0651.shaddaFatha=23@0,-200+0|u064a.medial.yeh=23+736|u0650.kasra=21@0,290+-80|u0628.initial.beh=21+856|u064e.fatha=19@0,-570+-200|u0631.final.reh=19+1102|u064e.fatha=17@0,-200+-200|u0639.medial.ain=17+938|u0644.initial.lam=16+514|u0627.final.alef=15+647|u0640.tatweel=14+448|u0629.final.tehMarbuta=13+712|u064e_u0651.shaddaFatha=10@0,-200+0|u064a.initial.yeh=10+735|u0650.kasra=8@0,570+-79|u062f.final.dal=8+1192|u064e.fatha=6@0,-160+-290|u062c.medial.jeem=6+1358|u0652.sukun=4@0,-200+0|u0628.initial.beh=4+283|u064e.fatha=2@0,120+120|u0644_u0623.isolated.lamHamzaOnAlef=1+1162|u0627.alef=0+646]

@behdad
Copy link
Member

behdad commented Nov 7, 2018

Okay. After a long day of trial and error, my PR gets most of this right. Just the u064e_u0651.shaddaFatha doesn't get positioned, and I don't see in the font tables how it should...

There's a few finishing touches that need to be made. I'll finish tomorrow.

@behdad
Copy link
Member

behdad commented Nov 7, 2018

Okay! With help from Ned, I fixed the remaining mystery, as well as finish the finishing touches. It renders fine now. There's a tiny difference visible compared to CoreText, but I don't think that's worth tracking down...

@behdad
Copy link
Member

behdad commented Nov 7, 2018

geeza

@behdad
Copy link
Member

behdad commented Nov 7, 2018

The marks on Lam-Alef (right-most two stacked marks) don't touch the Sokun mark to their left in our rendering, whereas they do in CoreText's. Not sure why. Ours is better anyway....

@behdad
Copy link
Member

behdad commented Nov 7, 2018

And hb-shape output:

[u0629.final.tehMarbuta=26+713|u064e_u0651.shaddaFatha=23@0,-200+0|u064a.medial.yeh=23+656|u0650.kasra=21@80,290+80|u0628.initial.beh=21@-80,0+576|u064e.fatha=19@200,-570+200|u0631.final.reh=19@-200,0+702|u064e.fatha=17@200,-200+200|u0639.medial.ain=17@-200,0+738|u0644.initial.lam=16+515|u0627.final.alef=15+647|u0640.tatweel=14+449|u0629.final.tehMarbuta=13+713|u064e_u0651.shaddaFatha=10@0,-200+0|u064a.initial.yeh=10+656|u0650.kasra=8@80,570+80|u062f.final.dal=8@-80,0+822|u064e.fatha=6@290,-160+290|u062c.medial.jeem=6@-290,0+1069|u0652.sukun=4@0,-200+0|u0628.initial.beh=4+656|u064e.fatha=1@-252,120+-252|u0644_u0623.isolated.lamHamzaOnAlef=1@120,0+1282|u0627.alef=0+647]

@behdad behdad closed this as completed in 385f78b Nov 7, 2018
@avidrissman
Copy link

avidrissman commented Nov 8, 2018 via email

@behdad
Copy link
Member

behdad commented Nov 8, 2018

Does this help with the Hebrew vowels as I pointed out in #1264?

Possibly. Someone with Mac needs to test.

@ebraminio
Copy link
Collaborator Author

Thanks Behdad, looks cool now, specially sharing the logic part.

No that doesn't have cross stream, harfbuzz doesn't shape it incorrectly AFAICT also, something wrong with Chrome itself, limited to 10.10 and 10.11, most likely till we find shaping difference on HarfBuzz itself also. I will check it again however.

@behdad
Copy link
Member

behdad commented Nov 17, 2018

something wrong with Chrome itself

Dominik and I now have a theory about what's wrong in Blink. He's working on it.

ebraminio pushed a commit to ebraminio/harfbuzz that referenced this issue Nov 24, 2018
Finally:  Fixes harfbuzz#1356

Test case:
$ ./hb-shape GeezaPro.ttc -u U+0628,U+064A,U+064E,U+0651,U+0629
[u0629.final.tehMarbuta=4+713|u064e_u0651.shaddaFatha=1@0,-200+0|u064a.medial.yeh=1+656|u0628.initial.beh=0+656]

The mark positioning (kern table CrossStream kerning) only works if deleted
glyph (as result of ligation) is still in stream and pushed through the
state machine.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Chrome Chrome/Chromium project related issues and requests
Projects
None yet
Development

No branches or pull requests

4 participants