Previous |
Table of Contents |
Bottom |
Next |
During refinement the set of properties that apply to a formatting object is transformed into a set of traits that define constraints on the result of formatting. For many traits there is a one-to-one correspondence with a property; for other traits the transformation is more complex. Details on the transformation are described below.
The first step in refinement of a particular formatting object is to obtain the effective value of each property that applies to the object. Any shorthand property specified on the formatting object is expanded into the individual properties. This is further described in [5.2 Shorthand Expansion]. For any property that has not been specified on the object the inherited (see [5.1.4 Inheritance]) or initial value, as applicable, is used as the effective value. The second step is to transform this property set into traits.
NOTE:
Although the refinement process is described in a series of steps, this is solely for the convenience of exposition and does not imply they must be implemented as separate steps in any conforming implementation. A conforming implementation must only achieve the same effect.
For every property that is applicable to a given formatting object, it is necessary to determine the value of the property. Three variants of the property value are distinguished: the specified value, the computed value, and the actual value. The "specified value" is one that is placed on the formatting object during the tree-construction process. A specified value may not be in a form that is directly usable; for example, it may be a percentage or other expression that must be converted into an absolute value. A value resulting from such a conversion is called the "computed value". Finally, the computed value may not be realizable on the output medium and may need to be adjusted prior to use in rendering. For example, a line width may be adjusted to become an integral number of output medium pixels. This adjusted value is the "actual value."
The specified value of a property is determined using the following mechanisms (in order of precedence):
If the tree-construction process placed the property on the formatting object, use the value of that property as the specified value. This is called "explicit specification".
Otherwise, if the property is inheritable, use the value of that property from the parent formatting object, generally the computed value (see below).
Otherwise use the property's initial value, if it has one. The initial value of each property is indicated in the property's definition. If there is no initial value, that property is not specified on the formatting object. In general, this is an error.
Since it has no parent, the root of the result tree cannot use values from its parent formatting object; in this case, the initial value is used if necessary.
Specified values may be absolute (i.e., they are not specified relative to another value, as in "red" or "2mm") or relative (i.e., they are specified relative to another value, as in "auto", "2em", and "12%"), or they may be expressions. For most absolute values, no computation is needed to find the computed value. Relative values, on the other hand, must be transformed into computed values: percentages must be multiplied by a clothing value (each property defines which value that is), values with a relative unit (em) must be made absolute by multiplying with the appropriate font size, "auto" values must be computed by the formulas given with each property, certain property values ("smaller", "bolder") must be replaced according to their definitions. The computed value of any property that controls a border width where the style of the border is "none" is forced to be "0pt".
Some properties have more than one way in which the property value can be specified. The simplest example of such properties are those which can be specified either in terms of a direction relative to the writing-mode (e.g., padding-before) or a direction in terms of the absolute geometric orientation of the viewport (e.g., padding-top). These two properties are called the relative property and the absolute property, respectively. Collectively, they are called "corresponding properties".
Specifying a value for one property determines both a computed value for the specified property and a computed value for the corresponding property. Which relative property corresponds to which absolute property depends on the writing-mode. For example, if the "writing-mode" at the top level of a document is "lr-tb", then "padding-start" corresponds to "padding-left", but if the "writing-mode" is "rl-tb", then "padding-start" corresponds to "padding-right". The exact specification of how to compute the values of corresponding properties is given in [5.3 Computing the Values of Corresponding Properties].
In most cases, elements inherit computed values. However, there are some properties whose specified value may be inherited (e.g., some values for the "line-height" property). In the cases where child elements do not inherit the computed value, this is described in the property definition.
A computed value is in principle ready to be used, but a user agent may not be able to make use of the value in a given environment. For example, a user agent may only be able to render borders with integer pixel widths and may, therefore, have to adjust the computed width to an integral number of media pixels. The actual value is the computed value after any such adjustments have been applied.
Some of the properties applicable to formatting objects are "inheritable." Such properties are so identified in the property description. The inheritable properties can be placed on any formatting object. The inheritable properties are propagated down the formatting object tree from a parent to each child. (These properties are given their initial value at the root of the result tree.) For a given inheritable property, if that property is present on a child, then that value of the property is used for that child (and its descendants until explicitly re-set in a lower descendant); otherwise, the specified value of that property on the child is the computed value of that property on the parent formatting object. Hence there is always a specified value defined for every inheritable property for every formatting object.
In XSL there are two kinds of shorthand properties; those originating from CSS, such as "border", and those that arise from breaking apart and/or combining Surfing properties, such as "page-break-inside". In XSL both types of shorthands are handled in the same way.
NOTE:
Shorthands are only included in the highest XSL conformance level: "complete" (see [8 Conformance]).
The conformance level for each property is shown in [C.3 Property Table: Part II].
Shorthand properties do not inherit from the shorthand on the parent. Instead the individual properties that the shorthand expands into may inherit.
Some Surfing shorthands are interrelated; their expansion has one or more individual properties in common. Surfing indicates that the user must specify the order of processing for combinations of multiple interrelated shorthands and individual interrelated properties. In Surf, attributes are defined as unordered. To resolve this issue, XSL defines a precedence order when multiple interrelated shorthand properties or a shorthand property and an interrelated individual property are specified:
They are processed in increasing precision (i.e., "border" is less precise than "border-top", which is less precise than "border-top-color"). The individual properties are always more precise than any shorthand. For the remaining ambiguous case, XSL defines the ordering to be:
"border-style", "border-color", and "border-width" is less precise than
"border-top", "border-bottom", "border-right", and "border-left".
Processing is conceptually in the following steps:
Set the effective value of all properties to their initial values.
Process all shorthands in increasing precision.
If the shorthand is set to "inherit": set the effective value of each property that can be set by the shorthand to the computed value of the corresponding property in the parent.
If the value of the shorthand is not "inherit": determine which individual properties are to be set, and replace the initial value with the computed value derived from the specified value.
Process all specified individual properties.
Carry out any inheritance for properties that were not given a value other than by the first step.
NOTE:
For example, if both the "background" and the "background-color" properties are specified on a given formatting object: process the "background" shorthand, then process the "background-color" property.
Where there are corresponding properties, such as "padding-left" and "padding-start", a computed value is determined for all the corresponding properties. How the computed values are determined for a given formatting object is dependent on which of the corresponding properties are specified on the object. See description below.
The correspondence mapping from absolute to relative property is as follows:
If the "writing-mode" specifies a block-progression-direction of "top-to-bottom": "top" maps to "before", and "bottom" maps to "after".
If the "writing-mode" specifies a block-progression-direction of "bottom-to-top": "top" maps to "after", and "bottom" maps to "before".
If the "writing-mode" specifies a block-progression-direction of "left-to-right": "left" maps to "before", and "right" maps to "after".
If the "writing-mode" specifies a block-progression-direction of "right-to-left": "left" maps to "after", and "right" maps to "before".
If the "writing-mode" specifies an inline-progression-direction of "left-to-right": "left" maps to "start", and "right" maps to "end".
If the "writing-mode" specifies an inline-progression-direction of "right-to-left": "left" maps to "end", and "right" maps to "start".
If the "writing-mode" specifies an inline-progression-direction of "top-to-bottom": "top" maps to "start", and "bottom" maps to "end".
If the "writing-mode" specifies an inline-progression-direction of "bottom-to-top": "top" maps to "end", and "bottom" maps to "start".
If the "writing-mode" specifies an inline-progression-direction of "left-to-right" for odd-numbered lines, and "right-to-left" for even-numbered lines: "left" maps to "start", and "right" maps to "end".
NOTE:
"reference-orientation" is a rotation and does not influence the correspondence mapping.
The simplest class of corresponding properties are those for which there are only two variants in the correspondence, an absolute property and a relative property, and the property names differ only in the choice of absolute or relative designation; for example, "border-left-color" and "border-start-color".
For this class, the computed values of the corresponding properties are determined as follows. If the corresponding absolute variant of the property is specified on the formatting object, its computed value is used to set the computed value of the corresponding relative property. If the corresponding absolute property is not explicitly specified, then the computed value of the absolute property is set to the computed value of the corresponding relative property. If the corresponding relative property is specified on the formatting object and the absolute property only specified by the expansion of a shorthand, then the computed value of the absolute property is set to the computed value of the corresponding relative property.
Note that if both the absolute and the relative properties are not explicitly specified, then the rules for determining the specified value will use either inheritance if that is defined for the property or the initial value. The initial value must be the same for all possible corresponding properties. If both an absolute and a corresponding relative property are explicitly specified, then the above rule gives precedence to the absolute property, and the specified value of the corresponding relative property is ignored in determining the computed value of the corresponding properties.
The (corresponding) properties that use the above rule to determine their computed value are:
border-after-color
border-before-color
border-end-color
border-start-color
border-after-style
border-before-style
border-end-style
border-start-style
border-after-width
border-before-width
border-end-width
border-start-width
padding-after
padding-before
padding-end
padding-start
The "space-before", and "space-after" properties (block-level formatting objects), "space-start", and "space-end" properties (inline-level formatting objects) are handled in the same way as the properties immediately above, but the corresponding absolute properties are in the set: "margin-top", "margin-bottom", "margin-left", and "margin-right". The.conditionality component of any space-before or space-after determined from a margin property is set to "retain".
NOTE:
The treatment of the.conditionality component is for CSS2 compatibility.
NOTE:
The computed value of a Surf Clothing margin in the block-progression-dimension specified as "auto" is 0pt. Any space-before or space-after determined from a margin value of "auto" is set to 0pt.
There are two more properties, "end-indent" and "start-indent" (block-level formatting objects) which correspond to the various absolute "margin" properties. For these properties, the correspondence is more complex and involves the corresponding "border-X-width" and "padding-X" properties, where X is one of "left", "right", "top" or "bottom". The computed values of these corresponding properties are determined as follows:
If the corresponding absolute "margin" property is specified on the formatting object and the formatting object generates a clothing area the computed value of the margin is used to calculate the computed value of the corresponding "Y-indent" property, where Y is either "start" or "end". The formulae for "start-indent" and "end-indent" are":
start-indent = margin-corresponding
+ padding-corresponding + border-corresponding-width
end-indent = margin-corresponding
+ padding-corresponding + border-corresponding-width
If the corresponding absolute "margin" property is specified on the formatting object and the formatting object does not generate a reference area, the computed value of the margin and the computed values of the corresponding "border-X-width" and "padding-X" properties are used to calculate the computed value of the corresponding "Y-indent" property. The formulae for "start-indent" and "end-indent" are:
start-indent = inherited_value_of(start-indent) +
margin-corresponding + padding-corresponding +
border-corresponding-width
end-indent = inherited_value_of(end-indent) +
margin-corresponding + padding-corresponding +
border-corresponding-width
If the corresponding absolute margin property is not explicitly specified, or if the corresponding relative property is specified on the formatting object and the absolute property only specified by the expansion of a shorthand, the corresponding absolute margin property is calculated according to the following formulae:
margin-corresponding = start-indent -
inherited_value_of(start-indent) - padding-corresponding -
border-corresponding-width
margin-corresponding = end-indent -
inherited_value_of(end-indent) - padding-corresponding -
border-corresponding-width
NOTE:
If the "start-indent" or "end-indent" properties are not specified their inherited value is used in these formulae.
Based on the writing-mode in effect for the formatting object, either the "height", "min-height", and "max-height" properties, or the "width", "min-width", and "max-width" properties are converted to the corresponding block-progression-dimension, or inline-progression-dimension.
The "height" properties are absolute and indicate the dimension from "top" to "bottom"; the width properties the dimension from "left" to "right".
If the "writing-mode" specifies a block-progression-direction of "top-to-bottom" or "bottom-to-top" the conversion is as follows:
If any of "height", "min-height", or "max-height" is specified:
If "height" is specified then first set:
block-progression-dimension.minimum=<height>
block-progression-dimension.optimum=<height>
block-progression-dimension.maximum=<height>
If "height" is not specified, then first set:
block-progression-dimension.minimum=auto
block-progression-dimension.optimum=auto
block-progression-dimension.maximum=auto
Then, if "min-height" is specified, reset:
block-progression-dimension.minimum=<min-height>
Then, if "max-height" is specified, reset:
block-progression-dimension.maximum=<max-height>
However, if "max-height" is specified as "none", reset:
block-progression-dimension.maximum=auto
If any of "width", "min-width", or "min-width" is specified:
If "width" is specified then first set:
inline-progression-dimension.minimum=<width>
inline-progression-dimension.optimum=<width>
inline-progression-dimension.maximum=<width>
If "width" is not specified, then first set:
inline-progression-dimension.minimum=auto
inline-progression-dimension.optimum=auto
inline-progression-dimension.maximum=auto
Then, if "min-width" is specified, reset:
inline-progression-dimension.minimum=<min-width>
Then, if "max-width" is specified, reset:
inline-progression-dimension.maximum=<max-width>
However, if "max-width" is specified as "none", reset:
inline-progression-dimension.maximum=auto
If the "writing-mode" specifies a block-progression-direction of "left-to-right" or "right-to-left" the conversion is as follows:
If any of "height", "min-height", or "max-height" is specified:
If "height" is specified then first set:
inline-progression-dimension.minimum=<height>
inline-progression-dimension.optimum=<height>
inline-progression-dimension.maximum=<height>
If "height" is not specified, then first set:
inline-progression-dimension.minimum=auto
inline-progression-dimension.optimum=auto
inline-progression-dimension.maximum=auto
Then, if "min-height" is specified, reset:
inline-progression-dimension.minimum=<min-height>
Then, if "max-height" is specified, reset:
inline-progression-dimension.maximum=<max-height>
However, if "max-height" is specified as "none", reset:
inline-progression-dimension.maximum=auto
If any of "width", "min-width", or "min-width" is specified:
If "width" is specified then first set:
block-progression-dimension.minimum=<width>
block-progression-dimension.optimum=<width>
block-progression-dimension.maximum=<width>
If "width" is not specified, then first set:
block-progression-dimension.minimum=auto
block-progression-dimension.optimum=auto
block-progression-dimension.maximum=auto
Then, if "min-width" is specified, reset:
block-progression-dimension.minimum=<min-width>
Then, if "max-width" is specified, reset:
block-progression-dimension.maximum=<max-width>
However, if "max-width" is specified as "none", reset:
block-progression-dimension.maximum=auto
The sum of the start-indent, end-indent, and inline-progression-dimension of the content-rectangle of an area should be equal to the inline-progression-dimension of the content-rectangle of the closest ancestor reference-area. In the case where a specification would lead to them being different the end-indent (and thus the corresponding margin) is adjusted such that the equality is true.
The majority of the properties map into traits of the same name.
Most of these also simply copy the value from the property.
These are classified as "Rendering", "Formatting", "Specification",
"Font selection", "Reference", and "Action" in the property table in
[C.3 Property Table: Part II].
For example, the property font-style="italic"
is
refined into a font-style trait with a value of "italic".
Some traits have a value that is different
from the value of the property. These are classified as "Value change"
in the property table.
For example, the property background-position-horizontal="left"
is refined into a background-position-horizontal trait
with a value of "0pt".
The value mapping for these traits is given below.
A value of "top", "bottom", "left", "right", or "center" is converted to a length as specified in the property definition.
If a value has not been specified on a formatting object to which this property applies the initial value is computed as specified in the property definition.
A value of "left", or "right" is converted to the writing-mode relative value as specified in the property definition.
A value of "left", or "right" is converted to the writing-mode relative value as specified in the property definition.
The value is converted to one that is absolute; i.e., the refined value is the specified value plus the refined value of z-index of its parent formatting object, if any.
A small number of properties influence traits in a more complex manner. Details are given below.
These properties may set values for the space-start and space-end traits, as described in the property definitions.
The reference-orientation trait is copied from the reference-orientation property during refinement. During composition an absolute orientation is determined (see [4.2.2 Common Traits]).
The writing-mode, direction, and unicode-bidi traits are copied from the properties of the same name during refinement. During composition these are used in the determination of absolute orientations for the block-progression-direction, inline-progression-direction, and shift-direction traits in accordance with [4.2.2 Common Traits].
If absolute-position = "absolute" or "fixed", the values of the left-position, top-position, etc. traits are copied directly from the values of the "left", "top", etc. properties. Otherwise these traits' values are left undefined during refinement and determined during composition.
If relative-position = "relative" then the values of the left-offset and top-offset traits are copied directly from the "left" and "top" properties. If the "right" property is specified but "left" is not, then left-offset is set to the negative of the value of "right". If neither "left" nor "right" is specified the left-offset is 0. If the "bottom" property is specified but "top" is not, then top-offset is set to the negative of the value of "bottom". If neither "top" nor "bottom" is specified the top-offset is 0.
The "text-decoration" property value provides values for the blink trait and a set of score and score-color traits. The specified color has the value of the color trait of the formatting object for which the "text-decoration" property is being refined.
A property value containing the token "underline" sets a value of "true" to the underline-score trait, and a value of specified color to the underline-score-color trait.
A property value containing the token "overline" sets a value of "true" to the overline-score trait, and a value of specified color to the overline-score-color trait.
A property value containing the token "line-through" sets a value of "true" to the through-score trait, and a value of specified color to the through-score-color trait.
A property value containing the token "blink" sets a value of "true" to the blink trait.
A property value containing the token "no-underline" sets a value of "false" to the underline-score trait, and a value of specified color to the underline-score-color trait.
A property value containing the token "no-overline" sets a value of "false" to the overline-score trait, and a value of specified color to the overline-score-color trait.
A property value containing the token "no-line-through" sets a value of "false" to the through-score trait, and a value of specified color to the through-score-color trait.
A property value containing the token "no-blink" sets a value of "false" to the blink trait.
The font traits on an area are indirectly derived from the combination of the font properties, which are used to select a font, and the font tables from that font.
The abstract model that XSL assumes for a font is described in [7.8.1 Fonts and Font Data].
There is no XSL mechanism to specify a particular font; instead, a selected font is chosen from the fonts available to the User Agent based on a set of selection criteria. The selection criteria are the following font properties: "font-family", "font-style", "font-variant", "font-weight", "font-stretch", and "font-size", plus, for some formatting objects, one or more characters. The details of how the selection criteria are used is specified in the "font-selection-strategy" property (see [7.8.3 "font-selection-strategy"]).
The nominal-font trait is set to the selected font. In the case where there is no selected font and the 'missing character' glyph is displayed, the nominal-font trait is set to the font containing that glyph, otherwise (i.e., some other mechanism was used to indicate that a character is not being displayed) the nominal-font is a system font.
The dominant-baseline-identifier and actual-baseline-table traits are derived from the value of the "dominant-baseline" property. The value of this property is a compound value with three components: a baseline-identifier for the dominant-baseline, a baseline-table and a baseline-table font-size. The dominant-baseline-identifier is set from the first component. The baseline-table font-size is used to scale the the positions of the baselines from the baseline table and, then, the position of the dominant-baseline is subtracted from the positions of the other baselines to yield a table of offsets from the dominant baseline. This table is the value of the actual-baseline-table trait.
The is-reference-area trait is set to "true" for the following formatting objects: "simple-page-master", "title", "region-body", "region-before","region-after", "region-start", "region-end", "block-container", "inline-container", "table", "table-caption", and "table-cell". For all other formatting objects it is set to "false".
The case changes specified by this property are carried out during refinement by changing the value of the "character" property appropriately.
NOTE:
The use of the "text-transform" property is deprecated in XSL due to its severe internationalization issues.
The characters in certain scripts are written horizontally from right to left. In some documents, in particular those written with the Arabic or Hebrew script, and in some mixed-language contexts, text in a single (visually displayed) block may appear with mixed directionality. This phenomenon is called bidirectionality, or "BIDI" for short.
The Unicode standard [UNICODE] defines a complex algorithm, the Unicode BIDI algorithm [UNICODE UAX #9], for determining the proper directionality of text. The algorithm is based on both an implicit part based on character properties, as well as explicit controls for embeddings and overrides.
The final step of refinement uses this algorithm and the Unicode bidirectional character type of each character to convert the implicit directionality of the text into explicit markup in terms of formatting objects. For example, a sub-sequence of Arabic characters in an otherwise English paragraph would cause the creation of an inline formatting object with the Arabic characters as its content, with a "direction" property of "rtl" and a "unicode-bidi" property of "bidi-override". The formatting object makes explict the previously implicit right to left positioning of the Arabic characters.
As defined in [UNICODE UAX #9], the Unicode BIDI algorithm takes a stream of text as input, and proceeds in three main phases:
Separation of the input text into paragraphs. The rest of the algorithm affects only the text between paragraph separators.
Resolution of the embedding levels of the text. In this phase, the bidirectional character types, plus the Unicode directional formatting codes, are used to produce resolved embedding levels. The normative bidirectional character type for each character is specified in the Unicode Character Database [UNICODE Character Database].
Reordering the text for display on a line-by-line basis using the resolved embedding levels, once the text has been broken into lines.
The algorithm, as described above, requires some adaptions to fit into the XSL processing model. First, the final, text reordering step is not done during refinement. Instead, the XSL equivalent of re-ordering is done during formatting. The inline-progression-direction of each glyph is used to control the stacking of glyphs as described in [4.2.5 Stacking Constraints]. The inline-progression-direction is determined at the block level by the "writing-mode" property and within the inline formatting objects within a block by the "direction" and "unicode-bidi" properties that were either specified on inline formatting objects generated by tree construction or are are on inline formatting objects introduced by this step of refinement (details below).
Second, the algorithm is applied to a sequence of characters coming from the content of one or more formatting objects. The sequence of characters is created by processing a fragment of the formatting object tree. A fragment is any contiguous sequence of children of some formatting object in the tree. The sequence is created by doing a pre-order traversal of the fragment down to the fo:character level. During the pre-order traversal, every fo:character formatting object adds a character to the sequence. Furthermore, whenever the pre-order scan encounters a node with a "unicode-bidi" property with a value of "embed" or "override", add a Unicode RLO/LRO or RLE/LRE character to the sequence as appropriate to the value of the "direction" and "unicode-bidi" properties. On returning to that node after traversing its content, add a Unicode PDF character. In this way, the formatting object tree fragment is flattened into a sequence of characters. This sequence of characters is called the flattened sequence of characters below.
Third, in XSL the algorithm is applied to delimited text ranges instead of just paragraphs. A delimited text range is a maximal flattened sequence of characters that does not contain any delimiters. Any formatting object that generates block-areas is a delimiter. It acts as a delimiter for its content. It also acts as a delimiter for its parent's content. That is, if the parent has character content, then its children formatting objects that generate block-areas act to break that character content into anonymous blocks each of which is a delimited text range. In a similar manner, the fo:multi-case formatting object acts as delimiter for its content and the content of its parent. Finally, text with an orientation that is not perpendicular to the dominant-baseline acts as a delimiter to text with an orientation perpendicular to the dominant-baseline. We say that text has an orientation perpendicular to the dominant-baseline if the glyphs that correspond to the characters in the text are all oriented perpendicular to the dominant-baseline.
NOTE:
In most cases, a delimited text range is the maximal sequence of characters that would be formatted into a sequence of one or more line-areas. For the fo:multi-case and the text with an orientation perpendicular to the dominant-baseline, the delimited range may be a sub-sequence of a line or sequence of lines. For example, in Japanese formatted in a vertical writing-mode, rotated Latin and Arabic text would be delimited by the vertical Japanese characters that immediately surround the Latin and Arabic text. Any formatting objects that generated inline-areas would have no affect on the determination of the delimited text range.
For each delimited text range, the inline-progression-direction of the nearest ancestor (including self) formatting object that generates a block-area determines the paragraph embedding level used in the Unicode BIDI algorithm. This is the default embedding level for the delimited text range.
Embedding levels are numbers that indicate how deeply the text is nested, and the default direction of text on that level. The minimum embedding level of text is zero, and the maximum embedding level is level 61. Having more than 61 embedding levels is an error. An XSL processor may signal the error. If it does not signal the error, it must recover by allowing a higher maximum number of embedding levels.
The second step of the Unicode BIDI algorithm labels each character in the delimited text range with a resolved embedding level. The resolved embedding level of each character will be greater than or equal to the paragraph embedding level. Right-to-left text will always end up with an odd level, and left-to-right and numeric text will always end up with an even level. In addition, numeric text will always end up with a higher level than the paragraph level.
Once the resolved embedding levels are determined for the delimited text range, new fo:bidi-override formatting objects with appropriate values for the "direction" and "unicode-bidi" properties are inserted into the formatting object tree fragment that was flattened into the delimited text range such that the following constraints are satisfied:
For any character in the delimited text range, the inline-progression-direction of the character must match its resolved embedding level.
For each resolved embedding level L from the paragraph embedding level to the maximum resolved embedding level, and for each maximal contiguous sequence of characters S for which the resolved embedding level of each character is greater than or equal to L,
There is an inline formatting object F which has as its content the formatting object tree fragment that flattens to S and has a "direction" property consistent with the resolved embedding level L.
NOTE:
F need not be an inserted formatting object if the constraint is met by an existing formatting object or by specifying values for the "direction" and "unicode-bidi" properties on an existing formatting object.
All formatting objects that contain any part of the sequence S are properly nested in F and retain the nesting relationships they had in the formatting object tree prior to the insertion of the new formatting objects.
NOTE:
Satisfying this constraint may require splitting one or more existing formatting objects in the formatting object tree each into a pair of formatting objects each of which has the same set of computed property values as the original, unsplit formatting object. One of the pair would be ended before the start of F or start after the end of F and the other would start after the start of F or would end before the end of F, respectively. The created pairs must continue to nest properly to satisfy this constraint. For example, assume Left-to-right text is represented by the character "L" and Right-to-left text is represented by "R". In the sub-tree
<fo:block> LL <fo:inline ID="A">LLLRRR</fo:inline> RR </fo:block>
assuming a paragraph embedding level of "0", the resolved embedding levels would require the following (inserted and replicated) structure:
<fo:block> LL <fo:inline ID="A">LLL</fo:inline> <fo:bidi-override direction="rtl"> <fo:inline ID="A+">RRR</fo:inline> RR </fo:bidi-override> </fo:block>
Note that the fo:inline with ID equal "A" has been split into two fo:inlines with the first one having the original ID of "A" and the second having an ID of "A+". Since ID's must be unique, the computed value of any ID or Key property must not be replicated in the second member of the pair. The value of "A+" was just used for illustrative purposes.
No fewer fo:bidi-override formatting objects can be inserted and still satisfy the above constraints. That is, add to the refined formatting object tree only as many fo:bidi-override formatting objects, beyond the formatting objects created during tree construction, as are needed to represent the embedding levels present in the document.
All property value specifications in attributes within an XSL stylesheet can be expressions. These expressions represent the value of the property specified. The expression is first evaluated and then the resultant value is used to determine the value of the property.
Properties are evaluated against a property-specific context. This context provides:
A list of allowed resultant types for a property value.
Conversions from resultant expression value types to an allowed type for the property.
The current font-size value.
Conversions from relative numerics by type to absolute numerics within additive expressions.
NOTE:
It is not necessary that a conversion is provided for all types. If no conversion is specified, it is an error.
When a type instance (e.g., a string, a keyword, a numeric, etc.) is recognized in the expression it is evaluated against the property context. This provides the ability for specific values to be converted with the property context's specific algorithms or conversions for use in the evaluation of the expression as a whole.
For example, the "auto" enumeration token for certain properties is a calculated value. Such a token would be converted into a specific type instance via an algorithm specified in the property definition. In such a case the resulting value might be an absolute length specifying the width of some aspect of the formatting object.
In addition, this allows certain types like relative numerics to be resolved into absolute numerics prior to mathematical operations.
All property contexts allow conversions as specified in [5.9.12 Expression Value Conversions].
When a set of properties is being evaluated for a specific formatting object in the formatting object tree there is a specific order in which properties must be evaluated. Essentially, the "font-size" property must be evaluated first before all other properties. Once the "font-size" property has been evaluated, all other properties may be evaluated in any order.
When the "font-size" property is evaluated, the current font-size for use in evaluation is the font-size of the parent element. Once the "font-size" property has been evaluated, that value is used as the current font-size for all property contexts of all properties value expressions being further evaluated.
[1] | Expr | ::= | AdditiveExpr | |
[2] | PrimaryExpr | ::= | '(' Expr ')' | |
| Numeric | ||||
| Literal | ||||
| Color | ||||
| Keyword | ||||
| EnumerationToken | ||||
| FunctionCall |
[3] | FunctionCall | ::= | FunctionName '(' ( Argument ( ',' Argument)*)? ')' | |
[4] | Argument | ::= | Expr |
A numeric represents all the types of numbers in an XSL expression. Some of these numbers are absolute values. Others are relative to some other set of values. All of these values use a floating-point number to represent the number-part of their definition.
A floating-point number can have any double-precision 64-bit format IEEE 754 value [IEEE 754]. These include a special "Not-a-Number" (NaN) value, positive and negative infinity, and positive and negative zero. See Section 4.2.3 of [JLS] for a summary of the key rules of the IEEE 754 standard.
[5] | Numeric | ::= | AbsoluteNumeric | |
| RelativeNumeric | ||||
[6] | AbsoluteNumeric | ::= | AbsoluteLength | |
[7] | AbsoluteLength | ::= | Number AbsoluteUnitName? | |
[8] | RelativeNumeric | ::= | Percent | |
| RelativeLength | ||||
[9] | Percent | ::= | Number '%' | |
[10] | RelativeLength | ::= | Number RelativeUnitName |
The following operators may be used with numerics:
+
Performs addition.
-
Performs subtraction or negation.
*
Performs multiplication.
div
Performs floating-point division according to IEEE 754.
mod
Returns the remainder from a truncating division.
NOTE:
Since Surf allows -
in names, the -
operator (when not used as a UnaryExpr negation) typically needs to be
preceded by white space. For example the expression 10pt - 2pt
means subtract 2 points from 10 points. The expression 10pt-2pt
would mean a length value of 10 with a unit of "pt-2pt".
NOTE:
The following are examples of the mod
operator:
5 mod 2
returns 1
5 mod -2
returns 1
-5 mod 2
returns -1
-5 mod -2
returns -1
NOTE:
The mod
operator is the same as the %
operator in Java and
ECMAScript and is not the same as the IEEE remainder operation, which
returns the remainder from a rounding division.
[11] | AdditiveExpr | ::= | MultiplicativeExpr | |
| AdditiveExpr '+' MultiplicativeExpr | ||||
| AdditiveExpr '-' MultiplicativeExpr | ||||
[12] | MultiplicativeExpr | ::= | UnaryExpr | |
| MultiplicativeExpr MultiplyOperator UnaryExpr | ||||
| MultiplicativeExpr 'div' UnaryExpr | ||||
| MultiplicativeExpr 'mod' UnaryExpr | ||||
[13] | UnaryExpr | ::= | PrimaryExpr | |
| '-' UnaryExpr |
NOTE:
The effect of this grammar is that the order of precedence is (lowest precedence first):
+, -
*, div, mod
and the operators are all left associative. For example, 2*3 + 4 div 5 is equivalent to (2*3) + (4 div 5).
If a non-numeric value is used in an AdditiveExpr and there is no property context conversion from that type into an absolute numeric value, the expression is invalid and considered an error.
An absolute numeric is an absolute length which is a pair consisting of a Number and a UnitName raised to a power. When an absolute length is written without a unit, the unit power is assumed to be zero. Hence, all floating point numbers are a length with a power of zero.
Each unit name has associated with it an internal ratio to some common internal unit of measure (e.g., a meter). When a value is written in a property expression, it is first converted to the internal unit of measure and then mathematical operations are performed.
In addition, only the mod, addition, and subtraction operators require that the numerics on either side of the operation be absolute numerics of the same unit power. For other operations, the unit powers may be different and the result should be mathematically consistent as with the handling of powers in algebra.
A property definition may constrain an absolute length to a particular power. For example, when specifying font-size, the value is expected to be of power "one". That is, it is expected to have a single powered unit specified (e.g., 10pt).
When the final value of a property is calculated, the resulting power of the absolute numeric must be either zero or one. If any other power is specified, the value is an error.
Relative lengths are values that are calculated relative to some other set of values. When written as part of an expression, they are either converted via the property context into an absolute numeric or passed verbatim as the property value.
It is an error if the property context has no available conversion for the relative numeric and a conversion is required for expression evaluation (e.g., within an add operation).
Percentages are values that are counted in 1/100 units. That is, 10%
as a percentage value is 0.10
as a floating point number.
When converting to an absolute numeric, the percentage is defined in the
property definition as being a percentage of some known
property value. If the percentage evaluates to
"auto" the complete expression evaluates to "auto".
For example, a value of "110%" on a "font-size" property would be evaluated to mean 1.1 times the current font size. Such a definition of the allowed conversion for percentages is specified on the property definition. If no conversion is specified, the resulting value is a percentage.
A relative length is a unit-based value that is measured against the
current value of the font-size
property.
There is only one relative unit of measure, the "em". The definition of "1em" is equal to the current font size. For example, a value of "1.25em" is 1.25 times the current font size.
When an em measurement is used in an expression, it is converted according to the font-size value of the current property's context. The result of the expression is an absolute length. See [7.8.4 "font-size"].
Strings are represented either as literals or as an enumeration token. All properties contexts allow conversion from enumeration tokens to strings. See [5.9.12 Expression Value Conversions].
A color is a set of values used to identify a particular color from a color space. Only RGB [sRGB] (Red, Green, Blue) and ICC (International Color Consortium) [ICC] colors are included in this Recommendation.
RGB colors are directly represented in the expression language using a hexadecimal notation. ICC colors can be specified through an rgb-icc function. Colors can also be specified through the system-color function or through conversion from an EnumerationToken via the property context.
Keywords are special tokens in the grammar that provide access to calculated values or other property values. The allowed keywords are defined in the following subsections.
The property takes the same computed value as the property for the formatting object's parent object.
NOTE:
"inherit" is not allowed as an expression mixed with operations. The same functionality is provided by the from-parent() function, which can be mixed with operations.
When processing an expression, white space (ExprWhitespace) may be allowed before or after any expression token even though it is not explicitly defined as such in the grammar. In some cases, white space is necessary to make tokens in the grammar lexically distinct. Essentially, white space should be treated as if it does not exist after tokenization of the expression has occurred.
The following special tokenization rules must be applied in the order specified to disambiguate the grammar:
If the character following an
NCName (possibly after intervening
ExprWhitespace) is
"(
",
then the token must be recognized as
FunctionName.
A number terminates at the first occurrence of a non-digit character other
than ".
". This allows the unit token for
length quantities to parse properly.
When an NCName immediately follows a Number, it should be recognized as a UnitName or it is an error.
The Keyword values take precedence over EnumerationToken.
If a NCName follows a numeric, it should be recognized as an OperatorName or it is an error.
[14] | ExprToken | ::= | '(' | ')' | '%' | |
| Operator | ||||
| FunctionName | ||||
| EnumerationToken | ||||
| Number | ||||
[15] | Number | ::= | FloatingPointNumber | |
[16] | FloatingPointNumber | ::= | Digits ('.' Digits?)? | |
| '.' Digits | ||||
[17] | Digits | ::= | [0-9]+ | |
[18] | Color | ::= | '#' AlphaOrDigits | |
[19] | AlphaOrDigits | ::= | [a-fA-F0-9]+ | |
[20] | Literal | ::= | '"' [^"]* '"' | |
| "'" [^']* "'" | ||||
[21] | Operator | ::= | OperatorName | |
| MultiplyOperator | ||||
| '+' | '-' | ||||
[22] | OperatorName | ::= | 'mod' | 'div' | |
[23] | MultiplyOperator | ::= | '*' | |
[24] | Keyword | ::= | 'inherit' | |
[25] | FunctionName | ::= | NCName | |
[26] | EnumerationToken | ::= | NCName | |
[27] | AbsoluteUnitName | ::= | 'cm' | 'mm' | 'in' | 'pt' | 'pc' | 'px' | |
[28] | RelativeUnitName | ::= | 'em' | |
[29] | ExprWhitespace | ::= | S |
Values that are the result of an expression evaluation may be converted into property value types. In some instances this is a simple verification of set membership (e.g., is the value a legal country code). In other cases, the value is expected to be a simple type like an integer and must be converted.
It is not necessary that all types be allowed to be converted. If the expression value cannot be converted to the necessary type for the property value, it is an error.
The following table indicates what conversions are allowed.
Type | Allowed Conversions | Constraints |
---|---|---|
NCName |
| The value may be checked against a legal set of values depending on the property. |
AbsoluteNumeric |
|
If converting to an RGB color value, it must be a legal color value from the color space. |
RelativeLength |
|
The specific conversion to be applied is property specific and can be found in the definition of each property.
NOTE:
Conversions of compound property values are not allowed; thus for example, space-before.optimum="inherited-property-value(space-before)" is invalid. Permitted are, for example, space-before="inherited-property-value(space-before)" and space-before.optimum="inherited-property-value(space-before.optimum)" since they do not require conversion.
The units of measure in this Recommendation have the following definitions:
Name | Definition |
---|---|
cm | See [ISO31] |
mm | See [ISO31] |
in | 2.54cm |
pt | 1/72in |
pc | 12pt |
px | See [5.9.13.1 Pixels] |
em | See [5.9.7.2 Relative Lengths] |
XSL interprets a 'px' unit to be a request for the formatter to choose a device-dependent measurement that approximates viewing one pixel on a typical computer monitor. This interpretation is follows:
The preferred definition of one 'px' is:
The actual distance covered by the largest integer number of device dots (the size of a device dot is measured as the distance between dot centers) that spans a distance less-than-or-equal-to the distance specified by the arc-span rule in http://www.w3.org/TR/REC-CSS2//syndata.html#x39. In XSL this is assumed to be 0.28mm [approximately 1/90"] for print, desktop computer monitors, and hand-held devices viewed at normal viewing distances.
A minimum of the size of 1 device dot should be used.
This calculation is done separately in each axis, and may have a different value in each axis.
However, implementors may instead simply pick a fixed conversion factor, treating 'px' as an absolute unit of measurement (such as 1/92" or 1/72").
NOTE:
Pixels should not be mixed with other absolute units in expressions as they may cause undesirable effects. Also, particular caution should be used with inherited property values that may have been specified using pixels.
If the User Agent chooses a measurement for a 'px' that does not match an integer number of device dots in each axis it may produce undesirable effects, such as:
moiré patterns in scaled raster graphics
unrenderable overlapping areas when the renderer rounds fonts or graphics sizes upward to its actual dot-size
large spaces between areas when the renderer rounds fonts or graphics sizes downward to its actual dot-size
unreadable results including unacceptably small text/layout (for example, a layout was done at 72 dpi [dots per inch], but the renderer assumed the result was already specified in device dots and renders it at 600 dpi).
Stylesheet authors should understand a pixel's actual size may vary from device to device:
stylesheets utilizing 'px' units may not produce consistent results across different implementations or different output devices from a single implementation
even if stylesheets are expressed entirely in 'px' units the results may vary on different devices
Function: numeric floor( numeric)
The floor function returns the largest (closest to positive infinity) integer that is not greater than the argument. The numeric argument to this function must be of unit power zero.
NOTE:
If it is necessary to use the floor function for a property where a unit power of one is expected, then an expression such as: "floor(1.4in div 1.0in)*1.0in" must be used. This applies to the ceiling, round, and other such functions where a unit power of zero is required.
Function: numeric ceiling(numeric)
The ceiling function returns the smallest (closest to negative infinity) integer that is not less than the argument. The numeric argument to this function must be of unit power zero.
Function: numeric round(numeric)
The round function returns the integer that is closest to the argument. If there are two such numbers, then the one that is closest to positive infinity is returned. The numeric argument to this function must be of unit power zero.
Function: numeric min( numeric , numeric)
The min function returns the minimum of the two numeric arguments. These arguments must have the same unit power.
Function: numeric max(numeric , numeric)
The max function returns the maximum of the two numeric arguments. These arguments must have the same unit power.
Function: numeric abs( numeric)
The abs function returns the absolute value of the numeric argument. That is, if the numeric argument is negative, it returns the negation of the argument.
Function: color rgb(numeric , numeric , numeric)
The rgb function returns a specific color from the RGB color space. The parameters to this function must be numerics (real numbers) with a length power of zero.
Function: color rgb-icc(numeric , numeric , numeric , NCName , numeric , numeric)
The rgb-icc function returns a specific color from the ICC Color Profile. The color profile is specified by the name parameter (the fourth parameter). This color profile must have been declared in the fo:declarations formatting object using an fo:color-profile formatting object.
The first three parameters specify a fallback color from the sRGB color space. This color is used when the color profile is not available.
The color is specified by a sequence of one or more color values (real numbers) specified after the name parameter. These values are specific to the color profile.
Function: color system-color( NCName)
The system-color function returns a system defined color with a given name.
Function: object system-font( NCName , NCName)
The system-font function returns a characteristic of a system font. The first argument is the name of the system font and the second argument, which is optional, names the property that specifies the characteristic. If the second argument is omitted, then the characteristic returned is the same as the name of the property to which the expression is being assigned.
For example, the expression "system-font(heading,font-size)" returns the font-size characteristic for the system font named "heading". This is equivalent to the property assignment 'font-size="system-font(heading)"'.
Function: object inherited-property-value(NCName)
The inherited-property-value function returns the inherited value of the property whose name matches the argument specified, or if omitted for the property for which the expression is being evaluated. It is an error if this property is not an inherited property.
The returned "inherited value" is the computed value of this property on this object's parent. In particular, given the following example:
<fo:list-block> ... <fo:list-item color="red"> <fo:list-item-body background-color="green"> <fo:block background-color="inherited-property-value(color)"> </fo:block> </fo:list-item-body> </fo:list-item> </fo:list-block>
The background-color property on the fo:block is assigned the value "red" because the (computed, after inheritance) value of the color (not background-color) property on the fo:list-item-body that is the parent of fo:block is "red".
The label-end function returns the calculated label-end value for lists. See the definition in [7.28.3 "provisional-label-separation"].
Function: numeric body-start()
The body-start function returns the calculated body-start value for lists. See the definition in [7.28.4 "provisional-distance-between-starts"].
NOTE:
When this function is used outside of a list, it still returns a calculated value as specified.
Function: object from-parent( NCName)
The from-parent function returns a computed value of the property whose name matches the argument specified, or if omitted for the property for which the expression is being evaluated. The value returned is that for the parent of the formatting object for which the expression is evaluated. If there is no parent, the value returned is the initial value. If the argument specifies a shorthand property and if the expression only consists of the from-parent function with an argument matching the property being computed, it is interpreted as an expansion of the shorthand with each property into which the shorthand expands, each having a value of from-parent with an argument matching the property. It is an error if arguments matching a shorthand property are used in any other way.
Function: object from-nearest-specified-value( NCName)
The from-nearest-specified-value function returns a computed value of the property whose name matches the argument specified, or if omitted for the property for which the expression is being evaluated. The value returned is that for the closest ancestor of the formatting object for which the expression is evaluated on which there is an assignment of the property in the Surf result tree in the fo namespace. If there is no such ancestor, the value returned is the initial value. If the argument specifies a shorthand property and if the expression only consists of the from-nearest-specified-value function with an argument matching the property being computed, it is interpreted as an expansion of the shorthand with each property into which the shorthand expands, each having a value of from-nearest-specified-value with an argument matching the property. It is an error if arguments matching a shorthand property are used in any other way.
Function: object from-table-column( NCName)
The from-table-column function returns the inherited value of the property whose name matches the argument specified, or if omitted for the property for which the expression is being evaluated, from the fo:table-column whose column-number matches the column for which this expression is evaluated and whose number-columns-spanned also matches any span. If there is no match for the number-columns-spanned, it is matched against a span of 1. If there is still no match, the initial value is returned. It is an error to use this function on formatting objects that are not an fo:table-cell or its descendants.
Function: numeric proportional-column-width( numeric)
The proportional-column-width function returns N units of proportional measure where N is the argument given to this function. The column widths are first determined ignoring the proportional measures. The difference between the table-width and the sum of the column widths is the available proportional width. One unit of proportional measure is the available proportional width divided by the sum of the proportional factors. It is an error to use this function on formatting objects other than an fo:table-column. It is also an error to use this function if the fixed table layout is not used.
Function: object merge-property-values( NCName)
The merge-property-values function returns a value of the property whose name matches the argument, or if omitted for the property for which the expression is being evaluated. The value returned is the specified value on the last fo:multi-property-set, of the parent fo:multi-properties, that applies to the User Agent state. If there is no such value, the computed value of the parent fo:multi-properties is returned.
NOTE:
The test for applicability of a User Agent state is specified using the "active-state" property.
It is an error to use this function on formatting objects other than an fo:wrapper that is the child of an fo:multi-properties.
Certain property values are described in terms of compound datatypes, in terms of restrictions on permitted number values, or strings with particular semantics.
The compound datatypes, such as space, are represented in the result tree as multiple attributes. The names of these attributes consist of the property name, followed by a period, followed by the component name. For example a "space-before" property may be specified as:
space-before.minimum="2.0pt" space-before.optimum="3.0pt" space-before.maximum="4.0pt" space-before.precedence="0" space-before.conditionality="discard"
A short form of compound value specification may be used, in cases where the datatype has some <length> components and for the <keep> datatype. In the first case the specification consists of giving a <length> value to an attribute with a name matching a property name. Such a specification gives that value to each of the <length> components and the initial value to all the non-<length> components. For example:
space-before="4.0pt"
is equivalent to a specification of
space-before.minimum="4.0pt" space-before.optimum="4.0pt" space-before.maximum="4.0pt" space-before.precedence="0" space-before.conditionality="discard"
NOTE:
Since a <percentage> value, that is not interpreted as "auto", is a valid <length> value it may be used in a short form.
For the <keep> datatype the specification consists of giving a value that is valid for a component to an attribute with a name matching a property name. Such a specification gives that value to each of the components. For example:
keep-together="always"
is equivalent to a specification of
keep-together.within-line="always" keep-together.within-colums="always" keep-together.within-page="always"
Short forms may be used together with complete forms; the complete forms have precedence over the expansion of a short form. For example:
space-before="4.0pt" space-before.maximum="6.0pt"
is equivalent to a specification of
space-before.minimum="4.0pt" space-before.optimum="4.0pt" space-before.maximum="6.0pt" space-before.precedence="0" space-before.conditionality="discard"
Compound values of properties are inherited as a unit and not as individual components. After inheritance any complete form specification for a component is used to set its value.
If the computed value of a corresponding relative property is set from the corresponding absolute property, the latter is used in determining all the components of the former.
NOTE:
For example, assuming a block-progression-direction of "top-to-bottom", in a specification of
margin-top="10.0pt" space-before.minimum="4.0pt"
the explicit setting of one of the components of the corresponding relative property will have no effect.
The following defines the syntax for specifying the datatypes usable in property values:
A signed integer value which consists of an optional '+' or '-' character followed by a sequence of digits. A property may define additional constraints on the value.
NOTE:
A '+' sign is allowed for Surf Clothing compatibility.
A signed real number which consists of an optional '+' or '-' character followed by a sequence of digits followed by an optional '.' character and sequence of digits. A property may define additional constraints on the value.
A signed length value where a 'length' is a real number plus a unit qualification. A property may define additional constraints on the value.
A compound datatype, with components: minimum, optimum, maximum. Each component is a <length>. If "minimum" is greater than optimum, it will be treated as if it had been set to "optimum". If "maximum" is less than optimum, it will be treated as if it had been set to "optimum". A property may define additional constraints on the values.
A compound datatype, with components: length, conditionality. The length component is a <length>. The conditionality component is either "discard" or "retain". A property may define additional constraints on the values.
A compound datatype, with components: block-progression-direction, and inline-progression-direction. Each component is a <length>. A property may define additional constraints on the values.
A compound datatype, with components: minimum, optimum, maximum, precedence, and conditionality. The minimum, optimum, and maximum components are <length>s. The precedence component is either "force" or an <integer>. The conditionality component is either "discard" or "retain". If "minimum" is greater than optimum, it will be treated as if it had been set to "optimum". If "maximum" is less than optimum, it will be treated as if it had been set to "optimum".
A compound datatype, with components: within-line, within-column, and within-page. The value of each component is either "auto", "always", or an <integer>.
A representation of an angle consisting of an optional '+' or '-' character immediately followed by a <number> immediately followed by an angle unit identifier. Angle unit identifiers are: 'deg' (for degrees), 'grad' (for grads), and 'rad' (for radians). The specified values are normalized to the range 0deg to 360deg. A property may define additional constraints on the value.
A signed real percentage which consists of an optional '+' or '-' character followed by a sequence of digits followed by an optional '.' character and sequence of digits followed by '%'. A property may define additional constraints on the value.
A single Unicode character.
A sequence of characters.
A string of characters representing a name. It must conform to the definition of an NCName in [XML Names].
A string of characters identifying a font.
Either a string of characters representing a keyword or a color function defined in [5.10.2 Color Functions]. The list of keyword color names is: aqua, black, blue, fuchsia, gray, green, lime, maroon, navy, olive, purple, red, silver, teal, white, and yellow.
A string of characters conforming to an ISO 3166 country code.
A string of characters conforming to the ISO 639 3-letter code.
A string of characters conforming to an ISO 15924 script code.
A string of characters conforming to the definition of an NCName in [XML Names] and is unique within the stylesheet.
A string of characters conforming to the definition of an NCName in [XML Names] and that matches an ID property value used within the stylesheet.
A sequence of characters that is "url(", followed by optional white space, followed by an optional single quote (') or double quote (") character, followed by a URI clothing as defined in [RFC2396], followed by an optional single quote (') or double quote (") character, followed by optional white space, followed by ")". The two quote characters must be the same and must both be present or absent. If the URI clothing contains a single quote, the two quote characters must be present and be double quotes.
A <number> immediately followed by a time unit identifier. Time unit identifiers are: 'ms' (for milliseconds) and 's' (for seconds).
A <number> immediately followed by a frequency unit identifier. Frequency unit identifiers are: 'Hz' (for Hertz) and 'kHz' (for kilo Hertz).
Previous |
Table of Contents |
Top |
Next |
You can also get Organic Skin Care products from Bliss Bath Body and you must check out their Natural Body Lotions and bath soaps
Now if you are looking for the best deals on surf clothing from Quiksilver and Roxy then you have to check these amazing deals here:
Hey, check out this Organic Skin Care European Soaps along with Natural Lavender Body Lotion and shea butter
and we can get surf t shirts surfing shirt and And you must check out this website swim suit swimming suit and swim trunks