[prev in list] [next in list] [prev in thread] [next in thread]
List: openjdk-openjfx-dev
Subject: Re: Support for Ligatures
From: Scott Palmer <swpalmer () gmail ! com>
Date: 2022-10-25 2:25:18
Message-ID: 745B02B6-B3F5-496E-960D-A24AE3C8BFE9 () gmail ! com
[Download RAW message or body]
I guess everything you've written below about querying and requesting features still \
falls into the hole of "stuff we could do with Swing, but can't do with JavaFX". I \
don't use Swing anymore, but every once in a while I run into one of these issues. \
There are workarounds for some, like NSMenuFX to get proper menu support on macOS, or \
using AWT Desktop support in combination with JavaFX to get the missing support for \
the system tray, dock, opening documents with the OS-defined default handler, etc... \
but it's less than ideal. However, this issue doesn't appear to have any \
workaround.
I did a quick search in the JavaFX code for ligature support and it seems there is \
quite a bit of incomplete support in many parts of the font processing. E.g. \
com.sun.javafx.scene.control.skin.Utils contains the commented out block that appears \
to be from older AWT code:
private static boolean requiresComplexLayout(Font font, String string) {
/* Map attrs = font.getAttributes();
if (contains(attrs, KERNING, KERNING_ON) ||
contains(attrs, LIGATURES, LIGATURES_ON) ||
(attrs.containsKey(TRACKING) && attrs.get(TRACKING) != null)) {
return true;
}
return isComplexLayout(string.toCharArray(), 0, string.length());
*/
return false;
}
So complexLayout is always ‘false', which is good because where it is used the path \
for 'true' looks like: if (complexLayout) {
// TODO needs implementation
return 0;
} else {
com.sun.javafx.font.FontResources defines a bunch of constants related to ligatures, \
but they don't appear to be used anywhere. Looks like they are intended for the \
value returned by getFeatures() in FontResource and PGFont.
com.sun.javafx.font.PrismFont and the interface it implements PGFont (what does PG \
stand for?) defines a getFeatures method: /*
* Returns the features the user has requested.
* (kerning, ligatures, etc)
*/
@Override public int getFeatures() {
return features;
}
but features is always 0, with no means to set it.
com.sun.javafx.text.GlyphLayout where ‘features' is used in two places compares the \
features of Font to FontResource. PrismFont defaults to 0, and the PrismFontFile \
implementation of FontResource returns -1, so for GlyphLayout the supported features \
are always "everything" and the requested features are always "nothing", so boolean \
feature = false, always. This is used to compute ‘complex' (initially false) if \
(!complex) {
complex = feature || \
ScriptMapper.isComplexCharCode(codePoint); }
So ScriptMapper is the only thing really deciding what's ‘complex'… which seems \
to bring me back to what you've stated, that required ligatures like those needed for \
Arabic are supported. Now I wonder if ‘feature' was true would my Fira Code \
experiment render correctly or is there a lot more to it than that?
It seems there is some otherwise ‘dead' code already in place to support requesting \
these openType features. Is exposing an API to initialize the features of \
FontResource enough to get some meaningful results?
I was going to try some experiments, but I'm unable to build OpenJFX on my Mac for \
some reason:
> > Task :graphics:compileJava FAILED
> You specified both --module-source-path and a sourcepath. These options are \
> mutually exclusive. Ignoring sourcepath.
> error: option --upgrade-module-path cannot be used together with --release
> Usage: javac <options> <source files>
> use --help for a list of possible options
(using JDK 17 running a simple ./gradlew)
I didn't have trouble when I last built it a couple years ago, so I'm not sure what's \
changed.
Cheers,
Scott
> On Oct 24, 2022, at 3:43 PM, Philip Race <philip.race@oracle.com> wrote:
>
> FX does (of course) support required ligatures, meaning those without which some \
> script (eg Arabic) can't even be rendered.
>
> But that is implementation, no API.
>
> So this is about adding an API to request optional ligatures - and other OpenType \
> features. For example I think we'd want to support things like small caps etc.
>
> Of course we'd need to make sure all the measuring code is up to that .. and BTW
> the APIs to do measurement probably should be in the queue ahead of this ..
>
> And I am not sure about just an API to request ligatures without an API to query
> if ligatures are available for a font. However that may turn out to be tricky for a
> few reasons, but we should at least study it.
>
> And to try to answer the "when" question .. it is on a "desired" list in my head \
> and maybe even on a wiki somewhere .. but no concrete timetable exists.
>
> But it is good to get feedback like this so we know it is interesting to \
> developers.
> -phil.
>
> On 10/24/22 12:07 PM, Scott Palmer wrote:
> > Something I noticed while experimenting with RichTextFX, when I set it to use \
> > Fira Code for the font, like I do in NetBeans, I see that JavaFX doesn't support \
> > ligatures. I found this issue that's been around for quite some time: \
> > https://bugs.openjdk.org/browse/JDK-8091616
> > Is there any drive to get this implemented within the next few releases? I would \
> > help, but unfortunately I suspect it will take more time than I can commit to it. \
> > I'm hoping that eliminating some of the remaining gaps between what JavaFX \
> > supports and Swing supports would be a priority, as it removes some barriers to \
> > JavaFX adoption... but maybe not?
> > Regards,
> >
> > Scott
>
[Attachment #3 (unknown)]
<html><head><meta http-equiv="content-type" content="text/html; \
charset=utf-8"></head><body style="overflow-wrap: break-word; -webkit-nbsp-mode: \
space; line-break: after-white-space;"><div dir="auto" style="overflow-wrap: \
break-word; -webkit-nbsp-mode: space; line-break: after-white-space;"><div dir="auto" \
style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: \
after-white-space;"><div dir="auto" style="overflow-wrap: break-word; \
-webkit-nbsp-mode: space; line-break: after-white-space;">I guess everything you've \
written below about querying and requesting features still falls into the hole of \
"stuff we could do with Swing, but can't do with JavaFX". I don't use Swing \
anymore, but every once in a while I run into one of these issues. There are \
workarounds for some, like NSMenuFX to get proper menu support on macOS, or using AWT \
Desktop support in combination with JavaFX to get the missing support for the system \
tray, dock, opening documents with the OS-defined default handler, etc... but it's \
less than ideal. However, this issue doesn't appear to have any \
workaround.</div><div dir="auto" style="overflow-wrap: break-word; -webkit-nbsp-mode: \
space; line-break: after-white-space;"><div><br></div><div>I did a quick search in \
the JavaFX code for ligature support and it seems there is quite a bit of incomplete \
support in many parts of the font processing. E.g. \
com.sun.javafx.scene.control.skin.Utils contains the commented out block that appears \
to be from older AWT code:</div><div><br></div><div><div><font face="Courier \
New"> private static boolean requiresComplexLayout(Font font, String \
string) {</font></div><div><font face="Courier New"> /* \
Map attrs = font.getAttributes();</font></div><div><font \
face="Courier New"> if (contains(attrs, \
KERNING, KERNING_ON) ||</font></div><div><font face="Courier New"> \
contains(attrs, LIGATURES, LIGATURES_ON) \
||</font></div><div><font face="Courier New"> \
(attrs.containsKey(TRACKING) && attrs.get(TRACKING) != null)) \
{</font></div><div><font face="Courier New"> \
return true;</font></div><div><font face="Courier New"> \
}</font></div><div><font face="Courier New"> \
return isComplexLayout(string.toCharArray(), 0, \
string.length());</font></div><div><font face="Courier New"> \
*/</font></div><div><font face="Courier New"> \
return false;</font></div><div><font face="Courier New"> \
}</font></div><div><br></div><div>So complexLayout is always ‘false', which is good \
because where it is used the path for 'true' looks like:</div><div><div><font \
face="Courier New"> if (complexLayout) \
{</font></div><div><font face="Courier New"> \
// TODO needs implementation</font></div><div><font face="Courier New"> \
return 0;</font></div><div><font face="Courier \
New"> } else \
{</font></div></div><div><br></div><div><br></div><div>com.sun.javafx.font.FontResources \
defines a bunch of constants related to ligatures, but they don't appear to be used \
anywhere. Looks like they are intended for the value returned by getFeatures() \
in FontResource and PGFont.</div><div><br></div><div>com.sun.javafx.font.PrismFont \
and the interface it implements PGFont (what does PG stand for?) defines a \
getFeatures method:</div><div><div><font face="Courier New"> \
/*</font></div><div><font face="Courier New"> * Returns the \
features the user has requested.</font></div><div><font face="Courier New"> \
* (kerning, ligatures, etc)</font></div><div><font face="Courier \
New"> */</font></div><div><font face="Courier New"> \
@Override public int getFeatures() {</font></div><div><font face="Courier New"> \
return features;</font></div><div><font face="Courier \
New"> }</font></div><div><br></div><div>but features is always 0, with \
no means to set it.</div><div><br></div><div>com.sun.javafx.text.GlyphLayout where \
‘features' is used in two places compares the features of Font to FontResource. \
PrismFont defaults to 0, and the PrismFontFile implementation of FontResource returns \
-1, so for GlyphLayout the supported features are always "everything" and the \
requested features are always "nothing", so boolean feature = false, always. This is \
used to compute ‘complex' (initially false)</div><div><div><font face="Courier \
New"> if \
(!complex) {</font></div><div><font face="Courier New"> \
complex = feature || \
ScriptMapper.isComplexCharCode(codePoint);</font></div><div><font face="Courier \
New"> \
}</font></div><div>So ScriptMapper is the only thing really deciding what's \
‘complex'… which seems to bring me back to what you've stated, that required \
ligatures like those needed for Arabic are supported. Now I wonder if \
‘feature' was true would my Fira Code experiment render correctly or is there a lot \
more to it than that?</div><div><br></div><div>It seems there is some otherwise \
‘dead' code already in place to support requesting these openType \
features.</div><div>Is exposing an API to initialize the features of FontResource \
enough to get some meaningful results?</div><div><br></div><div>I was going to try \
some experiments, but I'm unable to build OpenJFX on my Mac for some \
reason:</div><div><br></div><div><blockquote type="cite"><p style="margin: 0px; \
font-stretch: normal; line-height: normal; font-family: Hack; color: rgb(255, 99, \
85); background-color: rgba(255, 255, 255, 0.9);"><span \
style="font-variant-ligatures: no-common-ligatures"><b>> Task \
:graphics:compileJava</b> FAILED</span></p> <p style="margin: 0px; font-stretch: \
normal; line-height: normal; font-family: Hack; color: rgb(0, 255, 0); \
background-color: rgba(255, 255, 255, 0.9);"><span style="font-variant-ligatures: \
no-common-ligatures">You specified both --module-source-path and a sourcepath. These \
options are mutually exclusive. Ignoring sourcepath.</span></p> <p style="margin: \
0px; font-stretch: normal; line-height: normal; font-family: Hack; color: rgb(0, 255, \
0); background-color: rgba(255, 255, 255, 0.9);"><span style="font-variant-ligatures: \
no-common-ligatures">error: option --upgrade-module-path cannot be used together with \
--release</span></p> <p style="margin: 0px; font-stretch: normal; line-height: \
normal; font-family: Hack; color: rgb(0, 255, 0); background-color: rgba(255, 255, \
255, 0.9);"><span style="font-variant-ligatures: no-common-ligatures">Usage: javac \
<options> <source files></span></p> <p style="margin: 0px; font-stretch: \
normal; line-height: normal; font-family: Hack; color: rgb(0, 255, 0); \
background-color: rgba(255, 255, 255, 0.9);"><span style="font-variant-ligatures: \
no-common-ligatures">use --help for a list of possible \
options</span></p></blockquote><div><p style="margin: 0px; font-stretch: normal; \
line-height: normal; font-family: Hack; color: rgb(0, 255, 0); background-color: \
rgba(255, 255, 255, 0.9);"><span style="font-variant-ligatures: \
no-common-ligatures"><br></span></p></div></div></div><div><span style="caret-color: \
rgb(0, 0, 0); color: rgb(0, 0, 0);"> (using JDK 17 running a simple \
./gradlew)</span></div><div><font color="#000000">I didn't have trouble when I last \
built it a couple years ago, so I'm not sure what's \
changed.</font></div><div><br></div></div><div>Cheers,</div><div><br></div><div>Scott</div><div><br><blockquote \
type="cite"><div>On Oct 24, 2022, at 3:43 PM, Philip Race \
<philip.race@oracle.com> wrote:</div><br \
class="Apple-interchange-newline"><div> <meta http-equiv="Content-Type" \
content="text/html; charset=utf-8">
<div>
FX does (of course) support required ligatures, meaning those
without which some script (eg Arabic)<br>
can't even be rendered.<br>
<br>
But that is implementation, no API.<br>
<br>
So this is about adding an API to request optional ligatures - and
other OpenType features.<br>
For example I think we'd want to support things like small caps etc.<br>
<br>
Of course we'd need to make sure all the measuring code is up to
that .. and BTW<br>
the APIs to do measurement probably should be in the queue ahead of
this ..<br>
<br>
And I am not sure about just an API to request ligatures without an
API to query<br>
if ligatures are available for a font. However that may turn out to
be tricky for a<br>
few reasons, but we should at least study it.<br>
<br>
And to try to answer the "when" question .. it is on a "desired"
list in my head and maybe<br>
even on a wiki somewhere .. but no concrete timetable exists.<br>
<br>
But it is good to get feedback like this so we know it is
interesting to developers.<br>
<br>
-phil.<br>
<br>
<div class="moz-cite-prefix">On 10/24/22 12:07 PM, Scott Palmer
wrote:<br>
</div>
<blockquote type="cite" \
cite="mid:D2536978-0591-4BA9-AD3D-879057A10877@gmail.com">
<div style="display: block;">Something I noticed while
experimenting with RichTextFX, when I set it to use Fira Code
for the font, like I do in NetBeans, I see that JavaFX doesn't
support ligatures. I found this issue that's been around for
quite some time:</div>
<div style="display: block;">
<div style="-webkit-user-select: all; -webkit-user-drag:
element; display: inline-block;" class="apple-rich-link" draggable="true" \
role="link" data-url="https://bugs.openjdk.org/browse/JDK-8091616"><a \
style="border-radius:10px;font-family:-apple-system, Helvetica, Arial,
sans-serif;display:block;-webkit-user-select:none;width:300px;user-select:none;-webkit \
-user-modify:read-only;user-modify:read-only;overflow:hidden;text-decoration:none;" \
class="lp-rich-link" rel="nofollow" \
href="https://bugs.openjdk.org/browse/JDK-8091616" dir="ltr" role="button" \
draggable="false" width="300" moz-do-not-send="true">
<table style="table-layout:fixed;border-collapse:collapse;width:300px;background-color:#E5E6E9;font-family:-apple-system,
Helvetica, Arial, sans-serif;" class="lp-rich-link-emailBaseTable" \
width="300" cellspacing="0" cellpadding="0" border="0"> <tbody>
<tr>
<td vertical-align="center">
<table style="font-family:-apple-system, Helvetica,
Arial,
sans-serif;table-layout:fixed;background-color:rgba(229,
230, 233, 1);" class="lp-rich-link-captionBar" width="300" \
cellspacing="0" cellpadding="0" bgcolor="#E5E6E9"> <tbody>
<tr>
<td style="padding:8px 0px 8px 0px;" \
class="lp-rich-link-captionBar-textStackItem"> <div style="max-width:100%;margin:0px \
16px
0px 16px;overflow:hidden;" \
class="lp-rich-link-captionBar-textStack"> <div \
style="word-wrap:break-word;font-weight:500;font-size:12px;overflow:hidden;text-overflow:ellipsis;text-align:left;" \
class="lp-rich-link-captionBar-textStack-topCaption-leading"><a rel="nofollow" \
href="https://bugs.openjdk.org/browse/JDK-8091616" style="text-decoration: none" \
draggable="false" moz-do-not-send="true"><font style="" color="#272727">[JDK-8091616] \
Prism: font: ligature and kerning
support - Java Bug System</font></a></div>
<div \
style="word-wrap:break-word;font-weight:400;font-size:11px;overflow:hidden;text-overflow:ellipsis;text-align:left;" \
class="lp-rich-link-captionBar-textStack-bottomCaption-leading"><a rel="nofollow" \
href="https://bugs.openjdk.org/browse/JDK-8091616" style="text-decoration: none" \
draggable="false" moz-do-not-send="true"><font style="" \
color="#808080">bugs.openjdk.org</font></a></div> </div>
</td>
<td style="padding:6px 12px 6px 0px;" \
class="lp-rich-link-captionBar-rightIconItem" width="36"><a rel="nofollow" \
href="https://bugs.openjdk.org/browse/JDK-8091616" draggable="false" \
moz-do-not-send="true"><span \
id="cid:part1.pgghvLBj.kKB35Rev@oracle.com"><jira-favicon-hires.png></span></a></td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</a></div>
</div>
<div><br>
</div>
<div>Is there any drive to get this implemented within the next
few releases? I would help, but unfortunately I suspect it will
take more time than I can commit to it.</div>
<div>I'm hoping that eliminating some of the remaining gaps
between what JavaFX supports and Swing supports would be a
priority, as it removes some barriers to JavaFX adoption... but
maybe not?</div>
<div><br>
</div>
<div>Regards,</div>
<div><br>
</div>
<div>Scott</div>
</blockquote>
<br>
</div>
</div></blockquote></div><br></div></div></div></div></body></html>
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic