Difference between revisions of "Dimensions"

From Wiki
Jump to navigation Jump to search
m (expamples from the list)
 
(17 intermediate revisions by 5 users not shown)
Line 1: Line 1:
ConTeXt offers different methods to initialize variables and to calculate with dimension units.  
+
{{note|This article is about the data type. For the names of a page's many dimensions, see [[Layout]].}}
  
=== \definemeasure ===
+
A dimension, in TeX, is a variable storing a length. The length is entered
\setupexternalfigures[location={local,global,default}]
+
as a number immediately followed by two letters that indicate the unit, e.g.
+
{{code|12pt}} or {{code|1cm}}. TeX recognizes 9 different units:
\definemeasure[ColumnC][30mm]
 
\definemeasure[ColumnD][40mm]
 
\definemeasure[ColumnCD][\the\dimexpr(\measure{ColumnC}+\measure{ColumnD})\relax]
 
 
C \measure{ColumnC}
 
 
D \measure{ColumnD}
 
 
CD \measure{ColumnCD}
 
 
\externalfigure[cow][width=\measure{ColumnCD}]
 
  
 +
* scaled points ('''sp'''), equal to 1/65536 points. This is TeX's internal unit for dimensions. One sp is so small that TeX can store dimensions as integers; at the time, this was an advantage, because floating point arithmetic was not guaranteed to be consistent across platforms.
 +
* points ('''pt''') and picas ('''pc'''). One point is 1/72.27 inch; 12 points = 1 pica.
 +
* didot ('''dd''') and cicero ('''cc'''). The didot is a continental counterpart of the point; 12 didot = 1 cicero.
 +
* big points ('''bp'''), defined by Adobe as 1/72 of an inch.
 +
* millimeters ('''mm'''), centimeters ('''cm'''), and inches ('''in''').
  
=== \defineexpandable ===
+
The various conversions between the units are laid out in the [[#Conversion table|conversion table]] at the end of this article.
\setupexternalfigures[location={local,global,default}]
 
 
\defineexpandable\ColumnA    {30mm}
 
\defineexpandable\ColumnB    {40mm}
 
\defineexpandable\ColumnAB    {\the\dimexpr(\ColumnA + \ColumnB)\relax}
 
 
A  \ColumnA
 
 
B  \ColumnB
 
 
AB: \ColumnAB
 
 
\externalfigure[cow][width=\ColumnAB]
 
  
 +
== Defining and accessing dimensions ==
  
The behavior of \define has changed. At first the default was expanded, now it is unexpanded. If "unexpanded" is wished some extracommands are neccesary:
+
{{tex|newdimen}} is the native TeX method to initialise a dimension variable. The requirement to explicitly initialize your dimension variables is a bit clunky, but this method should still be preferred over [[#Storing dimensions as strings|storing dimensions as strings]].
 +
* {{tex|newdimen}} is by far the more common idiom
 +
* Values stored in a dimension register with {{cmd|newdimen}} can be accessed directly from Lua, which is not true for values stored in a macro with {{tex|def}} or {{cmd|definemeasure}}.
  
\defineexpandable\...
+
The following example shows how to set and access dimensions:
same as the lowlevel-TeX-Macro \def\...
 
  
\define\...
+
<context mode="mkiv" source="yes">
same as the low-level-textmacro \unexpanded\def\...
+
\newdimen\columnA                    % initialise variable
 +
\columnA=10mm                        % set variable
  
=== \def ===
+
Column A is \the\columnA{} wide.    % lengths are automatically
 +
                                    % displayed in pt.
  
=== \newdimen ===
+
Column A is \number\columnA sp wide. % internally, lengths are stored
\setupexternalfigures[location={local,global,default}]
+
                                    % as an integer number of sp
 
\defineexpandable\ColumnA    {30mm}
 
\defineexpandable\ColumnB    {40mm}
 
\newdimen\ColumnAB \ColumnAB=\dimexpr(\ColumnA + \ColumnB)
 
 
A  \ColumnA
 
 
B  \ColumnB
 
 
ColumnAB: \the\ColumnAB
 
 
\externalfigure[cow][width=\the\ColumnAB]
 
\externalfigure ist also working without "\the".
 
  
=== \ctxlua ===
+
\blackrule[width=\columnA]
\setupexternalfigures[location={local,global,default}]
+
</context>
 
\defineexpandable\ColumnA    {30mm}
 
\defineexpandable\ColumnB    {40mm}
 
 
\defineexpandable\ColumnABii  {\ctxlua{context([==[\ColumnA + \ColumnB]==])}}
 
 
ColumnABii: \the\dimexpr \ColumnABii\relax
 
 
\externalfigure[cow][width=\dimexpr(\ColumnABii)\relax]
 
  
=== Important to understand ===
+
== Defining and accesing dimensions in Lua ==
ToDos: This points have to be explained.
 
  
==== Which method? ====
+
How to rewrite TeX code
When to use which of the above methods?
 
  
==== \the ====
+
<texcode>
\the: what is it? When to use?
+
\the\dimexpr\availablehsize\relax %say, 426pt
 +
</texcode>
  
==== Expanding ====
+
Mostly LMTX:
expanding of variables: What does this mean? When to use?
 
  
==== \relax ====
+
<context mode="mkxl" source="yes">
With \relax the termination of a calculation is garantied. If there is one too much ... no problem, then it is ignored.
 
  
"add a \relax after code definitions to prevent the scanner from reading too much"
+
1: \number\dimexpr\availablehsize\relax
  
\the\dimexpr... will look ahead till there's something nonexpandable, and contrary to what one expects
+
2: \startluacode
  
\dimexpr(...)
+
token.set_macro(tex.ctxcatcodes,"temp","\\scratchdimen\\availablehsize")
 +
    token.expand_macro("temp")
 +
    context(tex.getdimen("scratchdimen"))
 +
\stopluacode
  
 +
3: \startluacode
  
will not stop at the ) so, although with measures it normally goes okay, personally I always use \relax as terminator; the \relax will be eaten up so there is no interference but it guarantees to stop scanning.
+
token.set_macro(tex.ctxcatcodes,"temp","\\scratchdimen\\availablehsize")
 +
    tex.runlocal("temp")
 +
    context(tex.getdimen("scratchdimen"))
 +
\stopluacode
  
;Example:
+
4: \startluacode
\definemeasure[ColumnC][30mm]
+
    tex.print("\\scratchdimen\\availablehsize")
\definemeasure[ColumnD][40mm]
+
    tex.pushlocal()
\definemeasure[ColumnCDi][\the\dimexpr(\measure{ColumnC}+\measure{ColumnD})\relax]
+
    tex.poplocal()
 +
    context(tex.getdimen("scratchdimen"))
 +
\stopluacode
  
 +
5: \startluacode
 +
    tex.print("\\dimensiondef\\temp\\availablehsize")
 +
    tex.pushlocal()
 +
    tex.poplocal()
 +
    context(tex.getdimensionvalue("temp"))
 +
\stopluacode
  
;Further examples:
+
\def\calculateavailablehsize{\dimensiondef\temp\availablehsize}
\footnote{\input tufte \relax} \par
+
 
  \definepapersize[bigsheet][width=\dimexpr\paperwidth+6mm\relax,height=\dimexpr\paperheight+6mm\relax]
+
6: \startluacode
  \setupTABLE[c][3][width={\dimexpr(\textwidth-2cm)* 2 / 3\relax}]
+
    token.expand_macro("calculateavailablehsize")
\definemeasure[topspace] [\dimexpr(210mm-31mm*5)/2\relax]
+
    context(tex.getdimensionvalue("temp"))
 +
\stopluacode
 +
 
 +
\newtoks\tcalculateavailablehsize
 +
\tcalculateavailablehsize{\dimensiondef\temp\availablehsize}
 +
 
 +
7: \startluacode -- mkiv
 +
    tex.runtoks("tcalculateavailablehsize")
 +
    context(tex.getdimensionvalue("temp"))
 +
\stopluacode
 +
</context>
 +
 
 +
== Converting dimensions ==
 +
 
 +
Usually, you will want to express a dimension in something other than points or
 +
scaled points. For this, Lua is the way to go:
 +
 
 +
* If you want to print, the functions {{code|number.tocentimeters}}, {{code|topoints}}, {{code|topicas}}, etc. are already provided. These functions return a number as a string with (by default) the unit abbreviation appended.
 +
 
 +
* If you want to calculate, the conversion factors from standard points are stored in {{code|number.dimenfactors}}. For example, {{code|65536 * number.dimenfactors["pt"]}} returns {{code|1}}.
 +
 
 +
<context source=yes>
 +
\newdimen\columnA                    % initialise variable
 +
\columnA=10mm                        % set variable
 +
 
 +
\startluacode
 +
    local A = tex.dimen.columnA      -- access a dimen value
 +
 
 +
    -- internal unit: scaled points (integer)
 +
    context("Column A is %d scaled points", A)
 +
    context.par()
 +
 
 +
    -- default conversion: 15 digits, unit at the end, no space
 +
    context("Column A is %s", number.tocentimeters(A))
 +
    context.par()
 +
 
 +
    -- expressing a dimen in cm, rounded to 0.01, no automatic unit
 +
    context("Column A is %s cm", number.tocentimeters(A, "%.2f"))
 +
    context.par()
 +
 
 +
    -- converting from mm to cm
 +
    local inmm = 10
 +
    local incm = inmm / number.dimenfactors["mm"] * number.dimenfactors["cm"]
 +
    context("Column A is %.1f cm", incm)
 +
\stopluacode
 +
</context>
 +
 
 +
== Calculating with dimensions ==
 +
 
 +
From TeX, you can compute with dimensions by writing your calculation between {{tex|dimexpr}}{{code|...}}{{tex|relax}}. Such an expression may only occur where a length is expected. Spaces are allowed, but never required.
 +
 
 +
<context mode=mkiv source=yes>
 +
\newdimen\columnA
 +
\columnA=1cm
 +
 
 +
0.5 cm equals \the\dimexpr \columnA / 2 \relax.
 +
 
 +
\blackrule[width=\dimexpr 2 \columnA\relax]
 +
</context>
 +
 
 +
In Lua, dimensions are a number of scaled points, and you can do all the usual things. TeX uses integers for dimens, but Lua treats them as floats; the number will only be coerced to integer when you retrieve from, or assign to, {{code|tex.dimen.somevalue}}. Not that half a scaled point is much to worry about.
 +
 
 +
<context mode=mkiv source=yes>
 +
\newdimen\columnA
 +
\columnA=1cm
 +
 
 +
\startluacode
 +
    local A = tex.dimen.columnA
 +
    double_A = 2 * A
 +
    context.blackrule({width = double_A .. "sp"})
 +
\stopluacode
 +
</context>
 +
 
 +
;More examples:
 +
 
 +
<context mode=mkiv source=yes>
 +
  \newdimen\AAA \AAA=100pt
 +
  \newdimen\BBB \BBB=\AAA
 +
 
 +
  AAA is \the\AAA
 +
 
 +
  BBB is \the\BBB
 +
</context>
 +
 
 +
== Storing dimensions as strings ==
 +
 
 +
Because TeX expands macros, we can store a dimension string like {{code|10pt}}
 +
in a macro, and insert that in any place TeX expects a dimension. You can use a plain {{tex|def}}; or you can define dimensions with  {{cmd|definemeasure|[...]}} and retrieve them with {{cmd|measure|{...}|}}.
 +
 
 +
<context mode=mkiv source=yes>
 +
\definemeasure[One][10mm]
 +
\def\Two{20mm}
 +
 
 +
\definemeasure[Three][\dimexpr \measure{One} + \Two\relax]
 +
 
 +
\blackrule[width=\measure{One}] \crlf
 +
\blackrule[width=\Two]           \crlf
 +
\blackrule[width=\measure{Three}]\crlf
 +
</context>
 +
 
 +
== Conversion table ==
 +
 
 +
Bold numbers indicate conversions that are set by definition.
 +
 
 +
{| class="wikitable"
 +
|-
 +
! unit              !! TeX name
 +
! in sp            !! in pt        !! in pc      !! in dd      !! in cc
 +
! in bp            !! in in        !! in mm      !! in cm
 +
|-
 +
| scaled point      || {{code|sp}}
 +
| 1                || '''1/65536''' ||            ||            ||
 +
|                  ||              ||            ||           
 +
|-
 +
| point            || {{code|pt}}
 +
| '''65536'''      || 1            || '''1/12''' || 0.9346    || 0.0779
 +
| 0.9963            || '''1/72.27''' || 0.3516    || 0.0351
 +
|-
 +
| pica              || {{code|pc}}
 +
| 786432            || '''12'''      || 1          || 11.2149    || 0.9346
 +
| 11.9552          || 0.1660        || 4.2175    || 0.4218
 +
|-
 +
| didot            || {{code|dd}}
 +
| 70124.081        || 1.0700        || 0.0892    || 1          || '''1/12'''
 +
| 1.0660            || 0.0148        || 0.3761    || 0.0376
 +
|-
 +
| cicero            || {{code|cc}}
 +
| 841488.98        || 12.8401      || 1.0700    || '''12'''  || 1
 +
| 12.7921          || 0.1777        || 4.5128    || 0.45128
 +
|-
 +
| big point        || {{code|bp}}
 +
| 65781.76          || 1.0038        || 0.0836    || 0.9381    || 0.0782
 +
| 1                || '''1/72'''    || 0.3528    || 0.0353
 +
|-
 +
| inch              || {{code|in}}
 +
| 4736286.7        || '''72.27'''  || 6.0225    || 67.5415    || 5.6284
 +
| '''72'''          || 1            || 25.4      || 2.54
 +
|-
 +
| millimeter        || {{code|mm}}
 +
| 186467.98        || 2.8453        || 0.2371    || 2.6591    || 0.2216
 +
| 2.8346            || 0.0394        || 1          || 0.1
 +
|-
 +
| centimeter        || {{code|cm}}
 +
| 1864679.8        || 28.4528      || 2.3711    || 26.5911    || 2.2159
 +
| 28.3464          || 0.39370      || 10        || 1
 +
|-
 +
|}
  
 
== See also ==
 
== See also ==
* [[Command/define]]
+
* {{cmd|definemeasure}}
 +
* {{cmd|measure}}
  
[[Category:ConTeXt-Issues]]
+
[[Category:Programming and Databases]]
[[Category:Programming]]
+
[[Category:Tools]]

Latest revision as of 15:05, 6 February 2021


NOTE: This article is about the data type. For the names of a page's many dimensions, see Layout.

A dimension, in TeX, is a variable storing a length. The length is entered as a number immediately followed by two letters that indicate the unit, e.g. 12pt or 1cm. TeX recognizes 9 different units:

  • scaled points (sp), equal to 1/65536 points. This is TeX's internal unit for dimensions. One sp is so small that TeX can store dimensions as integers; at the time, this was an advantage, because floating point arithmetic was not guaranteed to be consistent across platforms.
  • points (pt) and picas (pc). One point is 1/72.27 inch; 12 points = 1 pica.
  • didot (dd) and cicero (cc). The didot is a continental counterpart of the point; 12 didot = 1 cicero.
  • big points (bp), defined by Adobe as 1/72 of an inch.
  • millimeters (mm), centimeters (cm), and inches (in).

The various conversions between the units are laid out in the conversion table at the end of this article.

Defining and accessing dimensions

\newdimen is the native TeX method to initialise a dimension variable. The requirement to explicitly initialize your dimension variables is a bit clunky, but this method should still be preferred over storing dimensions as strings.

  • \newdimen is by far the more common idiom
  • Values stored in a dimension register with \newdimen can be accessed directly from Lua, which is not true for values stored in a macro with \def or \definemeasure.

The following example shows how to set and access dimensions:

\newdimen\columnA                    % initialise variable
\columnA=10mm                        % set variable

Column A is \the\columnA{} wide.     % lengths are automatically 
                                     % displayed in pt.

Column A is \number\columnA sp wide. % internally, lengths are stored
                                     % as an integer number of sp

\blackrule[width=\columnA]

Defining and accesing dimensions in Lua

How to rewrite TeX code

\the\dimexpr\availablehsize\relax %say, 426pt

Mostly LMTX:


1: \number\dimexpr\availablehsize\relax

2: \startluacode

token.set_macro(tex.ctxcatcodes,"temp","\\scratchdimen\\availablehsize")
     token.expand_macro("temp")
     context(tex.getdimen("scratchdimen"))
\stopluacode

3: \startluacode

token.set_macro(tex.ctxcatcodes,"temp","\\scratchdimen\\availablehsize")
     tex.runlocal("temp")
     context(tex.getdimen("scratchdimen"))
\stopluacode

4: \startluacode
     tex.print("\\scratchdimen\\availablehsize")
     tex.pushlocal()
     tex.poplocal()
     context(tex.getdimen("scratchdimen"))
\stopluacode

5: \startluacode
     tex.print("\\dimensiondef\\temp\\availablehsize")
     tex.pushlocal()
     tex.poplocal()
     context(tex.getdimensionvalue("temp"))
\stopluacode

\def\calculateavailablehsize{\dimensiondef\temp\availablehsize}

6: \startluacode
     token.expand_macro("calculateavailablehsize")
     context(tex.getdimensionvalue("temp"))
\stopluacode

\newtoks\tcalculateavailablehsize
\tcalculateavailablehsize{\dimensiondef\temp\availablehsize}

7: \startluacode -- mkiv
     tex.runtoks("tcalculateavailablehsize")
     context(tex.getdimensionvalue("temp"))
\stopluacode

Converting dimensions

Usually, you will want to express a dimension in something other than points or scaled points. For this, Lua is the way to go:

  • If you want to print, the functions number.tocentimeters, topoints, topicas, etc. are already provided. These functions return a number as a string with (by default) the unit abbreviation appended.
  • If you want to calculate, the conversion factors from standard points are stored in number.dimenfactors. For example, 65536 * number.dimenfactors["pt"] returns 1.
\newdimen\columnA                    % initialise variable
\columnA=10mm                        % set variable

\startluacode
    local A = tex.dimen.columnA      -- access a dimen value

    -- internal unit: scaled points (integer)
    context("Column A is %d scaled points", A)
    context.par()

    -- default conversion: 15 digits, unit at the end, no space
    context("Column A is %s", number.tocentimeters(A))
    context.par()

    -- expressing a dimen in cm, rounded to 0.01, no automatic unit
    context("Column A is %s cm", number.tocentimeters(A, "%.2f"))
    context.par()

    -- converting from mm to cm
    local inmm = 10
    local incm = inmm / number.dimenfactors["mm"] * number.dimenfactors["cm"]
    context("Column A is %.1f cm", incm)
\stopluacode

Calculating with dimensions

From TeX, you can compute with dimensions by writing your calculation between \dimexpr...\relax. Such an expression may only occur where a length is expected. Spaces are allowed, but never required.

\newdimen\columnA
\columnA=1cm

0.5 cm equals \the\dimexpr \columnA / 2 \relax.

\blackrule[width=\dimexpr 2 \columnA\relax]

In Lua, dimensions are a number of scaled points, and you can do all the usual things. TeX uses integers for dimens, but Lua treats them as floats; the number will only be coerced to integer when you retrieve from, or assign to, tex.dimen.somevalue. Not that half a scaled point is much to worry about.

\newdimen\columnA
\columnA=1cm

\startluacode
    local A = tex.dimen.columnA
    double_A = 2 * A
    context.blackrule({width = double_A .. "sp"})
\stopluacode

More examples
  \newdimen\AAA \AAA=100pt
  \newdimen\BBB \BBB=\AAA

  AAA is \the\AAA

  BBB is \the\BBB

Storing dimensions as strings

Because TeX expands macros, we can store a dimension string like 10pt in a macro, and insert that in any place TeX expects a dimension. You can use a plain \def; or you can define dimensions with \definemeasure[...] and retrieve them with \measure{...}.

\definemeasure[One][10mm]
\def\Two{20mm}

\definemeasure[Three][\dimexpr \measure{One} + \Two\relax]

\blackrule[width=\measure{One}]  \crlf
\blackrule[width=\Two]           \crlf
\blackrule[width=\measure{Three}]\crlf

Conversion table

Bold numbers indicate conversions that are set by definition.

unit TeX name in sp in pt in pc in dd in cc in bp in in in mm in cm
scaled point sp 1 1/65536
point pt 65536 1 1/12 0.9346 0.0779 0.9963 1/72.27 0.3516 0.0351
pica pc 786432 12 1 11.2149 0.9346 11.9552 0.1660 4.2175 0.4218
didot dd 70124.081 1.0700 0.0892 1 1/12 1.0660 0.0148 0.3761 0.0376
cicero cc 841488.98 12.8401 1.0700 12 1 12.7921 0.1777 4.5128 0.45128
big point bp 65781.76 1.0038 0.0836 0.9381 0.0782 1 1/72 0.3528 0.0353
inch in 4736286.7 72.27 6.0225 67.5415 5.6284 72 1 25.4 2.54
millimeter mm 186467.98 2.8453 0.2371 2.6591 0.2216 2.8346 0.0394 1 0.1
centimeter cm 1864679.8 28.4528 2.3711 26.5911 2.2159 28.3464 0.39370 10 1

See also