@@ -30,6 +30,9 @@ Markup Shorthands: markdown yes
3030[data-algorithm] :not(.heading) > :last-child {
3131 margin-bottom: 0;
3232}
33+ [data-algorithm] [data-algorithm] {
34+ margin: 1em 0;
35+ }
3336</style>
3437
3538<pre class=anchors>
@@ -723,26 +726,215 @@ The following are the arithmetic operations you can perform on dimensions:
723726 into another one with the specified |unit|.
724727 When called, it must perform the following steps:
725728
726- 1. If |unit| does not have a [=CSS type=] ,
727- [=throw=] a {{SyntaxError}}
728- and abort this algorithm .
729+ 1. Let |type| be the result of [=creating a type=] from |unit|.
730+ If |type| is failure,
731+ [=throw=] a {{SyntaxError}} .
729732
730- 2. If |this| is a {{CSSUnitValue}}
731- and |this|’s {{CSSUnitValue/unit}} internal slot and |unit| are [=compatible units=] ,
732- return a new {{CSSUnitValue}}
733- with its {{CSSUnitValue/unit}} internal slot set to |unit|
734- and its {{CSSUnitValue/value}} internal slot set to |this|’s {{CSSUnitValue/value}}
735- multiplied by the conversion ratio between the two units.
736-
737- 3. If |this| is a {{CSSCalcValue}} :
738- 1. Let |sum| be 0.
739- 2. [=map/For each=] |oldUnit| → |value| in |this|’s [=map entries=] :
740- 1. If |oldUnit| and |unit| are not [=compatible units=] ,
741- [=throw=] a {{TypeError}} .
742- 2. Increment |sum| by |value| times the conversion ratio between |oldUnit| and |unit|.
743- 3. Return a new {{CSSUnitValue}}
744- with its {{CSSUnitValue/unit}} internal slot set to |unit|
745- and its {{CSSUnitValue/value}} internal slot set to |sum|.
733+ 2. Let |sum| be the result of [=creating a sum value=] from |this|.
734+ If |sum| is failure,
735+ [=throw=] a {{TypeError}} .
736+
737+ 3. If |sum| has more than one [=list/item=] ,
738+ [=throw=] a {{TypeError}} .
739+ Otherwise, let |item| be the sole [=list/item=] in |sum|.
740+
741+ 4. If |item| has more than one [=map/value=] in its [=sum value/unit map=] ,
742+ or that single [=map/value=] ’s value is anything other than `1`,
743+ [=throw=] a {{TypeError}} .
744+ Otherwise, let |item unit| be the sole [=map/key=] in the [=sum value/unit map=] ,
745+ and |item value| be |item|’s [=sum value/value=] .
746+
747+ 5. If |unit| and |item unit| are not [=compatible units=] ,
748+ [=throw=] a {{TypeError}} .
749+
750+ 6. Return a new {{CSSUnitValue}}
751+ whose {{CSSUnitValue/unit}} internal slot
752+ is set to |unit|,
753+ and whose {{CSSUnitValue/value}} internal slot
754+ is set to |item value|
755+ multiplied by the conversion ratio between |item unit|
756+ and |unit|.
757+ </div>
758+
759+ <div algorithm="sum value">
760+ A <dfn>sum value</dfn>
761+ is an abstract representation of a {{CSSNumericValue}}
762+ as a sum of numbers with (possibly complex) units.
763+ Not all {{CSSNumericValue}} s can be expressed as a [=sum value=] .
764+
765+ A [=sum value=] is a [=list=] .
766+ Each entry in the list is a [=tuple=] of a <dfn for="sum value">value</dfn> ,
767+ which is a number,
768+ and a <dfn for="sum value">unit map</dfn> ,
769+ which is a [=ordered map|map=] of units (strings) to powers (integers).
770+
771+ <div class=example>
772+ Here are a few examples of CSS values,
773+ and their equivalent [=sum values=] :
774+
775+ * ''1px'' becomes `«(1, «"px"→1»)»`
776+ * ''calc(1px + 1in)'' becomes `«(97, «"px"→1»)»`
777+ (because ''in'' and ''px'' are [=compatible units=] ,
778+ and ''px'' is the [=canonical unit=] for them)
779+ * ''calc(1px + 2em)'' becomes `«(1, «"px"→1»), (2, «"em"→»1)»`
780+ * ''calc(1px * 2em)'' becomes `«(2, «"em"→1, "px"→1»)»`
781+ * ''calc(1px + 1deg)'' can't be represented as a [=sum value=]
782+ because it's an invalid computation
783+ * ''calc(1px * 1deg)'' becomes `«(2, «"deg"→1, "px"→1»)»`
784+ </div>
785+
786+ To <dfn lt="create a sum value|creating a sum value">create a sum value</dfn> from a {{CSSNumericValue}} |this|,
787+ the steps differ based on |this|’s class:
788+
789+ <dl class=switch>
790+ : {{CSSUnitValue}}
791+ ::
792+ <div algorithm="sum value from CSSUnitValue">
793+ 1. Let |unit| be the value of |this|’s {{CSSUnitValue/unit}} internal slot,
794+ and |value| be the value of |this|’s {{CSSUnitValue/value}} internal slot.
795+ 2. If |unit| is a member of a set of [=compatible units=] ,
796+ and is not the set's [=canonical unit=] ,
797+ multiply |value| by the conversion ratio between |unit| and the [=canonical unit=] ,
798+ and change |unit| to the [=canonical unit=] .
799+ 3. If |unit| is `"number"`,
800+ return «(|value|, «»)».
801+ 3. Otherwise, return <code> «(|value|, «|unit|→1»)»</code> .
802+ </div>
803+
804+ : {{CSSMathSum}}
805+ ::
806+ <div algorithm="sum value from CSSMathSum">
807+ 1. Let |values| initially be an empty list.
808+
809+ 2. [=list/For each=] |item| in |this|’s {{CSSMathSum/values}} internal slot:
810+
811+ 1. Let |value| be the result of [=creating a sum value=] from |item|.
812+ If |value| is failure,
813+ return failure.
814+
815+ 2. [=list/For each=] |subvalue| of |value|:
816+
817+ 1. If |values| already contains an [=list/item=]
818+ with the same [=sum value/unit map=] as |subvalue|,
819+ increment that [=list/item=] ’s [=sum value/value=]
820+ by the [=sum value/value=] of |subvalue|.
821+
822+ 2. Otherwise, [=list/append=] |subvalue| to |values|.
823+
824+ 3. [=create a type from a unit map|Create a type=]
825+ from the [=sum value/unit map=]
826+ of each [=list/item=] of |values|,
827+ and [=add=] all the types together.
828+ If the result is failure,
829+ return failure.
830+
831+ 4. Return |values|.
832+ </div>
833+
834+ : {{CSSMathNegate}}
835+ ::
836+ <div algorithm="sum value from CSSMathNegate">
837+ 1. Let |values| be the result of [=creating a sum value=]
838+ from |this|’s {{CSSMathNegate/value}} internal slot.
839+
840+ 2. If |values| is failure,
841+ return failure.
842+
843+ 3. Negate the [=sum value/value=] of each [=list/item=] of |values|.
844+
845+ 4. Return |values|.
846+ </div>
847+
848+ : {{CSSMathProduct}}
849+ ::
850+ <div algorithm="sum value from CSSMathProduct">
851+ 1. Let |values| initially be the [=sum value=] «(1, «»)».
852+ (I.e. what you'd get from ''1'' .)
853+
854+ 2. [=list/For each=] |item| in |this|’s {{CSSMathProduct/values}} internal slot:
855+
856+ 1. Let |new values| be the result of [=creating a sum value=] from |item|.
857+ Let |temp| initially be an empty [=list=] .
858+
859+ 2. [=list/For each=] |item1| in |values|:
860+
861+ 1. [=list/For each=] |item2| in |new values|:
862+
863+ 1. Let |item| be a [=tuple=] with its [=sum value/value=]
864+ set to the product of the [=sum value/values=] of |item1| and |item2|,
865+ and its [=sum value/unit map=]
866+ set to the union of the [=sum value/unit maps=] of |item1| and |item2|,
867+ with all [=map/entries=] with a zero value removed.
868+
869+ 2. Append |item| to |temp|.
870+
871+ 3. Set |values| to |temp|.
872+
873+ 3. Return |values|.
874+ </div>
875+
876+ : {{CSSMathInvert}}
877+ ::
878+ <div algorithm="sum value from CSSMathInvert">
879+ 1. Let |values| be the result of [=creating a sum value=]
880+ from |this|’s {{CSSMathInvert/value}} internal slot.
881+
882+ 2. If |values| is failure,
883+ return failure.
884+
885+ 3. If the length of [=values=] is more than one,
886+ return failure.
887+
888+ 3. Invert (find the reciprocal of) the [=sum value/value=] of the [=list/item=] in |values|,
889+ and negate the [=map/value=] of each [=map/entry=] in its [=sum value/unit map=] .
890+
891+ 4. Return |values|.
892+ </div>
893+
894+ : {{CSSMathMin}}
895+ ::
896+ <div algorithm="sum value from CSSMathMin">
897+ 1. Let |args| be the result of [=creating a sum value=]
898+ [=list/for each=] [=list/item=] in |this|’s {{CSSMathMin/values}} internal slot.
899+
900+ 2. If any [=list/item=] of |args| has a length greater than one,
901+ return failure.
902+
903+ 3. If not all of the [=sum value/unit maps=] among the [=list/items=] of |args| are identical,
904+ return failure.
905+
906+ 4. Return the [=list/item=] of |args| whose sole [=list/item=] has the smallest [=sum value/value=] .
907+ </div>
908+
909+ : {{CSSMathMax}}
910+ ::
911+ <div algorithm="sum value from CSSMathMax">
912+ 1. Let |args| be the result of [=creating a sum value=]
913+ [=list/for each=] [=list/item=] in |this|’s {{CSSMathMax/values}} internal slot.
914+
915+ 2. If any [=list/item=] of |args| has a length greater than one,
916+ return failure.
917+
918+ 3. If not all of the [=sum value/unit maps=] among the [=list/items=] of |args| are identical,
919+ return failure.
920+
921+ 4. Return the [=list/item=] of |args| whose sole [=list/item=] has the largest [=sum value/value=] .
922+ </div>
923+ </dl>
924+
925+ <div algorithm>
926+ To <dfn>create a type from a unit map</dfn> |unit map|:
927+
928+ 1. Let |types| be an initially empty [=list=] .
929+
930+ 2. [=map/For each=] |unit| → |power| in |unit map|:
931+
932+ 1. Let |type| be the result of [=creating a type=] from |unit|.
933+ 2. Set |type|’s sole [=map/value=] to |power|.
934+ 3. [=list/Append=] |type| to |types|.
935+
936+ 3. Return the result of [=multiplying=] all the [=list/items=] of |types|.
937+ </div>
746938</div>
747939
748940The {{CSSNumericValue/parse()}} method allows a {{CSSNumericValue}}
0 commit comments