1. kshow

Show text with kerning procedure between characters.

1.1. Syntax

proc string kshow → -

1.2. Stack Effects

Before:

proc string

After:

(empty)

1.3. Description

kshow paints the characters of string in a manner similar to show, but allowing program intervention between characters.

If the character codes in string are c₀, c₁, …​ cₙ, kshow proceeds as follows:

  1. Shows c₀ at the current point, updating the current point by c₀'s width

  2. Pushes character codes c₀ and c₁ on the operand stack (as integers)

  3. Executes proc

  4. Continues by showing c₁, pushing c₁ and c₂, executing proc, and so on

  5. Finishes by pushing cₙ₋₁ and cₙ, executing proc, and showing cₙ

When proc is called for the first time, the graphics state (in particular, the CTM) is the same as it was at the time kshow was invoked, except that the current point has been updated by the width of c₀. Execution of proc is permitted to have any side effects, including changes to the graphics state. Such changes persist from one call of proc to the next and may affect graphical output for the remainder of kshow's execution and afterward.

The name kshow is derived from "kern-show." To kern characters is to adjust the spacing between adjacent pairs of characters in order to achieve a visually pleasing result. The kshow operator enables user-defined kerning and other manipulations, because arbitrary computations can be performed between each pair of characters.

kshow can be applied only to base fonts. If the current font is composite, kshow issues an invalidfont error.

1.4. Parameters

proc (procedure) : Procedure to execute between each character pair; receives two character codes on stack

string (string) : The text to display

1.5. Procedure Arguments

When proc is called, the stack contains:

char(n-1) char(n)

Where: - char(n-1) is the character just shown - char(n) is the next character to be shown

1.6. Examples

1.6.1. Simple Kerning Table

% Define kerning pairs
/kernPairs <<
  /AV -2    % Kern A-V pair by -2 units
  /Aw -1    % Kern A-w pair by -1 unit
  /To -1.5  % Kern T-o pair by -1.5 units
  /We -1    % Kern W-e pair by -1 unit
>> def

% Kerning procedure
/kern {  % char1 char2 kern -
  % Convert to name
  2 copy
  =string cvs exch =string cvs
  exch concatstrings cvn

  % Look up kerning
  kernPairs exch known {
    kernPairs exch get
    0 rmoveto
  } {
    pop pop
  } ifelse
} def

/Helvetica findfont 24 scalefont setfont
100 700 moveto
/kern load (WAVE) kshow

1.6.2. Inter-Character Effects

% Add dots between characters
/dotProc {  % char1 char2 dotProc -
  pop pop  % Ignore character codes
  currentpoint
  0.5 0 rmoveto
  0 0 1 0 360 arc fill
  moveto
  1 0 rmoveto  % Extra space after dot
} def

100 700 moveto
/dotProc load (SPACED) kshow

1.6.3. Dynamic Spacing Based on Character Pairs

% Tighter spacing for lowercase, wider for uppercase
/adaptiveKern {  % char1 char2 adaptiveKern -
  % Check if both are uppercase (65-90)
  dup 65 ge 1 index 90 le and
  2 index 65 ge 3 index 90 le and and {
    % Both uppercase: add space
    pop pop
    1 0 rmoveto
  } {
    % At least one lowercase: reduce space
    pop pop
    -0.3 0 rmoveto
  } ifelse
} def

100 700 moveto
/adaptiveKern load (MixedCase TEXT) kshow

1.6.4. Tracking Adjustment

% Progressively increase spacing through string
/progressiveSpacing {  % char1 char2 progressiveSpacing -
  pop pop
  currentpoint /y exch def /x exch def
  /spacing spacing 0.1 add def
  x spacing add y moveto
} def

/spacing 0 def
100 700 moveto
/progressiveSpacing load (EXPANDING) kshow

1.7. Errors

invalidaccess : Font or string has restricted access

invalidfont : Current font is not valid or is a composite font

nocurrentpoint : Current point is not defined

stackunderflow : Fewer than two operands on stack

typecheck : proc is not a procedure or string is not a string

1.8. Procedure Execution Context

The proc procedure:

Can access: - All graphics state parameters - Character codes being processed - Current point (via currentpoint)

Can modify: - Current point (via rmoveto, moveto) - Graphics state (colors, line width, etc.) - Any PostScript state

Receives: - Two integers on stack (previous and next character codes)

Should return: - No specific return value required - Stack should be clean (pop operands or leave results intentionally)

1.9. Common Kerning Patterns

1.9.1. Letter Pair Kerning

Common pairs that benefit from kerning:

Pair Adjustment Reason

AV, AW, Av, Aw

Negative

Diagonal creates visual gap

To, Tr, Tu

Negative

Overhang opportunity

LT, LY

Negative

Height difference

ff, fi, fl

Negative

Ligature-like pairs

WA, Wa

Negative

Diagonal intersection

1.9.2. Optical Kerning

% Kern based on character shapes, not just codes
/opticalKern {  % char1 char2 opticalKern -
  % Check for diagonal-straight combinations
  exch dup 65 eq exch 86 eq or  % A or V
  1 index dup 84 eq exch 87 eq or  % T or W
  and {
    -1.5 0 rmoveto
  } {
    pop
  } ifelse
} def

/Helvetica findfont 18 scalefont setfont
100 700 moveto
/opticalKern load (WAVES TRAVEL) kshow

1.10. Performance Considerations

  • Most expensive text operator due to procedure calls

  • Called length(string) - 1 times

  • Procedure invocation overhead per character pair

  • Graphics state changes persist

  • Use only when necessary for typographic quality

Performance comparison:

show           - Fastest
ashow          - Fast (simple arithmetic)
widthshow      - Fast (conditional check)
awidthshow     - Moderate (two conditionals)
kshow          - Slowest (procedure calls)

1.11. Kerning Best Practices

Define kerning tables: - Store kerning pairs in dictionaries - Precompute common adjustments - Use efficient lookup structures

Minimize procedure complexity: - Keep proc as simple as possible - Avoid unnecessary calculations - Cache computed values when possible

Test with target fonts: - Kerning values are font-specific - Verify with actual font metrics - Adjust for different point sizes

1.12. Limitations

Composite fonts: : kshow cannot be used with composite fonts; use cshow instead

Character boundaries: : Procedure is called between characters, not within character rendering

Stack management: : Procedure must properly manage the character code operands

1.13. See Also

  • show - Basic text painting

  • ashow - Uniform character spacing

  • widthshow - Selective character width adjustment

  • awidthshow - Combine ashow and widthshow

  • cshow - Show with procedure per character (Level 2)

  • stringwidth - Calculate text width


Back to top

Copyright © 2025 Ribose. PostScript is a trademark of Adobe. Distributed under the MIT License.