<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <p>This proposal is a particular way of supporting arbitrary boolean
      expressions in OFF. That does have the benefit of "just doing it"
      -- it's certainly preferable to adding significantly more
      complexity while falling short of total generality.</p>
    <p>However, there were presumably reasons this route wasn't taken to
      begin with, probably having to do with complexity, and those would
      have to be discussed. I.e.: Is this too much rope? <br>
    </p>
    <p>This direction would be fine with me if it's fine with the group,
      but I feel that would a discussion for the upcoming, more onerous
      phase of work, not to squeeze in before the up coming deadline. <br>
    </p>
    <p>Skef<br>
    </p>
    <div class="moz-cite-prefix">On 4/11/24 08:44, Behdad Esfahbod
      wrote:<br>
    </div>
    <blockquote type="cite"
cite="mid:CAF63+7XmJ4m24+xmxYgdXgZSbU=354BewZJ8BC_vJj5YK2DM_A@mail.gmail.com">
      <meta http-equiv="content-type" content="text/html; charset=UTF-8">
      <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><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 dir="ltr" class="gmail_signature"
              data-smartmail="gmail_signature">behdad<br>
              <a href="http://behdad.org/" target="_blank"
                moz-do-not-send="true" class="moz-txt-link-freetext">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"
            moz-do-not-send="true" class="moz-txt-link-freetext">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">
          <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"
                        moz-do-not-send="true"
                        class="moz-txt-link-freetext">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" moz-do-not-send="true"
                    class="moz-txt-link-freetext">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" moz-do-not-send="true"
                    class="moz-txt-link-freetext">mpeg-otspec@lists.aau.at</a><br>
                  <a
href="https://lists.aau.at/mailman/listinfo/mpeg-otspec"
                    rel="noreferrer" target="_blank"
                    moz-do-not-send="true" class="moz-txt-link-freetext">https://lists.aau.at/mailman/listinfo/mpeg-otspec</a><br>
                </blockquote>
              </div>
            </blockquote>
          </div>
        </blockquote>
      </div>
    </blockquote>
  </body>
</html>