summaryrefslogtreecommitdiff
path: root/macros/optex/base/colors.opm
diff options
context:
space:
mode:
Diffstat (limited to 'macros/optex/base/colors.opm')
-rw-r--r--macros/optex/base/colors.opm215
1 files changed, 110 insertions, 105 deletions
diff --git a/macros/optex/base/colors.opm b/macros/optex/base/colors.opm
index 23ec22dd9f..6ef8fc9dcf 100644
--- a/macros/optex/base/colors.opm
+++ b/macros/optex/base/colors.opm
@@ -1,16 +1,6 @@
%% This is part of the OpTeX project, see http://petr.olsak.net/optex
-\_codedecl \colordef {Colors <2021-05-28>} % preloaded in format
-
- \_doc -----------------------------
- We declare internal boolean value \`\_iflocalcolor` ad do
- \`\localcolor` as default.
- \_cod -----------------------------
-
-\_newifi \_iflocalcolor \_localcolortrue
-\_protected\_def \_localcolor {\_localcolortrue}
-\_protected\_def \_nolocalcolor {\_localcolorfalse}
-\_public \localcolor \nolocalcolor ;
+\_codedecl \colordef {Colors <2021-07-16>} % preloaded in format
\_doc -----------------------------
The basic colors in CMYK
@@ -21,103 +11,101 @@
\_def\Blue {\_setcmykcolor{1 1 0 0}}
\_def\Red {\_setcmykcolor{0 1 1 0}}
-\_def\Brown {\_setcmykcolor{0 0.67 0.67 0.5}}
+\_def\Brown {\_setcmykcolor{0 .67 .67 .5}}
\_def\Green {\_setcmykcolor{1 0 1 0}}
\_def\Yellow {\_setcmykcolor{0 0 1 0}}
\_def\Cyan {\_setcmykcolor{1 0 0 0}}
\_def\Magenta {\_setcmykcolor{0 1 0 0}}
-\_def\Grey {\_setcmykcolor{0 0 0 0.5}}
-\_def\LightGrey {\_setcmykcolor{0 0 0 0.2}}
+\_def\Grey {\_setcmykcolor{0 0 0 .5}}
+\_def\LightGrey {\_setcmykcolor{0 0 0 .2}}
\_def\White {\_setgreycolor{1}}
\_def\Black {\_setgreycolor{0}}
\_doc -----------------------------
By default, the \`\setcmykcolor` \`\setrgbcolor` and \`\setgreycolor`
macros with `{<componetns>}` parameter
- expand to `\_setcolor{<pdf-primitive>}` using \`\_formatcmyk`
- or \`\_formatrgb` or \`\_formatgrey` expandable macros.
- For example `\setrgbcolor{1 0 0}` expands to `\_setcolor{1 0 0 rg 1 0 0 RG}`.\nl
- We set both types of colors (for lines (`K` or `RG` or `G`) and for fills
- (`r` or `rg` or `g`) together in the <pdf-primitive> command.
- This is the reason why the \`\_fillstroke` uses both its parameters.
- If only fills are needed you can do `\def\_fillstroke#1#2{#1}`.
- If only strokes are needed you can do `\def\_fillstroke#1#2{#2}`.
+ expand to \^`\_setcolor``{<color-data>}{<fill-op>}{<stroke-op>}` where
+ <color-data> is <R> <G> <B> or <C> <M> <Y> <K> or <G> and
+ <fill-op> is color operator for filling, <stroke-op> is color operator
+ for stroking.
\_cod -----------------------------
-\_def\_setcmykcolor#1{\_setcolor{\_formatcmyk{#1}}}
-\_def\_setrgbcolor#1{\_setcolor{\_formatrgb{#1}}}
-\_def\_setgreycolor#1{\_setcolor{\_formatgrey{#1}}}
-\_def\_formatcmyk#1{\_fillstroke{#1 k}{#1 K}}
-\_def\_formatrgb#1{\_fillstroke{#1 rg}{#1 RG}}
-\_def\_formatgrey#1{\_fillstroke{#1 g}{#1 G}}
-\_def\_fillstroke#1#2{#1 #2}
+\_def\_setcmykcolor#1{\_setcolor{#1}kK}
+\_def\_setrgbcolor#1{\_setcolor{#1}{rg}{RG}}
+\_def\_setgreycolor#1{\_setcolor{#1}gG}
\_public \setcmykcolor \setrgbcolor \setgreycolor ;
\_doc -----------------------------
- The \`\onlyrgb` declaration redefines \^`\_formatcmyk` in order it expands
- to its conversion to RGB <pdf-primitive>. This conversion is done by
- the \^`\_cmyktorgb` macro. Moreover, `\onlyrgb` re-defines three basic RGB
+ The \`\onlyrgb` declaration redefines \^`\setcmykcolor` to do conversion
+ to RGB just before \^`\_setcolor` is used.
+ The \`\onlycmyk` declaration redefines \^`\setrgbcolor` to do conversion
+ to CMYK just before \^`\_setcolor` is used.
+ Moreover, \^`\onlyrgb` re-defines three basic RGB
colors for RGB color space and re-declares \^`\colordef` as \^`\rgbcolordef`.
- The \hbox{\`\onlycmyk`} macro does similar work, it re-defines \^`\_formatrgb`
- macro. The Grey color space is unchanged and works in both main
- settings (RGB or CMYK) without collisions.
\_cod -----------------------------
\_def\_onlyrgb{\_def\Red{\_setrgbcolor{1 0 0}}%
\_def\Green{\_setrgbcolor{0 1 0}}\_def\Blue{\_setrgbcolor{0 0 1}}%
\_let\_colordef=\_rgbcolordef
- \_def\_formatrgb##1{\_fillstroke{##1 rg}{##1 RG}}%
- \_def\_formatcmyk##1{\_fillstroke{\_cmyktorgb ##1 ; rg}{\_cmyktorgb ##1 ; RG}}}
-\_def\_onlycmyk{\_def\_formatcmyk##1{\_fillstroke{##1 k}{##1 K}}%
- \_def\_formatrgb##1{\_fillstroke{\_rgbtocmyk ##1 ; k}{\_rgbtocmyk ##1 ; K}}}
+ \_def\_setrgbcolor##1{\_setcolor{##1}{rg}{RG}}%
+ \_def\_setcmykcolor##1{\_ea\_setcolor\_ea{\_expanded{\_cmyktorgb ##1 ;}}{rg}{RG}}%
+ \_public \colordef \setrgbcolor \setcmykcolor ;}
+\_def\_onlycmyk{%
+ \_let\_colordef=\_cmykcolordef
+ \_def\_setrgbcolor##1{\_ea\_setcolor\_ea{\_expanded{\_rgbtocmyk ##1 ;}}kK}%
+ \_def\_setcmykcolor##1{\_setcolor{##1}kK}%
+ \_public \colordef \setrgbcolor \setcmykcolor ;}
\_public \onlyrgb \onlycmyk ;
\_doc -----------------------------
- The \`\_setcolor` macro redefines empty `\_ensureblack` macro (used in
- output routine for headers and footers) to `\_ensureblackA` which sets
- Black at the start of its parameter and returns to the current color at the
- end of its parameter.
-
- The current color is saved into `\_currentcolor` macro and colorstack is pushed.
- Finally, the `\_colorstackpop` is initialized by `\aftergroup` if
- `\localcolor` is declared.
-
- You can save the current color to your macro by `\let\yourmacro=\_currentcolor`
- and you can return to this color by the command `\_setcolor\yourmacro`.
+ The \`\_colorattr` for coloring is allocated and
+ \`\_setcolor``{<color-data>}{<fill-op>}{<stroke-op>}` is defined here.
+ This macro does `\_colorattr=`\`\_colorcnt` if the <color data> was not used
+ before and prepare mapping from this integer value to the <color data>
+ and increments \^`\_colorcnt`.
+ If the <color data> were used already, then \^`\_setcolor`
+ does `\_colorattr=<stored-value>`.
+ This work is done by the \`\_translatecolor` macro. The following mapping
+ macros are created:
+ \begtt \catcode`<=13
+ \_color::<data> <fill-op> ... expands to used <attribute-value>
+ \_color:<attribute-value> ... expands to <data> <fill-op>
+ \_color-s:<attribute-value> ... expands to <data> <stroke-op>
+ \endtt
+ The \`\_resetcolor` un-sets the color attribute, it means that default
+ color (black) shall be used.
\_cod -----------------------------
-\_protected\_def \_setcolor #1{\_global\_let\_ensureblack=\_ensureblackA
- \_iflocalcolor \_edef\_currentcolor{#1}\_colorstackpush\_currentcolor
- \_aftergroup\_colorstackpop
- \_else \_xdef\_currentcolor{#1}\_colorstackset\_currentcolor \_fi
+\_newattribute \_colorattr
+\_newcount \_colorcnt \_colorcnt=1 % allocations start at 1
+\_protected\_def\_setcolor{\_colorprefix\_colorattr=\_translatecolor}
+\_def\_resetcolor{\_colorattr=-"7FFFFFFF }
+\_def\_translatecolor#1#2#3{\_ifcsname _color::#1 #2\_endcsname\_lastnamedcs\_relax
+ \_else
+ \_colorcnt
+ \_sxdef{_color::#1 #2}{\_the\_colorcnt}%
+ \_sxdef{_color:\_the\_colorcnt}{#1 #2}%
+ \_sxdef{_color-s:\_the\_colorcnt}{#1 #3}%
+ \_incr \_colorcnt
+ \_fi
}
-\_def\_pdfblackcolor{0 g 0 G}
-\_edef\_currentcolor{\_pdfblackcolor}
-\_def\_ensureblackA#1{\_global\_let\_openfnotestack=\_openfnotestackA
- \_colorstackpush\_pdfblackcolor #1\_colorstackpop}
-
- \_doc -----------------------------
- The colorstack is initialized here and the basic macros
- \`\_colorstackpush`, \`\_colorstackpop` and \`\_colorstackset`
- are defined here.
- \_cod -----------------------------
-
-\_mathchardef\_colorstackcnt=0 % Implicit stack usage
-\_def\_colorstackpush#1{\_pdfcolorstack\_colorstackcnt push{#1}}
-\_def\_colorstackpop{\_pdfcolorstack\_colorstackcnt pop}
-\_def\_colorstackset#1{\_pdfcolorstack\_colorstackcnt set{#1}}
+% Black is the default color.
+\_sdef{_color::0 g}{0}
+\_sdef{_color:0}{0 g}
+\_sdef{_color-s:0}{0 G}
\_doc -----------------------------
- We need to open a special color stack for footnotes because footnotes
- can follow on the next pages and their colors are independent of colors
- used in the main page-body. The \`\_openfnotestack` is defined as
- \`\_openfnotestackA` when the \^`\_setcolor` is used first.
- The \`\_fnotestack` is initialized in in `\everyjob` because the
- initialization is not saved to the format.
+ We support concept of non-local color, i.e. all changes of the color
+ attribute are global by setting \`\_colorprefix` to `\global`.
+ \`\localcolor` is the default, i.e.\ \^`\_colorprefix` is `\relax`.\nl
+ You can write `\global\Red` if you want to have global setting of the
+ color.
\_cod -----------------------------
-%\_mathchardef\_fnotestack=\_pdfcolorstackinit page {0 g 0 G} % must be in \everyjob
-\_def \_openfnotestackA {\_pdfcolorstack\_fnotestack current}
+\_protected\_def \_localcolor {\_let\_colorprefix=\_relax}
+\_protected\_def \_nolocalcolor {\_let\_colorprefix=\_global}
+\_public \localcolor \nolocalcolor ;
+\_localcolor
\_doc -----------------------------
We use Lua codes for RGB to CMYK or CMYK to RGB conversions and for
@@ -297,7 +285,7 @@
\begtt
\def\vr{\vrule height10pt depth2pt width20pt}
\def\_showcolor{\hbox{\tt\_bslash\_tmpb: \csname\_tmpb\endcsname \vr}\space\space}
- \begmulti 4 \typosize[11/14]
+ \begmulti 4 \typosize[10/14]
\morecolors
\endmulti
\endtt
@@ -319,35 +307,49 @@
\_endcode % -------------------------------------
-The colors have different behavior than fonts. Marks (whatsits) with color
-information are stored into PDF output and \TeX/ doesn't interpret them.
-The PDF viewer (or PDF interpreter in a printer) reads these marks
-and switches colors according to them. This
-is independent of \TeX/ group mechanism. You can declare
-`\nolocalcolor` at the beginning of the document, if you want this behavior.
-In this case, if you set a color then you must return to the black color
-using `\Black` manually.
-
-By default, \OpTeX/ sets `\localcolor`. It means that the typesetting
-returns to a previous color at the end of the current group, so you cannot
-write `\Black` explicitly. This is implemented using the `\aftergroup` feature.
-There is a limitation of this feature: when a color selector is used in a
-group of a box, which is saved by `\setbox`, then the activity or
-reconstruction of the previous color is processed at `\setbox` time, no in the
-box itself. You must correct it by double group:
-\begtt
-\setbox0=\hbox{\Red text} % bad: \Black is done after \setbox
-\setbox0=\hbox{{\Red text}} % good: \Black is done after group inside the box
-\endtt
-
-The implementation of colors is based on colorstack, so the current color
-can follow across more pages. It is not so obvious because PDF viewer (or PDF
-interpreter) manipulates with colors locally at each PDF page and it
-initializes each PDF page with black on white color.
+\secc Basic concept
+
+Setting of color in PDF is handled by graphics operators which change the
+graphics context. Colors for fills/strokes are distinguished, but apart from
+that, only one color is active at time and is used for all material drawn by
+following graphics operators, until next color is set. Each PDF content (e.g.
+page or form XObject) has its own graphics context, that is initialized from
+zero. Hence we have different concept of selecting fonts in \TeX/ (it
+depends on \TeX/ groups but does not depends on pages) and color handling in
+PDF.
+
+\TeX/ itself has no concept of colors. Colors have always been handled by
+inserting whatsits (either using `\special` for DVI or using
+`\pdfliteral`/`\pdfcolorstack` for PDF). It is very efficient and \TeX/ doesn't
+even have to know anything about colors, but it is also problematic in many
+ways.
+
+That is the reason why we decided to change color handling from
+`\pdfcolorstack` to \LuaTeX/ attributes in version 1.04 of \OpTeX. Using
+attributes, the color setting behaves exactly like font selection from \TeX/
+point of view: it respects \TeX/ groups, colors can span more pages,
+independent colors can be set for `\insert`s, etc. Moreover, once a material is
+created (using `\setbox` for example) then it has its fonts and its colors
+frozen and you can rely on it when you are using e.g. `\unhbox`. There are no
+internal whatsits for colors which can interfere with other typesetting
+material. In the end something like setting text to red (`{\Red text}`) should
+have the same nice behavior like setting text to bold (`{\bf text}`).
+
+\LuaTeX/ attributes can be set like count register -- one attribute holds one
+number at a time. But the value of attribute is propagated to each created
+typesetting element until the attribute is unset or set to another value. Very
+much like the font property. We use one attribute \^`\_colorattr` for storing
+the currently selected color (in number form).
Macros \^`\setcmykcolor``{<C> <M> <Y> <K>}` or \^`\setrgbcolor``{<R> <G> <B>}`
-or\nl \^`\setgreycolor``{<Grey>}` should be used in color selectors or user can
-specify these macros explicitly.
+or\nl \^`\setgreycolor``{<Grey>}` are used in color selectors. These
+macros expand to internal \^`\_setcolor` macro which sets the \^`\_colorattr`
+attribute to an integer value and prepares mapping between this value and the real
+color data. This mapping is used just before each `\shipout` in output routine.
+The \^`\_preshipout` pseudo-primitive is used here, it converts attribute
+values to internal PDF commands for selecting colors.
+
+\secc Color mixing
The color mixing processed by the \^`\colordef` is done in the subtractive color
model CMYK. If the result has a component greater than 1 then all
@@ -405,8 +407,11 @@ and it is used in \^`\colordef` or if it is printed when \^`\onlycmyk` is declar
The CMYK to RGB conversion is invoked when a color is declared using \^`\setcmykcolor`
and it is used in \^`\rgbcolordef` or if it is printed when \^`\onlyrgb` is declared.
+\secc Implementation
+
\_endinput
+2021-07-16 colors reimplemented, now they are based on attributes
2021-05-28 \rgbcmykmap introduced
2020-04-22 \replstring\tmpb{+ }{+}, {- }{-} added in \colordef, bug fixed
2020-03-18 introduced