aboutsummaryrefslogtreecommitdiffstats
path: root/doc/expert/tex
diff options
context:
space:
mode:
Diffstat (limited to 'doc/expert/tex')
-rw-r--r--doc/expert/tex383
1 files changed, 383 insertions, 0 deletions
diff --git a/doc/expert/tex b/doc/expert/tex
new file mode 100644
index 0000000..5d4d357
--- /dev/null
+++ b/doc/expert/tex
@@ -0,0 +1,383 @@
+@Appendix
+ @Title { Implementation of Textures }
+ @Tag { tex }
+@Begin
+The following notes detail how PostScript patterns have been
+used to produce textures. See the PostScript Language
+Reference Manual, second edition (PLRM), especially Section 4.9.
+@PP
+PostScript patterns are implemented as color spaces, whereas
+from a logical point of view they are really separate entities
+in the graphics state, independent of color (except that a
+colored texture overrides any current color while it is in
+effect). To ensure that Lout's @@SetTexture and @@SetColour
+symbols have this desired independence of each other, the
+following operators are defined in the Lout prologue:
+@CD @Tbl
+ mv { 0.5vx }
+ bfont { Italic }
+ bformat { @StartHSpan @Cell i { ctr } A | @HSpan | @HSpan | @Cell D }
+ aformat { @Cell i { right } @Code A | @Cell @Code B |
+ @Cell mr { 1c } @Code "-" | @Cell D }
+{
+@Rowb
+ ma { 0i }
+ A { Lout-defined operator }
+ D { What it replaces }
+ rb { yes }
+@Rowa
+ A { num }
+ B { LoutSetGray }
+ D { setgray }
+@Rowa
+ A { num num num }
+ B { LoutSetRGBColor }
+ D { setrgbcolor }
+@Rowa
+ A { num num num }
+ B { LoutSetHSBColor }
+ D { sethsbcolor }
+@Rowa
+ A { num num num num }
+ B { LoutSetCMYKColor }
+ D { setcmykcolor }
+@Rowa
+ A { p }
+ B { LoutSetTexture }
+ D { setpattern }
+ rb { yes }
+ mb { 0i }
+}
+These have similar signatures to the corresponding PostScript
+operators shown, and the idea is to use the Lout-defined
+versions where you would normally use the PostScript ones.
+The first four set the color without disturbing any current
+texture; the last sets the texture without disturbing
+any current color. Here @Code { p } may be the PostScript
+{@Code null} object, meaning no texture i.e. normal filling,
+or else it must be an instantiated pattern dictionary, as
+returned by @Code { makepattern }.
+@PP
+There are three key data types used by this code:
+@BulletList
+
+@LI { A colorspace, denoted @Code { cs }, is a PostScript
+colorspace array and may have one of the following values:
+@DP @RID @Tbl
+ mv { 0.6vx }
+ aformat { @Cell @Code A | @Cell B }
+{
+@Rowa
+ ma { 0i }
+ A { "[ /DeviceGray ]" }
+ B { The greyscale colorspace }
+@Rowa
+ A { "[ /DeviceRGB ]" }
+ B { The RGB colorspace }
+@Rowa
+ A { "[ /DeviceCMYK ]" }
+ B { The CMYK colorspace }
+@Rowa
+ A { "[ /Pattern ]" }
+ B { A colored pattern }
+@Rowa
+ mb { 0i }
+ A { "[ /Pattern /name ]" }
+ B { An uncolored pattern; @Code "/name" may be
+{@Code "/DeviceGray"}, {@Code "/DeviceRGB"}, or
+{@Code "/DeviceCMYK"} }
+}
+}
+
+@LI { A color, denoted c, is an array containing a PostScript
+non-pattern color and thus may have one of the following values:
+@ID @Tbl
+ mv { 0.6vx }
+ aformat { @Cell @Code A | @Cell B }
+{
+@Rowa
+ ma { 0i }
+ A { "[ grey ]" }
+ B { A @Code "/DeviceGray" color }
+@Rowa
+ A { "[ red green blue ]" }
+ B { A @Code "/DeviceRGB" color }
+@Rowa
+ A { "[ c m y k ]" }
+ B { A @Code "/DeviceCMYK" color }
+ mb { 0i }
+}
+We enclose colors in an array to make it easy for us to
+deal with their varying length. The array has to be unpacked
+with @Code "aload" before calling {@Code setcolor}.
+}
+
+@LI { A pattern, denoted {@Code "p"}. For us, a pattern is
+either the PostScript null object, meaning to fill with solid
+color, or else it is a dictionary as returned by
+{@Code makepattern}. When such a dictionary is installed in
+the current graphics state, this code guarantees that it will
+contain two extra entries:
+@ID @Tbl
+ mv { 0.6vx }
+ aformat { @Cell @Code A | @Cell B }
+{
+@Rowa
+ ma { 0i }
+ A { "/UnderlyingColorSpace" }
+ B { A @Code cs as defined above }
+@Rowa
+ A { "/UnderlyingColor" }
+ B { A @Code c as defined above }
+ mb { 0i }
+}
+We need these extra entries to make color independent of
+texture: without them we would lose the current color when
+we set a texture. Because of these variables we can't share
+pattern dictionaries among graphics states. We must copy them.
+}
+
+@EndList
+This representation obeys the following invariant:
+@BulletList
+
+@LI {
+All components of the PostScript graphics state related to
+pattern and color have defined values (e.g. there is never a
+situation where we set color space but not color).
+}
+
+@LI {
+If the PostScript graphics state contains a @Code "/Pattern"
+colorspace, the pattern dictionary stored in the state has
+@Code "/UnderlyingColorSpace" and @Code "/UnderlyingColor"
+entries of types @Code cs and {@Code c}.
+}
+
+@LI {
+If the graphics state contains an uncolored @Code "/Pattern"
+colorspace, then the @Code "/UnderlyingColorSpace" and
+@Code "/UnderlyingColor" entries of the pattern dictionary
+stored in the state agree with the underlying color space
+and color stored in the graphics state.
+}
+
+@EndList
+And it has the following abstraction function:
+@BulletList
+
+@LI {
+If the graphics state colorspace is {@Code "/Pattern"}, then
+the abstract current texture is the pattern dictionary stored
+in the graphics state color. If the graphics state colorspace
+is not {@Code "/Pattern"}, then the abstract current texture
+is {@Code null}.
+}
+
+@LI {
+If the graphics state colorspace is {@Code "/Pattern"}, then the
+abstract colorspace and color are the values of
+@Code "/UnderlyingColorSpace" and @Code "/UnderlyingColor"
+in the pattern dictionary stored in the graphics state color.
+If the graphics state colorspace is not {@Code "/Pattern"},
+then the abstract current colorspace and color are as returned
+by @Code "currentcolorspace" and {@Code "[ currentcolor ]"}.
+}
+
+@EndList
+The following functions are private helpers for the public functions:
+@IndentedList
+
+@LI @OneRow -2px @Break @F @Verbatim @Begin
+% Current pattern (may be null): - LoutCurrentP p
+/LoutCurrentP
+{ %% -
+ currentcolorspace %% [ /name etc ]
+ 0 get /Pattern eq %% bool
+ { %% - (have pattern)
+ [ currentcolor ] %% [ comp0 ... compn p ]
+ dup length 1 sub get %% p
+ }
+ { %% - (no pattern)
+ null %% null
+ } ifelse %% p
+} def
+@End @Verbatim
+
+@LI @OneRow -2px @Break @F @Verbatim @Begin
+% Current color and color space: - LoutCurrentCCS c cs
+/LoutCurrentCCS
+{
+ LoutCurrentP dup null eq %% p bool
+ { %% null
+ pop [ currentcolor ] %% c
+ currentcolorspace %% c cs
+ }
+ { %% p
+ dup %% p p
+ /UnderlyingColor get exch %% c p
+ /UnderlyingColorSpace get %% c cs
+ } ifelse %% c cs
+} def
+@End @Verbatim
+
+@LI @OneRow -2px @Break @F @Verbatim @Begin
+% Make c, cs, and p current: c cs p LoutSetCCSP -
+/LoutSetCCSP
+{ %% c cs p
+ dup null eq %% c cs p bool
+ { %% c cs p (null pattern)
+ pop setcolorspace %% c
+ aload pop setcolor %% -
+ }
+ { %% c cs p (non-null pattern)
+ % copy pattern dictionary
+ 12 dict copy %% c cs p
+
+ % record cs and c in p
+ dup /UnderlyingColorSpace %% c cs p p /UCS
+ 3 index put %% c cs p
+ dup /UnderlyingColor %% c cs p p /UC
+ 4 index put %% c cs p
+
+ % do setcolorspace and setcolor
+ dup /PaintType get 1 eq %% c cs p bool
+ { %% c cs p (colored pattern)
+ [/Pattern] setcolorspace %% c cs p
+ setcolor %% c cs
+ pop pop %% -
+ }
+ { %% c cs p (uncolored pattern)
+ [ /Pattern %% c cs p [ /Pattern
+ 4 -1 roll %% c p [ /Pattern cs
+ ] setcolorspace %% c p
+ exch aload length 1 add %% p comp1 ... compm m+1
+ -1 roll %% comp1 ... compm p
+ setcolor %% -
+ } ifelse %% -
+ } ifelse %% -
+} def
+@End @Verbatim
+
+@EndList
+With the helper functions it's now easy to derive the colour and
+texture setting commands that we are offering to our end users.
+When setting the color we pass it, plus the current pattern, to
+{@Code "LoutSetCCSP"}; when setting the pattern we pass it, plus
+the current color, to {@Code "LoutSetCCSP"}. Note that there is
+no {@Code "/DeviceHSB"}: @Code "hsb" is a variant of {@Code "rgb"}.
+@IndentedList
+
+@LI @OneRow -2px @Break @F @Verbatim @Begin
+% num LoutSetGray -
+/LoutSetGray
+{
+ [ 2 1 roll ] %% c
+ [ /DeviceGray ] %% c cs
+ LoutCurrentP %% c cs p
+ LoutSetCCSP %% -
+} def
+@End @Verbatim
+
+@LI @OneRow -2px @Break @F @Verbatim @Begin
+% r g b LoutSetRGBColor -
+/LoutSetRGBColor
+{ %% r g b
+ [ 4 1 roll ] %% c
+ [ /DeviceRGB ] %% c cs
+ LoutCurrentP %% c cs p
+ LoutSetCCSP %% -
+} def
+@End @Verbatim
+
+@LI @OneRow -2px @Break @F @Verbatim @Begin
+% h s b LoutSetHSBColor -
+/LoutSetHSBColor
+{ %% h s b
+ gsave sethsbcolor %% -
+ currentrgbcolor grestore %% r g b
+ LoutSetRGBColor %% -
+} def
+@End @Verbatim
+
+@LI @OneRow -2px @Break @F @Verbatim @Begin
+% c m y k LoutSetRGBColor -
+/LoutSetCMYKColor
+{
+ [ 5 1 roll ] %% c
+ [ /DeviceCMYK ] %% c cs
+ LoutCurrentP %% c cs p
+ LoutSetCCSP %% -
+} def
+@End @Verbatim
+
+@LI @OneRow -2px @Break @F @Verbatim @Begin
+% p LoutSetTexture -
+/LoutSetTexture
+{
+ LoutCurrentCCS %% p c cs
+ 3 -1 roll %% c cs p
+ LoutSetCCSP %% -
+} def
+@End @Verbatim
+
+@EndList
+All we need now is some sample textures. Textures are just pattern
+dictionaries as returned by {@Code "makepattern"}. Here is
+a PostScript function that appears in the Lout prologue. Its
+function is to simplify the production of textures. It first
+takes six parameters to specify a transformation of the texture
+used to build the matrix taken by {@Code makepattern}, then
+five parameters that go into the pattern dictionary.
+@IndentedList
+
+@LI @OneRow -2px @Break @F @Verbatim @Begin
+% <scale> <scalex> <scaley> <rotate> <hshift> <vshift>
+% <pt> <bb> <xs> <ys> <pc> LoutMakeTexture p
+/LoutMakeTexture
+{ %% s sx sy r h v pt bb xs ys pp
+ 12 dict begin %% s sx sy r h v pt bb xs ys pp
+ /PaintProc exch def %% s sx sy r h v pt bb xs ys
+ /YStep exch def %% s sx sy r h v pt bb xs
+ /XStep exch def %% s sx sy r h v pt bb
+ /BBox exch def %% s sx sy r h v pt
+ /PaintType exch def %% s sx sy r h v
+ /PatternType 1 def %% s sx sy r h v
+ /TilingType 1 def %% s sx sy r h v
+ currentdict end %% s sx sy r h v p
+ 7 1 roll %% p s sx sy r h v
+ matrix translate %% p s sx sy r mat1
+ 5 1 roll %% p mat1 s sx sy r
+ matrix rotate %% p mat1 s sx sy mat2
+ 4 1 roll %% p mat1 mat2 s sx sy
+ matrix scale %% p mat1 mat2 s mat3
+ exch dup matrix scale %% p mat1 mat2 mat3 mat4
+ matrix concatmatrix %% p mat1 mat2 mat34
+ matrix concatmatrix %% p mat1 mat234
+ matrix concatmatrix %% p mat1234
+ /makepattern where
+ { %% p mat123 dict
+ pop makepattern %% p
+ }
+ { %% p mat123
+ pop pop null %% null
+ } ifelse %% p (may be null)
+} def
+@End @Verbatim
+
+@EndList
+For examples of textures using {@Code LoutMakeTexture}, consult
+the standard include file {@Code coltex}. There is only one
+built-in texture, {@Code LoutTextureSolid}:
+@IndentedList
+
+@LI @OneRow -2px @Break @F @Verbatim @Begin
+/LoutTextureSolid
+{
+ null
+ LoutSetTexture
+} def
+@End @Verbatim
+
+@RawEndList
+@End @Appendix