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

Spacing Attachment clarification #2

Open
JelleBosmaMT opened this issue Mar 18, 2016 · 6 comments
Open

Spacing Attachment clarification #2

JelleBosmaMT opened this issue Mar 18, 2016 · 6 comments

Comments

@JelleBosmaMT
Copy link

Asked to comment, here it is:

In Single positioning lookups there are 2 times 2 possible positioning types that can be applied to a glyph.

Xplacement and Yplacement: the image of the glyph changes its position in x or y in relation to the surrounding glyphs, that stay where they are.

Xadvance and Yadvance: the glyph stays where it is, but all the following glyphs are shifted.

The 3 variants of mark attachment lookups apply an algorithm where in a context of two glyphs with matching anchors, there is an X/Yplacement applied to the second glyph with a distance of 1st
glyph anchor minus 2nd glyph anchor. Of course in most cases this works best if the second glyph is zero width. It is assumed and even forced to be always zero width. But I do not see this written in the current GPOS spec as a requirement.

The cursive attachment is very different. One way of describing its algorithm is to say that there is an X/Yadvance applied to the first glyph with a distance of 1st glyph anchor minus 2nd glyph anchor.
(Of course it can also be done with X/Yplacement AND X/Yadvance to the second glyph.)
But there is a second way to describe what happens. On the first glyph the exit anchor creates an new right sidebearing and on the second the entry anchor a left sidebearing, if we ignore Y for a moment. With cursive connection we space glyphs with an alternative for the hmtx metrics.

Within the context of cursive connection the whole concept of spacing and non-spacing glyphs becomes very fluid. The advance width of a glyph may be the advance width of the hmtx table, which may be zero of positive. The advance width may be the distance between the two anchors: a value which can be positive, zero or negative. It may be the distance between the entry anchor and the original right sidebearing: positive, zero or negative. And the distance between origin and exit anchor is also possible: positive, zero or negative. So a single glyph may be zero width, positive width or negative width depending on context. And it does not really matter if glyphs are marks or base glyphs. To position one shape in relation to another, it is the coordinates of the anchors that matter: it does not matter if these coordinates are an anchor on a base glyph or mark glyph or on a spacing glyph or a non-spacing glyph.

Now we have a proposal to add a flag to allow attachment with spacing marks. There are 3 samples given of what it can do. Then its says: add this flag and we can use spacing marks for mark attachment and cursive attachment. But it does not specify an implementation or algorithm and it does not seem to distinguish between very different lookup types.

So what is the proposed algorithm for mark attachment in terms of placement and advance? What should the flag do for cursive connection, if anything other than preventing the shaper to meddle with the hmtx-advance? And if this flag is set and the spacing glyph is not “attached” to something would it be meddled with anyway. Any solution for that?

In other words: the current specification of the SpacingAttach flag, specifies the existence of a flag, but not what it does.

@davelab6
Copy link

davelab6 commented Mar 5, 2019

@JelleBosmaMT did this get resolved/clarified?

@JelleBosmaMT
Copy link
Author

I had to refresh my memory. I do not see any clarification in the proposal. So the answer seems to be "No".

@mhosken
Copy link
Collaborator

mhosken commented Mar 8, 2019

I've added some thinking that attempts to answer your questions. I'm sorry it's a bit rushed, Feel free to come back with further questions. I'll leave this bug open unless you consider it ready to be closed.

@JelleBosmaMT
Copy link
Author

JelleBosmaMT commented Mar 21, 2019

@mhosken

I think I understand what you mean to do with the mark to base case. The goal is to preserve a minimum side bearing measured from marks. But I have a hard time with the description. I'll just write down what I think the proposal is.

Maybe we can describe it from the point of view of the anchor points. We want to fix those base glyphs where the anchor is too close to the left or to the right. On the base the anchor has a left side distance baseLeft which is its distance to the origin, and a right side distance baseRight to the advance width. It is these distances that need to be fixed if they are too small for a particular mark.

Whether or not the mark has zero width the mark anchor has these distances too: markLeft and markRight.
In the mark the position of the anchor in relation to the advance width defines what minimum distance to preserve: If it is to left of origin and zero width, it is left side bearing only. To the right of origin and zero width it is the right sidebearing. To manage both sides you need to have an advance width and the anchor inside the advance. But the advance is used for measuring left and right sides only and otherwise ignored.

To preserve the left side bearing of a mark
the anchor has to be to the right of the origin (markLeft > 0)
To preserve a right side bearing of a mark
the anchor has to be to the right of the advance (markRight > 0)

To preserve the left side bearing of a mark, shift the base and increase the advance width:
If markLeft >0 and markLeft > baseLeft then shiftGlyph = mark left - base left and advanceWidth = advance width + shiftGlyph

To preserve the right side bearing of a mark, increase the advance where needed.
If markRight >0 and markRight > baseRight then advanceWidth = advance width + markRight - baseRight

In a GPOS I am used to the set-up where we deal with changes to advances first. In order: Cursive connection - kerning - context rules for advances. Then the placement with context positioning of base glyphs, mark to base/ligature, context positioning with marks, mark to mark.

This flag would create a lookup that does advances, base x-placement and mark attachment. I guess this means this should be OK when the lookup is applied before the first normal mark to base. If a base glyph is moved up or down in a context rule, its anchors are moved up and down. I haven't tried moving left or right, but see no reason why that would not work too. So within this order things should work without additional attributes described in the proposal as long as the x-placement is treated like any other.

For the case without cursive attachment I might use it to put wide Malayalam subscript Lvocalic below narrow base glyphs, rather than the ligatures that I have now.

But use with cursive connection is intended for Nastaliq. I guess it works if you treat a cluster as one on the fly ligature glyph. But this means it can only be used to control the boundaries of connected graphs. It would not be useable inside a cluster as an exception rule to fix specific combinations where a little extra room is needed..

For mark-to-mark the baseRight and baseLeft distances are measured where the anchor of the fixed mark is in relation to the advance of the base glyph or the cluster.

Is this the right interpretation?

@davelab6
Copy link

@mhosken ping :)

@mhosken
Copy link
Collaborator

mhosken commented Apr 17, 2019

Thanks for the ping.

I agree with you up to where you say: If a base glyph is moved up or down, its anchors are moved up and down. The difficulty is that different OT libraries behave differently with regard to mark attachment and subsequent base movement. If I understand it correctly, DirectWrite implements a position and forget behaviour where you can move the base all you like by the attachment won't move (except that the mark is positioned relative to the advance of the base, so if you change that, then it will move). Whereas harfbuzz does sort of track which marks attach to what, after attachment and so can move things when the base moves.

It is that complexity I am addressing in the document as to how to implement the spacing mark in a position and forget implementation, without having to start tracking attachment relationships.

As to your basic understanding: yes, I agree.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants