<div dir="ltr">Thanks Skef.<div><br></div><div>I think I found the right approach for this (taking ideas from COLRv1 paint tree / graph). Ignoring your other proposals, we add these:</div><div><br></div><div>We add new Condition's that implement AND of a bunch of Conditions (like the current ConditionSet does), another for OR, and another for NEGATE:</div><div><br></div><div>struct ConditionAnd</div><div>{</div><div> uint16 format; // 2</div><div> uint16 conditionCount; // Number of conditions for this conjunction expression.</div> Offset32To<Condition> conditionOffsets[conditionCount];<div>}</div><div><br></div><div><div>struct ConditionOr<br></div><div>{</div><div> uint16 format; // 3</div><div> uint16 conditionCount; // Number of conditions for this disjunction expression.</div> Offset32To<Condition> conditionOffsets[conditionCount];<div>}</div><div></div></div><div><div><div><br></div><div>struct ConditionNegate<br></div><div>{</div><div> uint16 format; // 4</div> Offset32To<Condition> condition;<div>}</div><div><br></div><div>WDYT?</div><div></div></div><div></div><div><div dir="ltr" class="gmail_signature" data-smartmail="gmail_signature">behdad<br><a href="http://behdad.org/" target="_blank">http://behdad.org/</a></div></div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Apr 11, 2024 at 6:26 AM Skef Iterum <<a href="mailto:skef@skef.org">skef@skef.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><u></u>
<div>
<p>I'm still trying to think through all of this stuff, but I
tentatively think that if we added a hack to negate a condition
set then we'll have enough. <br>
</p>
<p>To see the issues involved it may be easiest to work backwards.
It's not an accident that most programming languages contain the
combination of boolean expressions (with AND, OR, NOT and some
equivalent of parentheses) + an if/else if/.../else structure. The
former lets you express anything you need to, typically quite
compactly. The latter expresses a set of alternatives such that
it's guaranteed you'll only get one of them. <br>
</p>
<p>With arbitrary boolean expressions it's easy to fake up the
if/else if/else. If you would have had</p>
<blockquote>
<p><font face="monospace">if A<br>
R<br>
else if B<br>
S<br>
else if C<br>
T<br>
else if D<br>
U<br>
else<br>
V</font></p>
</blockquote>
<p>you can just do</p>
<blockquote>
<p><font face="monospace">if A<br>
R<br>
if ~A & B<br>
S<br>
if ~A & ~B & C<br>
T<br>
if ~A & ~B & ~C & D<br>
U<br>
if ~A & ~B & ~C & ~D<br>
V</font></p>
</blockquote>
<p>at the cost of a bit more computation (typically). <br>
</p>
<p>This kind of generality was (presumably) thought to be <i>over</i>-general
for variable fonts, and I don't disagree. But it's worth noting
what you lose if you lack <i>both</i> arbitrary boolean
expressions <i>and</i> if/else if/.../else. Say we add condition
set negation. Then if you have a fairly typical case like the
following (where brackets indicate a set)<br>
</p>
<blockquote>
<p><font face="monospace">if [A & C]<br>
R<br>
else<br>
S</font></p>
</blockquote>
<p>You can replace that with</p>
<blockquote>
<p><font face="monospace">if [A & C]<br>
R<br>
if ~[A & C]<br>
S</font></p>
</blockquote>
<p>However, <i>at a single level</i> that doesn't extend further.
So if you have</p>
<blockquote>
<p><font face="monospace">if [A & C]<br>
R<br>
else if [D & E]<br>
S<br>
else<br>
T</font></p>
</blockquote>
<p>(which is just adding a third case), there's no easy way to adapt
that into pure "if" conditions using the tools available. And
that's what I've been worried about -- it seems annoying not to be
able to have three alternatives (with non-trivial conditions)
spread out over the design space. <br>
</p>
<p>However, it seems like you can accomplish the equivalent with an
extra level. Assume <font face="monospace">R</font>, <font face="monospace">S</font>, and <font face="monospace">T</font>
are "existing" components. Then you can just do</p>
<blockquote>
<p><font face="monospace">a:</font><br>
<font face="monospace">if [D & E]<br>
S<br>
if ~[D & E]<br>
T</font></p>
<p><font face="monospace">b:</font><br>
<font face="monospace">if [A & C]<br>
R<br>
if ~[A & C]<br>
a</font></p>
</blockquote>
<p>Now <font face="monospace">b</font> has the right qualities. In
effect, <font face="monospace">a</font> sometimes has the "wrong"
contents when <font face="monospace">[A & C]</font> applies
but you never <i>see</i> it in that case.<br>
</p>
<p>So like I said I want to think about this a bit more but I
tentatively think the thing to do is add means of negating the
condition set (and I think the Format 5 condition hack would be
fine for that, actually), and remove the "else" from the
lookup-based feature variations mechanism to simplify it.</p>
<p>Skef<br>
</p>
<div>On 4/11/24 01:20, Behdad Esfahbod
wrote:<br>
</div>
<blockquote type="cite">
<div dir="ltr">Hi Skef,
<div><br>
</div>
<div>I'm a bit uncomfortable encoding if/else in VARC. As you
said on the call, the current design seems like a practical
compromise. As for negation, we *can* add a flag to the
component to negate the condition. Maybe that's the right
approach. But I feel like the conditionSet itself should
contain the negation. That would reduce sharing though.</div>
<div><br>
</div>
<div>A "negate the rest" condition type sounds good to me.<br>
</div>
<div><br clear="all">
<div>
<div dir="ltr" class="gmail_signature">behdad<br>
<a href="http://behdad.org/" target="_blank">http://behdad.org/</a></div>
</div>
<br>
</div>
</div>
<br>
<div class="gmail_quote">
<div dir="ltr" class="gmail_attr">On Mon, Apr 8, 2024 at 1:55 PM
Skef Iterum via mpeg-otspec <<a href="mailto:mpeg-otspec@lists.aau.at" target="_blank">mpeg-otspec@lists.aau.at</a>>
wrote:<br>
</div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div>
<p>A note on conditions as defined in
WG03-varc-and-other-updates-03.pdf (up for review tomorrow
morning).</p>
<p>When I sketched out the VARC condition idea I had them
arranged in if/else if/.../else sequences. From my reading
of the document they're currently in "if" form -- a
condition set can be attached to a component and if it is
it will only be used if the condition set evaluates to
true.</p>
<p>There's nothing wrong with that semantic; it may be
preferable because it's simpler. However, the most common
case with this system is that you want one shape to render
in some region of design space (defined by the condition
set) and another shape to render outside of that. And
negating a condition <i>set</i> can be expensive and/or
tricky. So I would recommend that one of these two things
change:<br>
</p>
<ul>
<li>The if/else if/.../else semantic is restored</li>
<li>Some way of negating a condition set is added to the
specification<br>
</li>
</ul>
<p>We talked about the possibility of condition set negation
in a previous meeting but didn't come to any conclusions.
It's tricky because the table has no versioning. If we
wanted to hack negations into the current format the way
to do that might be to add a new condition format
(possibly 5 if newfeatvar_spec.pdf is accepted) that looks
something like:<br>
</p>
<blockquote>
<p>ConditionTableFormat5</p>
</blockquote>
<blockquote>
<p><b>Type
Name Description</b></p>
<p>uint16
Format Format (set to 5)</p>
</blockquote>
<blockquote>
<p>When present in a condition set this condition
indicates the set should apply when<br>
at least one of the other conditions is false and not
otherwise. That is, it makes the<br>
condition set apply when it would normally not and
vice-versa. There should be at <br>
most one format 5 condition in a condition set and it
should be the first.<br>
</p>
</blockquote>
<p>If this is preferred it could be used to replace/simplify
the trueLookupIndexListOffset/falseLookupIndexListOffset
pair in the LookupCondition record of newfeatvar_spec.pdf
to just lookupIndexListOffset (because one could just
follow the record<br>
with the "positive" condition set with another record with
the negated one when needed).</p>
<p>Skef<br>
</p>
</div>
_______________________________________________<br>
mpeg-otspec mailing list<br>
<a href="mailto:mpeg-otspec@lists.aau.at" target="_blank">mpeg-otspec@lists.aau.at</a><br>
<a href="https://lists.aau.at/mailman/listinfo/mpeg-otspec" rel="noreferrer" target="_blank">https://lists.aau.at/mailman/listinfo/mpeg-otspec</a><br>
</blockquote>
</div>
</blockquote>
</div>
</blockquote></div>