[MPEG-OTSPEC] Note on VARC conditions and condition set negation

Behdad Esfahbod behdad at behdad.org
Thu Apr 11 17:44:49 CEST 2024


Thanks Skef.

I think I found the right approach for this (taking ideas from COLRv1 paint
tree / graph). Ignoring your other proposals, we add these:

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:

struct ConditionAnd
{
  uint16 format; // 2
  uint16 conditionCount; // Number of conditions for this conjunction
expression.
  Offset32To<Condition> conditionOffsets[conditionCount];
}

struct ConditionOr
{
  uint16 format; // 3
  uint16 conditionCount; // Number of conditions for this disjunction
expression.
  Offset32To<Condition> conditionOffsets[conditionCount];
}

struct ConditionNegate
{
  uint16 format; // 4
  Offset32To<Condition> condition;
}

WDYT?
behdad
http://behdad.org/


On Thu, Apr 11, 2024 at 6:26 AM Skef Iterum <skef at skef.org> wrote:

> 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.
>
> 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.
>
> With arbitrary boolean expressions it's easy to fake up the if/else
> if/else. If you would have had
>
> if A
>     R
> else if B
>     S
> else if C
>     T
> else if D
>     U
> else
>     V
>
> you can just do
>
> if A
>     R
> if ~A & B
>     S
> if ~A & ~B & C
>     T
> if ~A & ~B & ~C & D
>     U
> if ~A & ~B & ~C & ~D
>     V
>
> at the cost of a bit more computation (typically).
>
> This kind of generality was (presumably) thought to be *over*-general for
> variable fonts, and I don't disagree. But it's worth noting what you lose
> if you lack *both* arbitrary boolean expressions *and* 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)
>
> if [A & C]
>     R
> else
>     S
>
> You can replace that with
>
> if [A & C]
>     R
> if ~[A & C]
>     S
>
> However, *at a single level* that doesn't extend further. So if you have
>
> if [A & C]
>     R
> else if [D & E]
>     S
> else
>     T
>
> (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.
>
> However, it seems like you can accomplish the equivalent with an extra
> level. Assume R, S, and T are "existing" components. Then you can just do
>
> a:
> if [D & E]
>     S
> if ~[D & E]
>     T
>
> b:
> if [A & C]
>     R
> if ~[A & C]
>     a
>
> Now b has the right qualities. In effect, a sometimes has the "wrong"
> contents when [A & C] applies but you never *see* it in that case.
>
> 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.
>
> Skef
> On 4/11/24 01:20, Behdad Esfahbod wrote:
>
> Hi Skef,
>
> 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.
>
> A "negate the rest" condition type sounds good to me.
>
> behdad
> http://behdad.org/
>
>
> On Mon, Apr 8, 2024 at 1:55 PM Skef Iterum via mpeg-otspec <
> mpeg-otspec at lists.aau.at> wrote:
>
>> A note on conditions as defined in WG03-varc-and-other-updates-03.pdf (up
>> for review tomorrow morning).
>>
>> 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.
>>
>> 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 *set* can be expensive and/or tricky. So I would recommend
>> that one of these two things change:
>>
>>    - The if/else if/.../else semantic is restored
>>    - Some way of negating a condition set is added to the specification
>>
>> 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:
>>
>> ConditionTableFormat5
>>
>> *Type                    Name                                Description*
>>
>> uint16                  Format                              Format (set
>> to 5)
>>
>> When present in a condition set this condition indicates the set should
>> apply when
>> at least one of the other conditions is false and not otherwise. That is,
>> it makes the
>> condition set apply when it would normally not and vice-versa. There
>> should be at
>> most one format 5 condition in a condition set and it should be the first.
>>
>> 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
>> with the "positive" condition set with another record with the negated
>> one when needed).
>>
>> Skef
>> _______________________________________________
>> mpeg-otspec mailing list
>> mpeg-otspec at lists.aau.at
>> https://lists.aau.at/mailman/listinfo/mpeg-otspec
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.aau.at/pipermail/mpeg-otspec/attachments/20240411/a81f0320/attachment.htm>


More information about the mpeg-otspec mailing list