%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FILE BEGIN
%...:....1....:....2....:....3....:....4....:....5....:....6....:....7....:|
%234567890123456789012345678901234567890123456789012345678901234567890123456
%
% ((( The text can be seen best with tab-width 4. (But 8 should do it too.)
%      If necessary, it works, to replace everywhere:
%                          |%<tab>| --> |%.  |
%                           |<tab>| --> |    |     .
%      The effect can be reversed by replacing (`^' means `start of line'):
%                           |^%.  | --> |%<tab>|
%                           |^    | --> |<tab>|
%                       |<tab>    | --> |<tab><tab>|  ((iteratively)).
% )))
%
%%%%%%%%%

def
=========
= \
enddef;

def
=================
= \
enddef;

def
=======================================================================
= \
enddef;

=======================================================================
% ===================================================|  discreteness  |
=======================================================================
% Nearly nothing has been done yet for this problem.
=================
vardef Good.z primary u = ( good.x xpart u, good.y ypart u ) enddef;
vardef Good.x primary u = ( good.x xpart u,        ypart u ) enddef;
vardef Good.y primary u = (        xpart u, good.y ypart u ) enddef;
=======================================================================
% =========================================================== |  pen  |
=======================================================================
% define both used pens (and set data for top, bot, rt, lft)
=================
define_blacker_pixels( stroke_thickness_x, stroke_thickness_y );

currentpen :=  pencircle  xscaled 1.3 stroke_thickness_x
.                         yscaled 1.3 stroke_thickness_y;
point_pen   =  savepen;

currentpen :=  pencircle  xscaled stroke_thickness_x
.                         yscaled stroke_thickness_y;
stroke_pen  =  savepen;
=======================================================================
% ================================= |  convert dimensions to unsharp  |
=======================================================================
define_whole_vertical_pixels( dy_normal, dy_high, dy_shrinked );
define_whole_vertical_pixels( asc_dy_normal, asc_dz, asc_baseline_y );
define_whole_pixels         ( dx_high, asc_dx, glyph_distance
.                           , preliminary_bound_dist
.                           , preliminary_glyph_dist );
define_corrected_pixels     ( o );

if  dx_high = 0:  dx_high := floor infinity - glyph_distance;  fi
=======================================================================
% ======================================== |  standards ( vertical )  |
=======================================================================
% standard vertical coordinates and extensions
=======================================================================
numeric  ys_normal  ;      ys_normal  =  - 1/2 dy_normal;
=========
numeric  yn_normal  ;     -ys_normal  +  yn_normal    =  dy_normal  ;
numeric  yn_high    ;     -ys_normal  +  yn_high      =  dy_high    ;
numeric  yn_shrinked;     -ys_normal  +  yn_shrinked  =  dy_shrinked;
=========
pair     sn_normal  ;      sn_normal   =  ( ys_normal, yn_normal   );
pair     sn_high    ;      sn_high     =  ( ys_normal, yn_high     );
pair     sn_shrinked;      sn_shrinked =  ( ys_normal, yn_shrinked );
=========
pair     sn_roofed  ;      sn_roofed   =  sn_high;
=======================================================================
% ============================================== |  preferred unit $  |
=======================================================================
% $ :  preferred unit for heights and widths (formally it's a function)
%      we take `$' as unit, such that $ 12 = $$ = normal height
=================
numeric $$;       $$  =  dy_normal;
vardef  $  primary e  =  e * $$ / 12  enddef;
=======================================================================
% ======================================= |  low, mid, ... distances  |
=======================================================================
numeric  distance_x_low, distance_x_mid, stroke_distance_x,
.                        distance_y_mid, stroke_distance_y;
=================
.                          % stroke_distance includes stroke_thickness
distance_x_low    =  $ 1   ;
distance_x_mid    =  $ 1.25;
stroke_distance_x =  $ 1.5 ;  % 4 stroke_distance_x = rrx ip\328
=========
distance_y_mid    =  distance_x_mid;
stroke_distance_y =  stroke_distance_x;
=======================================================================

% %%%%%%%%     % ########### |  BEG PART 1  : tools                   |
% #####################################################################

=======================================================================
% =================================================== |  save sparks  |
=======================================================================

let  plusplus = ++;   % we need this spark for another purpose later on
.                     % (but it can be used in its original meaning too)

=======================================================================
% ================================================ |  type notations  |
=======================================================================
% Let's prefer to use type notations with some (more) semantics ...
=======================================================================
	let  nangle  =  numeric;  % angle
	let  figure  =  numeric;  % figure representative
	let  numer   =  numeric;  % other number

	let  pairp   =  pair   ;  % point
	let  pairv   =  pair   ;  % vector
	let  paird   =  pair   ;  % direction
%	let  pair    =  pair   ;  % other pair (not point / vector / direction)

	let  pathl   =  path   ;  % straight line % not really used yet
	let  pathj   =  path   ;  % jet
%	let  path    =  path   ;  % other path
=======================================================================
% ... and to use abbreviations to reduce distracting redundancy, ...
=======================================================================
	def  Def        suffix v  =  save v;    quote def    v        enddef;
	def  Vardef     suffix v  =  save v;    quote vardef v        enddef;
=================
	def  Boolean    suffix v  =  save v;    boolean      v;    v  enddef;
	def  String     suffix v  =  save v;    string       v;    v  enddef;

	def  Numer      suffix v  =  save v;    numer        v;    v  enddef;
	def  Nangle     suffix v  =  save v;    nangle       v;    v  enddef;
	def  Figure     suffix v  =  save v;    figure       v;    v  enddef;

	def  Pair       suffix v  =  save v;    pair         v;    v  enddef;
	def  Paird      suffix v  =  save v;    paird        v;    v  enddef;
	def  Pairp      suffix v  =  save v;    pairp        v;    v  enddef;
	def  Pairv      suffix v  =  save v;    pairv        v;    v  enddef;

	def  Path       suffix v  =  save v;    path         v;    v  enddef;
	def  Pathl      suffix v  =  save v;    pathl        v;    v  enddef;
	def  Pathj      suffix v  =  save v;    pathj        v;    v  enddef;

	def  Transform  suffix v  =  save v;    transform    v;    v  enddef;
=================
	def  NUMER      text vv   =  save vv;   numer        vv;      enddef;
	def  PAIR       text vv   =  save vv;   pair         vv;      enddef;
	def  PATH       text vv   =  save vv;   path         vv;      enddef;
	def  STRING     text vv   =  save vv;   string       vv;      enddef;
	def  BOOLEAN    text vv   =  save vv;   boolean      vv;      enddef;
=========
	def  FIGURE  =  NUMER  enddef;
	def  PAIRP   =  PAIR   enddef;
	def  PATHL   =  PATH   enddef;
=================
	def  PairArray    text vv  =
		forsuffixes  v = vv :
			save  v;    pair    v[];    numer  v .hix;    v .hix := -1;
		endfor
	enddef;
=========
	def  PathArray    text vv  =
		forsuffixes  v = vv :
			save  v;    path    v[];    numer  v .hix;    v .hix := -1;
		endfor
	enddef;
=========
	def  NumerArray   text vv  =
		forsuffixes  v = vv :
			save  v;    numer   v[];    numer  v .hix;    v .hix := -1;
		endfor
	enddef;
=========
	def  StringArray  text vv  =
		forsuffixes  v = vv :
			save  v;    string  v[];    numer  v .hix;    v .hix := -1;
		endfor
	enddef;
=========
	def   PairpArray  =   PairArray  enddef;
	def  FigureArray  =  NumerArray  enddef;
=======================================================================
% ... but to avoid wrong semantics.
=======================================================================
	let  first   =  xpart;  % for ordinary pairs
	let  second  =  ypart;  % for ordinary pairs
=========
	Def  part  primary xy  =  if  xy = 0: xpart  else: ypart  fi  enddef;
=======================================================================
% ========================================================== |  user  |
=======================================================================
% user_intervention: asks user for wanted command
=======================================================================
Def   user_intervention( text condition ) expr mess  =
	if  condition :
		begingroup
			STRING  answer;

			message mess;
			forever:
				message "enter a command or hit return: ";
				answer := readstring;
				exitif      answer = "";
				scantokens  answer;
			endfor
		endgroup
	fi
enddef;
=======================================================================
% =========================================== |  user: error message  |
=======================================================================
% error: eject an error message
% hope : assertion with reaction, if it fails
%        (no check on validity, if error_handling <= 0)
%        ((There's only one use yet.))
=======================================================================
StringArray  err;

begingroup
	Def  !( suffix s ) primary tt =
		numer  err.s;    err.s = incr err .hix;    err[ err.s ] = tt;
	enddef;

	!( argument_type_first         ) "Type of 1st argument not intended"
	!( argument_type_second        ) "Type of 2nd argument not intended"
	!( arguments_number            ) "Number of arguments not intended"
	!( arguments_types             ) "Type of arguments not intended"
%	!( args_type_not_implemented   ) "Argument type not implemented"
%	!( assignment_for_i_only       ) "Assignment implemented for i only"
%	!( equal_points                ) "Points are equal"
%	!( fig_mem_overflow            ) "Figure memory overflow"
	!( foc_forgotten               ) "Focus value forgotten. Will take 0 instead"
	!( invalid_bound               ) "Invalid bound access"
%	!( near_of_infinity_points     ) "Points are near of infinity"
	!( no_intersection_first       ) "No intersection with first/only bound path"
	!( no_intersection_second      ) "No intersection with second bound path"
	!( paths_dont_intersect        ) "The paths don't intersect"
	!( sectors_not_addable         ) "Sectors not addable"
	!( shifts_per_transf_figure    ) "To many shifts per transformed figure"
	!( statement_string_unintended ) "Statement string unintended"
	!( stripe_number_contra_list   ) "Stripe number contradicts list length"
	!( transformations_per_figure  ) "To many transformations per figure"
	!( unknown_path                ) "Unknown path"
	!( unknown_sign_list           ) "Unknown sign list"
endgroup ;
=================
Def   error( suffix sfx ) =
	hide( errmessage  err[ err .sfx ]; )
enddef;
=================
if error_handling > 0:
	save  xxx_err;     boolean  xxx_err;

	Def  Begingroup  =  error_frame (  enddef;
	Def    Endgroup  =  \              enddef;

	Def  error_frame( text t )  =
			begingroup
				forever:  t  exitif true;  endfor
			endgroup
	enddef;

	Def  hope( expr b )( text reaction ) =
		xxx_err := b;
		if not xxx_err :  reaction fi
		exitif not xxx_err;
	enddef;

else:
	Def  Begingroup  =  begingroup             enddef;
	Def    Endgroup  =    endgroup  gobble ( 0 enddef;

	Def  hope( expr b )( text reaction )  =  \  enddef;
fi
=======================================================================
% ================================================ |  user: show ...  |
=======================================================================
% show_arr: show contents of an array, which uses standard bound setting
% show_fig: show some parameters of a figure (but not its picture)
=======================================================================
Def   show_arr  suffix u  =
	show "=== "  &  str u  &  " ===:";
	for  j = 0  upto  u .hix :  show u[ j ];  endfor
enddef;
=================
Def   show_fig  primary f  =
	show  "figure "  &  decimal f  &  ": "  &  op_string op f
		if      op f = op_plus:
	,     " lef= "  &  decimal lef f  &  ", rgt= "  &  decimal  rgt f
		elseif  op f = op_path:
	,     pth f
		fi
	,     trf f;
	show  "min/max x-value: "
	&     "( " & decimal( f.?.x_w ) & ", " & decimal( f.?.x_e ) & " )";
	show  "min/max y-value: "
	&     "( " & decimal( f.?.y_s ) & ", " & decimal( f.?.y_n ) & " )";
enddef;
=======================================================================
% ============================== |  early needed constants/functions  |
=======================================================================
Numer  asc_temp_base         = -128;
Numer  preliminary_temp_base = -256;
=======================================================================
% ==================================== |  early needed: function new  |
=======================================================================
Def   new  suffix sfx  =
	if  unknown  sfx .hix :  hide( sfx .hix := -1; )  fi
	sfx[ incr sfx .hix ]
enddef;
=======================================================================
% ===================================================== |  sign list  |
=======================================================================
% One sign list only is implemented,
% but 25 others are possible
% (with the upper case letter, assigned to it):
%
% I - Iravatham Mahadevan ( list from ((1))   below )
% A - Asko Parpola        ( list from ((2))   below )
% S - Seppo Koskenniemi   ( list from ((3))   below )
% K - Kimmo Koskenniemi   ( list from ((4.3)) below )
% (other upper case letters can be used for other sign lists)
%
% (The pseudo name XYz will mark,
%  where we need to add something to handle another sign list.)
%
% `I' works (let's hope it).
% `A' runs too - but only 5 of its 398 signs will be produced.
% `S', `K': only some comments are inserted for these lists yet,
%     and sketchy lists of `preliminary signs' have been provided.
%     (No doubt, there are errors in these comments/lists yet.)
%
%  ((1)) Iravatham Mahadevan
%        The Indus Script: Texts, Concordances and Tables
%        New-Delhi, 1977
%        (Memoirs of the Archaeological Survey of India No. 77)
%
%  ((2)) Asko Parpola
%        Deciphering the Indus script
%        Cambridge, 1994
%
%  ((3)) Seppo Koskenniemi, Asko Parpola, Simo Parpola
%        A Concordance to the Indus Inscriptions
%        (Materials for the Study of the Indus Script, Vol. I)
%        Helsinki, 1973, Suomalainen Tiedeakatemia
%
%  ((4.3)) Kimmo Koskenniemi, Asko Parpola
%        A Concordance to the Texts in the Indus Script
%        (Department of Asian and African Studies,
%        University of Helsinki, Research Reports, No. 3)
%        Helsinki, 1982
=======================================================================
% sign_list: information on sign lists
%            sign_lists will be indexed by 1 upto 26
=================
save     sign_list;
boolean  sign_list[];  % sign_list called into existence?
=======================================================================
% Information on sign_lists will be initialised by seven `steps':
=======================================================================
% First step: The sign lists get a short name.
%             (It will be equated to a number by step 3.)
=================
Def   sign_lists  =
	. IMa         % list from ((1))    above
	, APa         % list from ((2))    above
	, SKo         % list from ((3))    above
	, KKo         % list from ((4.3))) above
%	, XYz         % list from ((?))    above
enddef;
=======================================================================
% Second step: Associate a (one lowercase letter-) suffix
%              to every sign list.
%             (It will be used to associate short names (as `iwe')
%              with the list as for short sign names (as `i123').)
=================
Def   sign_list_suffix   suffix sigl_sfx =
	if      str sigl_sfx = "IMa" :  i
	elseif  str sigl_sfx = "APa" :  a
	elseif  str sigl_sfx = "SKo" :  s
	elseif  str sigl_sfx = "KKo" :  k
%	elseif  str sigl_sfx = "XYz" :  x
	fi
enddef;
=======================================================================
% Third step: Equate every sign lists short name to a number.
%             (This number is used as primary reference to the sign list.)
%             Mark sign list as existent.
=================
% Three helper functions first,
% to convert between sign list number
%                and sign list suffix (realized as string):
=================
Def   sign_list_string_lc  primary sigl_number =
	char( ASCII "a" + sigl_number - 1 )
enddef;
=================
Def   sign_list_string_uc  primary sigl_number =
	char( ASCII "A" + sigl_number - 1 )
enddef;
=================
Vardef   sign_list_number  primary sigl_string =
	ASCII sigl_string  -  ASCII "a"  +  1
enddef;
=================
forsuffixes  sigl_sfx = sign_lists :
	Numer sigl_sfx = sign_list_number( str sign_list_suffix sigl_sfx );
	sign_list[ sigl_sfx ] :=  true;
endfor;
=======================================================================
% Fourth step: Enter the sign number range for every sign list:
%
%   (Its assumed here, that signs are numbered by natural numbers,
%    taken from the range 1 .. 4095.
%    For integer numbers out of this range, or fractional numbers,
%    we would need some reprogramming,
%    as would be necessary for non-numbered signs.)
=================
Def   last_sign_in_sign_list  primary sigl =
	if      sigl = IMa: (417 +  2) % 2 signs, discovered late: i418, i419
	elseif  sigl = APa: (386 + 12) % 12 questionable signs
	elseif  sigl = SKo: (399     ) % but 37 variants too
	elseif  sigl = KKo: (403     ) % but 62 variants too
%	elseif  sigl = XYz: ( ?      ) % ?
	else              :   0        error( unknown_sign_list )
	fi
enddef;
=======================================================================
% Fifth step: classify the sign lists mentioned,
%             to avoid wasting of resources for lists not handled seriously
=================
% The stages roughly means:
%
%   stage_d: names as `iwe' has been used for the list,
%            such that these names will be used
%            in case the list is not the actual ASL list too
%   stage_c: there is some code for the list
%   stage_b: the list has been mentioned only
%   stage_a: the list is a possible one
%
% There is no real harm to give a list a stage, unnecessarily high.
=================
Def   sign_lists_implemented_stage_d  =  IMa, APa             enddef;
Def   sign_lists_implemented_stage_c  =  IMa, APa             enddef;
Def   sign_lists_implemented_stage_b  =  IMa, APa, SKo, KKo   enddef;
% (XYz)
Def   sign_lists_possible  =  for xx = 1 upto 26: ,xx endfor  enddef;
=================
% and - to make things easy - for stage_d additionally:

Def   sign_lists_implemented_suffixes =    i,   a       enddef;
=======================================================================
% Sixth step: Define some functions:
=================
% signs_in_sign_list: list of all signs, a list could contain
% (We include the number range of ASCII signs too. (Wrong hack!!))
% (We include preliminary signs too. (Wrong hack!!))
=================
Def   signs_in_sign_list  primary sigl =
	if  known  sign_list[ sigl ] :
		for  sig = 0   upto  last_sign_in_sign_list( sigl ): , sig  endfor
		for  sig = asc_temp_base  upto  asc_temp_base + 127: , sig  endfor
		for  sig = preliminary_temp_base
		.    upto  preliminary_temp_base - 1
		.             + llength( list_of_preliminary_glyph_strings ):
		.                                                    , sig  endfor
	else :
		error( unknown_sign_list )
	fi
enddef;
=================
% There are three ways, to call a sign:
%    by a pair   - examples: ( IMa, 123 ), (APa, 2 )
%       i.e. ( sign_list_number, sign_number )
%    by a string - examples: "i123", "a002"
%       i.e.   sign_list_string_lc(sign_list_number)
%            & decimal sign_number  (but with a three-digits-number)
%    by the suffix, this string represents - examples: i123, a002
=================
% sign_name: produce the second calling form from the first
=================
Vardef   sign_name  primary sign_id =
	sign_list_string_lc( first sign_id )
	if  second sign_id <  10 :  &  "0"  fi
	if  second sign_id < 100 :  &  "0"  fi
	&  decimal( second sign_id )
enddef;
=======================================================================
% Last step: Define the sign list, we will actually produce signs for.
%            (We only allow to produce signs for one list in a run yet.
%             But that should be changed ...)
=================
numeric  ASL;    ASL := IMa;    % ASL ~ Actual Sign List
=======================================================================
% ========================================================== |  type  |
=======================================================================
% assign_type: type a variable according to an expression
=======================================================================
Def   assign_type( text v )( expr u ) =
	if      numer     u :  numer     v;
	elseif  pair      u :  pair      v;
	elseif  path      u :  path      v;
	elseif  picture   u :  picture   v;
	elseif  pen       u :  pen       v;
	elseif  transform u :  transform v;
	elseif  boolean   u :  boolean   v;
	elseif  string    u :  string    v;
	fi
enddef;
=======================================================================
% ======================================================= |  boolean  |
=======================================================================
% cand, cor : conditional and, or (from METAFONTbook, p. 289)
% tT, fF    : short names of boolean values
%             (to use, where the full names are to long)
=======================================================================
Def   cand( text q )  =  startif true   q  else: false fi  enddef;
Def   cor ( text q )  =  startif true true else:   q   fi  enddef;
tertiarydef  p startif true  =  if p:  enddef;
=================
Boolean  tT = true ;
Boolean  fF = false;
=======================================================================
% ======================================================= |  numeric  |
=======================================================================
% x  -+  y  : Operator `-' (minus), but operands in reversed order.
%             Operation for numeric and for pair operands.
%             (read it as `move from x to y',
%                   or as `leave x, goto y',
%                   or as `vector from x to y')
% signature : `sign' of  mathematics
% even      : ...
=======================================================================
secondarydef  x  -+  y  =  -x + y  enddef;
=================
Def   signature  primary e  =
	if  e < 0:  -1    elseif e > 0:  1    else:  0  fi
enddef;
=================
Def   even  =  not odd   enddef;
=================
Numer  golden_ratio = ( sqrt 5 - 1 )/2; % 0.61804; 1/g._ratio = 1.61801
=======================================================================
% ======================================================= |  algebra  |
=======================================================================
% quadr_eq: Solve a * (x**2) + b * x + c = 0 for a<>0,
%           assuming real solutions exist.
%          (Used only once yet. Not checked on all risks.)
=======================================================================
Vardef  quadr_eq( expr a, b, c ) =
	Numer ph  =  (0.5 b)/a;
	Numer qh  =  sqrt abs( c/a );
	save +--+;   def +--+ = if c/a > 0: +-+ else: ++ fi enddef;

	( -ph - ( ph +--+ qh ), -ph + ( ph +--+  qh ) )
enddef;
=======================================================================
% ========================================================= |  angle  |
=======================================================================
% The notion of angle has been changed here:
% 1) angle 0 denotes north direction
%       (Many signs are symmetrical to the y-axis.)
% 2) angles are metered clockwise
%       (no strong reason)
% ---------------------------------------------------
% Angle, Dir: as `angle', `dir'
%             adapted to the changes of angle notion;
%             Angle extended on paths and path-figures too.
% normal    : reduces angle onto [0 .. 360)
% tand, cotd: trigonometric functions
% interangle: as interpath
=======================================================================
Def   Angle      primary e  =
	if      pair   e :  normal( -angle e  +  90 )
	else             :  Angle vect e
	fi
enddef;
=================
Def   Dir          primary e  =  dir( -e + 90 )   enddef;
=================
Def   normal       primary e  =  ( e  mod 360 )   enddef;
=================
Def   tand         primary e  =  ( sind e / cosd e )  enddef;
Def   cotd         primary e  =  ( cosd e / sind e )  enddef;
=================
Def   interangle  ( expr f, x, y ) =    % 0 <= f <= 1;   x, y normalized
	if  x <= y :        f[ x, y ]
	else       : normal f[ x, y + 360 ]
	fi
enddef;
=======================================================================
% ========================================================== |  pair  |
=======================================================================
% !!  : (numeric) x -> x * ( -1, +1 )
%       (to store the bounds of bound symmetrical glyphs in a pair)
% !!! : reverse a pair
%       (some glyphs have the bounds of another, but reversed)
%       ((seldom used - candidate to be eliminated))
% OQ  : short name of origin
% Decimal : as `decimal', but extended for pairs
=======================================================================
Def   !!   primary p  =  ( -p, +p )  enddef;
=================
Def   !!!  primary p  =  ( -second p, -first p )  enddef;
=================
Pair  OQ   =  origin;
=================
Def   Decimal  primary p  =
	if pair p: "(" & decimal first p & ", " & decimal second p & ")"
	else     : decimal p
	fi
enddef;
=======================================================================
% ========================================================== |  path  |
=======================================================================
% Nearly all of the definitions here are (either/or/or both):
% 1. extensions of operations to path-figures or paths as operands
% 2. modified, special or generalized versions of basic path operations
%
% Some of the functions could be generalized to work for any figure,
% not a path-figure only. But there was no need to do it yet.
=======================================================================
% =================================== |  path: elementary operations  |
=======================================================================
% ppath        : path or path-figure --> its path
% beg, mid, fin: first, middle, last point of path
% vect         : vector from start to end of a path(-figure)
=======================================================================
Def   ppath  primary e   =
	if  figure e :  ( pth e  transformed  trf e   reversed  rev e )
	else         :  e
	fi
enddef;
=================
Vardef   beg  primary p  =  Point  0             of  p   enddef;
Vardef   mid  primary p  =  Point  0.5 Length p  of  p   enddef;
Vardef   fin  primary p  =  Point      Length p  of  p   enddef;
		% (`fin' is not thought to be used for cycles)
=================
Def   vect  primary f  =  ( beg f  -+  fin f )   enddef;
=================
join_radius       :=  $ 0.5;   % parameter for softjoin
=======================================================================
% ===================================== |  path: extended operations  |
=======================================================================
% For most of the path operations
% we need extensions, which work with path-figures too.
% They will be named as the original, but with first letter uppercase.
=======================================================================
% Direction: extended `direction'
% Point    : extended `point'
% Length   : extended `length'
% Subpath  : extended `subpath'
%            additionally it accepts a point pair as first argument
%            - represented by a path between the points.
%            (The points need to be points on the path.)
%
% Intersectiontimes: extended `intersectiontimes'
% Intersectionpoint: extended `intersectionpoint'
%
% non_it: intersectiontimes  `no intersection' value
% non_ip: intersectionpoints `no intersection' value
=======================================================================
Def   Direction  expr e  of p  =  direction  e  of  ppath p   enddef;
Def   Point      expr e  of p  =  point      e  of  ppath p   enddef;

Def   Length     primary    p  =
	if      pair p :  0
	elseif  path p :  length p
	else           :  if  p = zero: -1  else: length ppath p  fi
	fi
enddef;
=================
Vardef   Subpath  expr e  of  p  =
	Path  pp = ppath p;
	if   pair e :  subpath  e  of  pp
	else        :  Numer  ta  =  first( pp intersectiontimes beg e );
	.              Numer  tb  =  first( pp intersectiontimes fin e );
	.              if ( tb < ta )  and  cycle p:
	.                  tb := tb  +  Length pp;
	.              fi
	.              subpath ( ta, tb ) of pp
	fi
enddef;
=================
secondarydef  p  Intersectiontimes  q  =
	ppath p  intersectiontimes  ppath q
enddef;
=================
Pair   non_it = ( -1, -1 );
=================
secondarydef   p Intersectionpoint q  =
	ppath p  intersectionpoint  ppath q
enddef;
=================
Pair   non_ip = (  0,  0 );
=======================================================================
% ===================================== |  path: modified operations  |
=======================================================================
% Intersectionpoint_left : intersectionpoint, being on the left operand
% Intersectionpoint_right: ditto, on the right operand
% first_intersection: intersection point with minimal xpart
% last_intersection : intersection point with maximal xpart
% intersection_at   : ... ... minimal/max. xpart, chosen by parameter
% where_x, where_y  : point on path/figure with given xpart/ypart
% first_where_y     : point with given ypart, with minimal xpart
% last_where_y      : point with given ypart, with maximal xpart
% where_y_at        : ... ... minimal/max. xpart, chosen by parameter
=======================================================================
secondarydef   p  Intersectionpoint_left  q  =
begingroup
	Path   pp  =  ppath p;
	NUMER  xx, yy;
	( xx, yy )  =  pp  intersectiontimes  ppath q;

	if   xx < 0 :  non_ip          error( paths_dont_intersect )
	else        :  point xx  of pp
	fi
endgroup
enddef;
=================
secondarydef   p  Intersectionpoint_right  q  =
	q  Intersectionpoint_left  p
enddef;
=================
Def   first_intersection  =  intersection_at( 0 )   enddef;
Def    last_intersection  =  intersection_at( 1 )   enddef;
=================
secondarydef    f  intersection_at  l_or_r =
	intersection_at_implementation( f, l_or_r )
enddef;
================= % non-public:
Vardef   intersection_at_implementation( expr f, l_or_r ) secondary g =
	PairpArray  qq;
	intersection_points( f, g )( qq );
	qq[   if  l_or_r = 0:  MiaX( < )  else:  MiaX( > )  fi   qq ]
enddef;
=================
secondarydef  p where_x x = p Intersectionpoint_right line((x,0),  0) enddef;
secondarydef  p where_y y = p Intersectionpoint_right line((0,y), 90) enddef;
	% ---------------------------------------------------------------
	% (There is some doubt here on `..._right': We get a point on p,
	%  but the xpart/ypart may differ from the given value.
	%  Is it that, what we need? Or would `..._left' be right?
	%  Should we delete `_left' as `_right'?
	%  Or should we split both functions into two? )
	% ---------------------------------------------------------------
=================
Def   first_where_y  =  where_y_at( 0 )  enddef;
Def    last_where_y  =  where_y_at( 1 )  enddef;
=================
primarydef    f  where_y_at  l_or_r =
	where_y_at_implementation( f, l_or_r )
enddef;
================= % non-public:
Def   where_y_at_implementation( expr f, l_or_r ) secondary y =
	intersection_at_implementation( f, l_or_r )  line( (0,y), 90 )
enddef;
=======================================================================
% ========================================== |  path: new operations  |
=======================================================================
% meets : do paths or figures intersect?
=======================================================================
secondarydef   p meets q  =
(
	if      figure p :
		if      op p = op_path :  q  meets  ppath p
		elseif  op p = op_plus :      (  fig_left p  meets  q )
		.                         cor ( fig_right p  meets  q )
		else                   :  false            % op p = op_zero
		fi
	elseif  figure q :  q meets p
	else             :  p intersectiontimes q  <>  non_it
	fi
)
enddef;
=======================================================================
% collect_paths:
%   Collects (modified) paths of path/pair/figure f, appending them to pp.
%   The paths will be modified by given transformation t and reversion v.
=======================================================================
Vardef   collect_paths( expr f )( suffix pp )( expr t, v ) =
	if         path f
	.      or  pair f :   new pp  =  f  transformed t  reversed v;
	elseif  figure  f :
		if      op f = op_path : new pp = pth f
		.                         transformed ( trf f  transformed t )
		.                         reversed    ( rev f  reversed    v );
		elseif  op f = op_plus : collect_paths( lef f )( pp )
		.                                     ( trf f  transformed t )
		.                                     ( rev f  reversed    v );
		.                        collect_paths( rgt f )( pp )
		.                                     ( trf f  transformed t )
		.                                     ( rev f  reversed    v );
		fi
	else :  error( argument_type_first )
	fi
enddef;
=======================================================================
% ======================================================== |  string  |
=======================================================================
% find( u, v ): index of most left occurrence of v in u (or -1)
% p is_in q   : is string p substring of q?
=======================================================================
Vardef   find( expr q, e )  =
	Numer  rx := -1;

	if  known q   and   known e :
		for  qx = 0   upto   length q - length e:
			if  e = substring( qx, qx + length e ) of q:  rx := qx;  fi
			exitif  rx <> -1;
		endfor
	fi

	rx
enddef;
=================
secondarydef   p is_in q  =  ( find( q, p ) >= 0 )  enddef;
=======================================================================
% =============================================== |  transformations  |
=======================================================================
% build_trf   : create a transformation with given parts
% ship        : get shift part of given transformation
% is_shift    : is given transformation a shift only?
% Transformed : as transformed, but with figure as first operand too
% Scaled      : as  scaled    , but with figure as first operand too
%                             , and with pair possible as 2nd operand
% Xscaled     : as xscaled    , but with figure as first operand too
% Yscaled     : as yscaled    , but with figure as first operand too
=======================================================================
Vardef   build_trf( expr part___xy, part_x_xy, part_y_xy ) =
	save  t;   transform  t;

	(  xpart t,  ypart t )  =  part___xy;
	( xxpart t, xypart t )  =  part_x_xy;
	( yxpart t, yypart t )  =  part_y_xy;

	t
enddef;
=================
Vardef   ship  primary t  =  ( xpart t, ypart t )  enddef;
=================
Vardef   is_shift  primary t =
	.    ( xxpart t = 0 )
	and  ( xypart t = 0 )
	and  ( yxpart t = 0 )
	and  ( yypart t = 0 )
enddef;
=================
primarydef    f  Transformed  t =
	if  figure f :  copy( f, t )
	else         :  f  transformed  t
	fi
enddef;
=================
primarydef  f  Scaled e  =
	if not pair e:      f Transformed( identity  scaled e )
	else         :      f Transformed( identity xscaled first  e
	.                                           yscaled second e )
	fi
enddef;

primarydef  f Xscaled e  =  f Transformed( identity xscaled e )  enddef;
primarydef  f Yscaled e  =  f Transformed( identity yscaled e )  enddef;
=======================================================================
% ========================================== |  transformations: ...  |
=======================================================================
% The following operators are in relation to the MF original operations:
% 1) on figure operands extended versions,
% 2) shorter or more handy variations.
% They allow to use `~' in the 2nd operand as reference to the first.
% Example:
%    I.a xsh( rrx ~ )
% means:
%    I.a xsh( rrx I.a ), i.e. shift I.a in x-direction by its x-width
=======================================================================
% b shi e: shift b by e
% b xsh e: shift b by e (or xpart e), but in x-direction only
% b ysh e: shift b by e (or ypart e), but in y-direction only
% b scx e: scale b, such that e gives the new x-width
% b scy e: scale b, such that e gives the new y-width
% b xsc e: scale b, in x direction only - e gives the new x-width
% b ysc e: scale b, in y direction only - e gives the new y-width
% b zsc e: scale b, in both directions - pair e gives ( x-width, y-width )
% b sla e: slant b by e
% b |>  e: rotate b by e clockwise
% b |<  e: rotate b by e anti-clockwise
% b Reflectedabout c: as reflectedabout, but for figures too
% b Rotatedaround  c: as rotatedaround , but for figures too
% b ||              : b Reflectedabout y-axis
% b   |:            : b Reflectedabout x-axis
% b |||:            : b Reflectedabout origin
=======================================================================
Def  shi =              name_left_argument  dummy ( ~ )  shi_op  enddef;
Def  xsh =              name_left_argument  dummy ( ~ )  xsh_op  enddef;
Def  ysh =              name_left_argument  dummy ( ~ )  ysh_op  enddef;
Def  scx =              name_left_argument  dummy ( ~ )  scx_op  enddef;
Def  scy =              name_left_argument  dummy ( ~ )  scy_op  enddef;
Def  xsc =              name_left_argument  dummy ( ~ )  xsc_op  enddef;
Def  ysc =              name_left_argument  dummy ( ~ )  ysc_op  enddef;
Def  zsc =              name_left_argument  dummy ( ~ )  zsc_op  enddef;
Def  sla =              name_left_argument  dummy ( ~ )  sla_op  enddef;
Def  |>  =              name_left_argument  dummy ( ~ )  ror_op  enddef;
Def  |<  =              name_left_argument  dummy ( ~ )  rol_op  enddef;
=================
Def  Reflectedabout  =  name_left_argument  dummy ( ~ )  rfl_op  enddef;
Def  Rotatedaround   =  name_left_argument  dummy ( ~ )  rot_op  enddef;
=================
Def  ||    =  rfl_op (  down , up    )   enddef;
Def    |:  =  rfl_op (  left , right )   enddef;
Def  |||:  =  rot_op ( origin, 180   )   enddef;
=======================================================================
% shi_op, ..., rfl_op are non-public functions only
=======================================================================
primarydef  f shi_op d =
	f  Transformed  ( identity  shifted d )
enddef;
=================
primarydef  f xsh_op d =
	f  Transformed  ( identity  shifted ( if pair d: xpart fi d, 0 ) )
enddef;
=================
primarydef  f ysh_op d =
	f  Transformed  ( identity  shifted ( 0, if pair d: ypart fi d ) )
enddef;
=================
primarydef  f scx_op d =
	f  Transformed  ( identity  scaled ( d / rrx f ) )
enddef;
=================
primarydef  f scy_op d =
	f  Transformed  ( identity  scaled ( d / rry f ) )
enddef;
=================
primarydef  f xsc_op d =
	f  Transformed  ( identity xscaled ( d / rrx f ) )
enddef;
=================
primarydef  f ysc_op d =
	f  Transformed  ( identity yscaled ( d / rry f ) )
enddef;
=================
primarydef  f zsc_op d  =
	if  pair d:
		f  Transformed  ( identity  xscaled ( xpart d / rrx f )
		.                           yscaled ( ypart d / rry f ) )
	else:
		f  Transformed  ( identity  xscaled (       d / rrx f )
		.                           yscaled (       d / rry f ) )
	fi
enddef;
=================
primarydef  f sla_op d  =
	f  Transformed  ( identity  slanted  d )
enddef;
=================
primarydef  f ror_op d  =
	f  Transformed  ( identity  rotated -d )
enddef;
=================
primarydef  f rol_op d  =
	f  Transformed  ( identity  rotated +d )
enddef;
=================
Def   rot_op( expr z, d )  =
	Transformed ( identity  rotatedaround ( z, -d ) )
enddef;
=================
Def   rfl_op( expr X, Y )  =
	Transformed ( identity  reflectedabout( X, Y ) )
enddef;
=======================================================================
% special helpers (non-public):
=======================================================================
primarydef   f  name_left_argument  dummy  =
	assign_type_and_value_left_to_right__give_it( f )
enddef;
=================
Vardef   assign_type_and_value_left_to_right__give_it( expr f ) suffix n =
	assign_type( n )( f );
	n = f;
	n
enddef;
=======================================================================
% ========================================================= |  order  |
=======================================================================
% MiaX: index of `minimal' elememt in given array
%       the order relation will be given by argument
%       so it can be the maximal elememt, in terms of the natural order
=======================================================================
Vardef   MiaX ( text < ) suffix u =
	Numer  ex := u.hix;

	for  ux = u.hix - 1  downto  0 :
		if  u[ ux ] < u[ ex ] :   ex := ux;  fi
	endfor

	ex
enddef;
=================
Def  swap( suffix u, v ) =
	if      numer  u:  xxxn  := u;   u := v;   v := xxxn ;
	elseif  pair   u:  xxxpr := u;   u := v;   v := xxxpr;
	fi
enddef;
=================
Vardef   ordered( expr u, v, w ) =
	.    ordered_by( u, v, w )( <= )
	or   ordered_by( u, v, w )( >= )
enddef;
=================
Vardef   ordered_by( expr u, v, w )( text < ) =
	( u < v )  and  ( v < w )
enddef;
=======================================================================
% ================================================= |  order: cyclic  |
=======================================================================
% `Cyclical order' is used analogue to `<' here, not to `<=' :
% a row is considered to be cyclically ordered,
% iff  either  it has no adjacent pairs not ordered
%      or    ( it has exactly one such pair
%              and the last row element is less than the first ).
% I.e., running through the elements, we don't take a full round.
% (We need ascending ordering only.)
=======================================================================
Vardef   cyc_ordered( text t ) =
	( 0, 0 )    % t may be empty ...  that's cyclically ordered too

	for val = t :
		+ ( 0
			if  val
		exitif true;
	endfor

	for val = t :
			.       > val :   + 1  fi
			if  val
	endfor

	for val = t :
			.       >= val :   ,  0 )
			else           :   , -1 )
			fi
		exitif true;
	endfor

	. < ( 1, 0 )
enddef;
=======================================================================
% ====================================================== |  geometry  |
=======================================================================
=======================================================================
% ================================================ |  geometry: axes  |
=======================================================================
% Axes are thought as directed (w --> e, s --> n):
%
% x_axis, y_axis :  axis code
% z_axis         :  axis code ( z_axis ~ y_axis, but for depth, not height )
% axis_list      :  existing axes
=======================================================================
Numer  x_axis  =  0;
Numer  y_axis  =  1;
Numer  z_axis  = -1;

Def  axis_list = z_axis, x_axis, y_axis   enddef;
=======================================================================
% ======================================== |  geometry: trigonometry  |
=======================================================================
% teqla_s: equilateral triangle: height -> side length
% teqla_h: equilateral triangle: side length -> height
% teqre_s: isosceles rectangle triangle:
%                                diag. side length -> other side length
=======================================================================
Def   teqla_s  primary h     =  ( 2 sqrt 3 * h / 3 ) enddef;
Def   teqla_h  primary s     =  (   sqrt 3 * s / 2 ) enddef;
=================
Def   teqre_s  primary diag  =  ( diag / sqrt 2 )    enddef;
=======================================================================
% ================================================ |  geometry: line  |
=======================================================================
% We represent a line by a length 1 to 3 path with infinity bounds.
% For line/jet( point, point ) both points are points on the path;
% for line/jet( point, angle ) the point is point on the path.
=================
% line   : 2 points, or point and angle --> line
% jet    : 2 points, or point and angle --> jet
% linojet: (ditto) --> jet, if first argument is point, else line
%
% A path or path-figure p can be given as only argument,
% it represents the point pair beg p, fin p.
%
% All other functions are non-public implementing functions.
=======================================================================
Def   line     =  linojet_fu( 2 )  enddef;
Def       jet  =  linojet_fu( 1 )  enddef;
Def   linojet  =  linojet_fu( 0 )  enddef;
=================
Vardef   linojet_fu( expr n )( text t ) = % one or two arguments in t
	linojet_fu_two( n )
	. if  llength( t ) = 2 :  ( t )  else:  ( beg( t ), fin( t ) )  fi
enddef;
=================
Def   linojet_fu_two( expr n )( expr u, v ) =
	if        nangle u :  linojet_fu_pa      ( v, u )( n <> 1 )
	else: if  nangle v :  linojet_fu_pa
	.     else         :  linojet_fu_pp  fi  ( u, v )( n =  2 )
	fi
enddef;
=================
Def   linojet_fu_pp( expr P, Q ) primary both = % point, point --> line/jet
	if  ( xpart P = xpart Q )
	or  ( ypart P = ypart Q ):
		linojet_fu_hori_o_vert( P, unitvector( P -+ Q ) ) both
		.                       % will cry for P = Q
	else:
		if  both: jet_meeting_infinity( P, Q -+ P )(unitvector) --  fi
		.                               P  --  Q
		.      -- jet_meeting_infinity( Q, P -+ Q )(unitvector)
	fi
enddef;
=================
Def   linojet_fu_pa( expr P, a ) primary both = % point, angle --> line/jet
	if  a mod 90 = 0 :
		linojet_fu_hori_o_vert( P, Dir a ) both
	else:
		if  both: jet_meeting_infinity( P, -Dir a )() --   fi
		.                               P
		.      -- jet_meeting_infinity( P, +Dir a )()
	fi
enddef;
=================
Def   linojet_fu_hori_o_vert( expr P, v ) primary both =
	xxxpr := if xpart v = 0: ( xpart P, 0 ) else: ( 0, ypart P ) fi;

	if  both: ( -v * infinity + xxxpr )
	else    : P                      fi  --  ( v * infinity + xxxpr )
enddef;
=================
% v         : v <> (0,0) assumed
% unitvector: if abs v <= 1: empty; else: `unitvector'
=========
Vardef   jet_meeting_infinity( expr P, v )( text unitvector ) =
	Numer  x  = signature xpart v   infinity;
	Numer  y  = signature ypart v   infinity;

	Numer lor = signature(  abs( ypart unitvector v * ( xpart P -+ x ) )
	.                     - abs( xpart unitvector v * ( ypart P -+ y ) ) );

	if  lor <> 0:
		expandafter save if  lor < 0: y  else: x fi; % numer implicitly
		interim  warningcheck := 0;
		P + whatever * v  = (x, y);
	fi

	(x, y)
enddef;
=======================================================================
% ========================================== |  geometry: projection  |
=======================================================================
% projection:  src  projection( angle )  trg
%   computes the straight-line image (under given angle) of src on trg
%   src:  point, path, or (path-)figure
%   trg:  path or (path-)figure
=======================================================================
tertiarydef    src  projection  alf =
	projection_implementation( src, alf )
enddef;
=================
Vardef   projection_implementation( expr src, alf ) tertiary trg =
	for k = 0  upto  Length src :
		if k > 0 :  -- fi
		( jet( ( Point k of src ), alf ) Intersectionpoint_right  trg )
	endfor
enddef;
=======================================================================
% ======================================== |  geometry: intersection  |
=======================================================================
% intersection_points:
%   Collects (in a restricted sense) `all' intersection points
%   of two paths/pairs/figures and appends them to given array q.
%   Tries in case of common non-point-parts to take their bound points only.
=======================================================================
Vardef   intersection_points( expr fa, fb )( suffix q ) =
	PathArray  ppa;     collect_paths( fa )( ppa )( identity, false );
	PathArray  ppb;     collect_paths( fb )( ppb )( identity, false );

	for  ax = 0  upto  ppa .hix :
	for  bx = 0  upto  ppb .hix :
		intersection_paths( ppa[ ax ], ppb[ bx ] )( q );
	endfor
	endfor
enddef;
=================
Vardef   intersection_paths( expr pa, pu )( suffix q ) =
	Numer tal := 0;
	forever:
		NUMER ta, tu;
		( ta, tu ) = subpath( tal, Length pa ) of pa  intersectiontimes  pu;
		exitif  ta = first non_it;

		Numer tarr = min( max( ceiling( tal + ta ), tal + 1 ), Length pa );
		Numer tall = max( 0, tarr - 1 );

		Numer turr = min( max( ceiling(       tu ),       1 ), Length pu );
		Numer tull = max( 0, turr - 1 );

		intersection_paths_tt( subpath( tall, tarr ) of pa
		.                    , subpath( tull, turr ) of pu
		.                    , tal + ta - tall, tu - tull )( q );

		if turr < Length pu:        % order changed for efficiency only:
			intersection_paths( subpath( turr, Length pu ) of pu
			.                 , subpath( tall, tarr      ) of pa )( q );
		fi

		tal := tarr;
		exitif tal >= Length pa;
	endfor
enddef;
=================
% Intersection of two paths with length <= 1;
% one intersection -with times (ta, tu)- is known already.
%
% Simple conditions are assumed here,
% especially that there are at most two intersection points.
=========
Vardef   intersection_paths_tt( expr pa, pu, ta, tu )( suffix q ) =

	Pairp  qi = point   ta of pa;
	Pairp  qj = reverse pa  Intersectionpoint_left  reverse pu;

	add_element( q ) qi;
	if  length( qj - qi ) >= 1/10 :
	.         % 7*<0.01, 12*<0.1, else:0 - i.e. never:
		add_element( q ) qj;
	fi
enddef;
=======================================================================
% ============================================= |  geometry: tangent  |
=======================================================================
% tangent_sector: computes sector, a path/pair/figure is seen at from
%      a pongle (i.e. a point or an angle).
%      The sector will be given by
%      a pair of points on sector tangents (if the pongle is an angle)
%      or by a pair of angles (if the pongle is a point).
% tangent_sector_path       : the same for a path
% tangent_sector_path_simple: the same for a path of length 1
% tangent_sector_path_straight: as tangent_sector_path_simple,
%       but the path will be handled as if it would be a straight line
=======================================================================
Vardef   tangent_sector( expr f, pongle )( suffix tap ) =
	save sector_type;    % 2 points or 2 angles represent a sector
	def  sector_type( expr pongl ) =
		if  nangle pongl :  expandafter pairp
		else             :  expandafter nangle
		fi
	enddef;

	save sector;    sector_type( pongle )  sector [][];
	.               numer                  sector .hix;

	PathArray  pp;    collect_paths( f )( pp )( identity, false );
	sector .hix := pp .hix;
	for  j = 0  upto  pp .hix:
		tangent_sector_path( pp[ j ], pongle )( sector[ j ] );
	endfor

		% ( a not_addable b ) and ( a not_addable c )
		% --> ( a not_addable (b+c) )
	Numer  j := -1;
	forever:
		exitif  incr j > sector .hix - 1;
		Numer  k := j;
		forever:
			exitif  incr k > sector .hix;
			if  add_sectors ( sector[ j ], sector[ k ] )( pongle ):
				swap_sectors( sector[ k ], sector[ sector .hix ] );
				sector .hix := sector .hix - 1;
				k := j;
			fi
		endfor
	endfor

	NUMER min_j;
	for  j = 0  upto  sector .hix - 1 :
		min_j := j;
		for  k = j + 1  upto  sector .hix :
			if  sector[ k ][ 0 ] < sector[ min_j ][ 0 ] ) :
				min_j := k;
			fi
		endfor

		swap_sectors( sector[ j ], sector[ min_j ] );
	endfor

	NUMER  pre_max;
	sector[ sector.hix + 1 ][ 0 ] := sector[ 0 ][ 0 ];  % hack

	if  nangle pongle:
		pre_max  =  sector .hix;
	else:
		pre_max :=  -1;
		Numer  distance_max :=  -1;
		for  j = 0  upto  sector .hix :
			xxxn := ( sector[ j ][ 1 ]  -+  sector[ j + 1 ][ 0 ] )
			.       mod 360;

			if  distance_max < xxxn:
				pre_max      := j;
				distance_max := xxxn;
			fi
		endfor
	fi

	if pre_max >= 0:
		tap 0 := sector[ pre_max + 1 ][ 0 ];
		tap 1 := sector[ pre_max     ][ 1 ];
	fi
enddef;
=================
Vardef  tangent_sector_path( expr p, pongle )( suffix tap ) =
	tangent_sector_path_straight( p, pongle )( tap );

	save  taq;    sector_type( pongle )  taq[];
	PATH    q;
	for  j = 0  upto  Length p - 1:
		q := subpath( j, j + 1 ) of p;
		tangent_sector_path_simple( q, pongle )( taq );
		pit_true := add_sectors( tap, taq )( pongle );
	endfor
enddef;
=================
Vardef  tangent_sector_path_simple( expr p, pongle )( suffix tap ) =
	tangent_sector_path_straight( p, pongle )( tap );

	if  nangle pongle :
		for d = + Dir pongle, - Dir pongle:
			Numer t = directiontime d of p;
			if  t <> -1 :
				Path  q = subpath( 0, t ) of p;
				save  taq;     sector_type( pongle )  taq[];
				tangent_sector_path_straight( q, pongle )( taq );
				pit_true := add_sectors( tap, taq )( pongle );
			fi
		endfor

	else :         % branch is unused and not really tested
		save  tap_old;     sector_type( pongle )  tap_old[];
		forever:
			tap_old 0 := tap 0;
			tap_old 1 := tap 1;

			for d = + Dir tap 0, - Dir tap 0,
			.     , + Dir tap 1, - Dir tap 1 :
				Numer t = directiontime d of p;
				if  t <> -1 :
					Path  q = subpath( 0, t ) of p;
					save  taq;    sector_type( pongle )  taq[];
					tangent_sector_path_straight( q, pongle )( taq );
					pit_true := add_sectors( tap, taq )( pongle );
				fi
			endfor

			exitif abs( tap 0 - tap_old 0 )
			.    + abs( tap 1 - tap_old 1 ) < 0.1; % good value ?
		endfor
	fi
enddef;
=================
Vardef  tangent_sector_path_straight( expr p, pongle )( suffix tap ) =
	sector_type( pongle )  ma;    ma = meter( beg p )( pongle );
	sector_type( pongle )  mo;    mo = meter( fin p )( pongle );

	if ( nangle pongle  and  ( ma <= mo ) )
	or ( pairp  pongle
	.    cand (  ( p meets jet( pongle, 0.5[ beg p, fin p ] ) )
	.          = ( ( ma -+ mo ) mod 360 <= 180                ) )
	.  ):
		tap 0 := ma;
		tap 1 := mo;
	else:
		tap 0 := mo;
		tap 1 := ma;
	fi
enddef;
=======================================================================
% ============================================== |  geometry: sector  |
=======================================================================
% There are two kinds of sector:
%
% 1) angle sectors = regions, bounded by two jets with common origin
%
%    With origin point given, a sector is determined by
%    the pair of angles of its bounding jets,
%    meaning the sector from the first jet to the second (clockwise).
%
% 2) stripe sectors = regions, bounded by two parallel straight lines
%
%    If the sloping angle is fixed, a sector is determined by 2 points
%    on one of the longest infinite diagonal lines (or on the y-axis).
%
% Both kinds of sector will be discriminated by the type of a `pongle':
% - that is either the point from 1) or the angle from 2).
% The pair of angles from 1) or of the points from 2) will be used
% as data, representing a sector (with fixed pongle).
=======================================================================
% meter: meters a point in relation to a pongle.
%      If pongle is an angle, the point is metered by its projection on
%         if  pongle mod 180 < 90 :  NW to SE infinite diagonal line,
%         if  pongle mod 180 > 90 :  SW to NE infinite diagonal line,
%         if  pongle mod 180 = 90 :  y-axis.
%      If pongle is a pair, the point is metered by the angle,
%         it is seen at from the pongle point.
% add_sectors : add 2nd sector onto 1st, i.e.
%      if the union of two sectors is a sector,
%         return this union sector in the 1st argument
%         and result into `true',
%      else: don't change any argument
%         and result into `false'.
% swap_sectors: swaps data, representing two sectors.
=======================================================================
Vardef   meter( expr u )( expr pongle ) =
	if  nangle  pongle:
		Pairp R = u  +  whatever * Dir pongle
		.       = whatever * ( signature( pongle mod 180  -  90 ), 1 );
		R
	else:
		Angle( pongle  -+  u )
	fi
enddef;
=================
Vardef   add_sectors( suffix u, v )( expr pongle ) =
	Boolean added := true;

	if      cyc_ordered( u 0, v 0, v 1, u 1 ): % u 0 := u 0;
	.                                          % u 1 := u 1;

	elseif  cyc_ordered( v 0, u 0, u 1, v 1 ):   u 0 := v 0;
	.                                            u 1 := v 1;

	elseif  cyc_ordered( u 0, v 1, v 0, u 1 ):           % v 1 <> v 0

		if nangle pongle:
			u 1 := infinity *
				if   pongle mod 180 = 90 :  ( 0, 1 )
				else :  ( 1, signature( pongle mod 180  -  90 ) )
				fi;
			u 0 := - u 1;
		else:
			u 0 :=   0;
			u 1 := 360 - epsilon;
		fi

	elseif  cyc_ordered( u 0, v 0, u 1, v 1 ): % u 0 := u 0;
	.                                            u 1 := v 1;

	elseif  cyc_ordered( v 0, u 0, v 1, u 1 ):   u 0 := v 0;
	.                                          % u 1 := u 1;

	else:
		added := false;
	fi

	added
enddef;
=================
Def   swap_sectors( suffix u, v ) =
	swap( u 0, v 0 );
	swap( u 1, v 1 );
enddef;
=======================================================================
% ====================================================== |  variable  |
=======================================================================
=======================================================================
% ========================================= |  variable: temporaries  |
=======================================================================
NUMER   xxxn , xxxn_a, xxxn_b;
FIGURE  xxxf ;
PAIR    xxxpr;
STRING  xxxs , xxxs_a;
PATHL   xxxl ;
=================
NUMER   pit;     % for values not used, but produced (for side effects)
BOOLEAN pit_true;
=======================================================================
% ============================================ |  variable: unknowns  |
=======================================================================
Def   unk       =  begingroup  save ?;   numer ?;  ?  endgroup  enddef;
Def   unk_pr    =  begingroup  save ?;   pair  ?;  ?  endgroup  enddef;
PATH  unk_path;
=======================================================================
% ===================================================== |  container  |
=======================================================================
=======================================================================
% ============================================== |  container: array  |
=======================================================================
% new : helps to add a new element to a (may be not initialized) array
%       Example:   new sig = 123;  -->  sig[ incr sig .hix ] = 123;
%       (early needed - so the function has been shifted up in the file)
% copy_array: copy array (with standard hix-coding)
=======================================================================
Def  copy_array( suffix source, target )  =
	for k = 0 upto source .hix:
		target[ k ] = source[ k ];
	endfor
	target .hix := source .hix;
enddef;
=======================================================================
% ============================================== |  container: stack  |
=======================================================================
% Stacks are implemented by arrays, bounded by 0 and .hix.
=======================================================================
% push      : ...
% pop       : ...
=======================================================================
%Def   push( suffix stack ) expr e =
%	stack[ incr stack .hix ] := e;
%enddef;
=================
%Def   pop( suffix stack ) =
%	stack[ decr stack .hix + 1 ]
%enddef;
=======================================================================
% ================================================= |  container: set |
=======================================================================
% Sets will be represented by ordered arrays, bounded by 0 and .hix.
=======================================================================
% add_element( q ) e : add e onto q
=======================================================================
Vardef   add_element( suffix q ) expr e =
	Numer  qx := 0;
	forever:
		exitif   q .hix  < qx ;
		exitif   q[ qx ] >= e ;
		qx := qx + 1;
	endfor

	if  ( q .hix  < qx )
	cor ( q[ qx ] > e  ) :
		for  qqx  =  incr q.hix  downto  qx + 1:
			q[ qqx ] := q[ qqx - 1 ];
		endfor
		q[ qx ] := e;
	fi
enddef;
=======================================================================
% =============================================== |  container: list  |
=======================================================================
% A list (of expressions or suffixes) will occur mainly as text argument.
% Such lists should be used very cautiously,
% because text arguments are not evaluated/expanded - only inserted ...
% They will be used here to get more freedom of argument structure.
=======================================================================
% lhead      : get head element
% empty      : is it the empty list?
% llength    : get list length (for a list of expressions)
% s_llength  : get list length (for a list of suffixes)
% is_element : is expression c element of list l ?
% first_occurrence: index of most left occurrence of an element in a list,
%                   starting with 1; 0 means `no occurrence'
% is_range_element:  is expr. c element of a range (given by a pair)?
% is_may_be_range_element: as is_element, but list l may contain ranges
% apply      : list --> list, given function applied elementwise
% filtered   : list --> list, filtered by given condition (named result)
% first_only : list --> list, high values removed
% last_only  : list --> list,  low values removed
=======================================================================
		% ((check for def/vardef or parentheses on new use))
Def   lhead( text l ) =
	for  b = l :   b  exitif true;  endfor
enddef;
=================
Vardef   empty( text l ) =
	true  for  b = l :  and false  endfor
enddef;
=================
Vardef   llength( text l ) =
	0  for  b = l :   + 1  endfor
enddef;
=================
Vardef   s_llength( text l ) =
	0  forsuffixes  b = l :   + 1  endfor
enddef;
=================
Vardef   is_element( expr c )( text l ) =
	false  for  b = l :  or ( b = c )  endfor
enddef;
=================
%Vardef   first_occurrence( expr c )( text l ) =
%	(   0
%		for  b = l, c :
%			+ 1
%			exitif  b = c;
%		endfor
%	) mod ( llength( l ) + 1 )
%enddef;
=================
Vardef   is_range_element( expr c )( expr t ) =
	if  pair t:
		( first t <= c ) and ( c <= second t )
	else:
		( t = c )
	fi
enddef;
=================
Vardef   is_may_be_range_element( expr c )( text l ) =
	false  for  b = l :  or ( is_range_element( c )( b ) )  endfor
enddef;
=================
%Def  apply( text f )( text l ) =
%	for el = l: , f( el )  endfor
%enddef;
=================
Def  filtered( suffix nom )( text list )( text condition ) =
	def  nom =  enddef;
	for el = list:
		if condition( el ):
			expandafter def
			expandafter     nom
			expandafter         = nom, el  enddef;
		fi
	endfor
enddef;
=================
Def  first_only( suffix nom )( text list )( expr bound ) =
	def  nom =  enddef;
	for el = list:
		if    numeric el  cand ( el       < bound ):
			expandafter def
			expandafter     nom
			expandafter         = nom
				, el                                       enddef;
		elseif   pair el  cand ( first el < bound ):
			expandafter def
			expandafter     nom
			expandafter         = nom
				, min( el, ( first el, bound - epsilon ) ) enddef;
		fi
	endfor
enddef;
=================
Def  last_only( suffix nom )( text list )( expr bound ) =
	def  nom =  enddef;
	for el = list:
		if    numeric el  cand (        el >= bound ):
			expandafter def
			expandafter     nom
			expandafter         = nom
				, el                              enddef;
		elseif   pair el  cand ( second el >= bound ):
			expandafter def
			expandafter     nom
			expandafter         = nom
				, max( el, ( bound, second el ) ) enddef;
		fi
	endfor
enddef;
=======================================================================
% ======================= |  macros: list arguments: special helpers  |
=======================================================================
% assign_array_from_homogeneous_list:
%             Given a nonempty list of homogeneously typed expressions,
%             the given suffix lx will be made an array of this type
%             and filled with the expression values.
%             lx.hix will be set accordingly.
%             If the list is empty, only lx.hix will be set.
%             (The function will be used to handle
%              the angle or point list of the striping operator ''.)
% get_list_arguments_two:
%             handles special form argument lists, as used for '':
%                fixed number of expressions( here: two )
%                followed by an expression list (or by  nothing)
%     The initial expressions will be assigned to two suffix arguments,
%     the list will be handled by assign_array_from_homogeneous_list.
=======================================================================
			%  t should be an expression list without side effects
Def   assign_array_from_homogeneous_list( suffix lx )( text t ) =
	numer  lx .hix;     lx .hix := -1;

	for  t_first = t :
		assign_type( lx[] )( t_first );
		exitif true;
	endfor

	for  tx = t :
		lx[ incr lx .hix ] = tx;
	endfor
enddef;
=================
Def   get_list_arguments_two( suffix u, v )( suffix target )( text t ) =
	save  fhelp;
	def   fhelp  ( expr  a, b )
	.            ( text  tttt )       % tttt is parenthesized list
	.            text  ignore_me
	=
		assign_type( u )( a );     u = a;
		assign_type( v )( b );     v = b;
		assign_array_from_homogeneous_list( target ) tttt;
	enddef;

	fhelp( t )( () );
enddef;
=======================================================================
% ====================================== |  macros: suffix arguments  |
=======================================================================
% (only numeric suffix heads will be considered):
% ------
% suffix_head       : get first part of variable macro name with suffix
% suffix_tail_string: get everything after the first index (as string)
=======================================================================
save     suffix_head;
vardef   suffix_head []  @# =
	@
enddef;
=================
save     suffix_tail_string;
vardef   suffix_tail_string []  @# =
	str @#
enddef;
=======================================================================
% ======================================================= |  compass  |
=======================================================================
% We use compass point notation to denote sign parts, so:
=======================================================================
Def   compass_point  =
	n, e, s, w, ne, se, sw, nw, nnw, nne, ene, ese, sse, ssw, wsw, wnw, o
enddef;
=======================================================================
% ================================================ |  axes functions  |
=======================================================================
% axis_apart ax :  xpart/ypart,  according to axis ax
% axis_bpart ax :  xpart/ypart, orthogonal to axis ax
% para  ax :  unitvector,   parallel  to axis ax, w-->e / s-->n
% orth  ax :  unitvector,  orthogonal to axis ax, w-->e / s-->n
=======================================================================
Def axis_apart primary ax = if ax = x_axis: xpart else: ypart fi enddef;
Def axis_bpart primary ax = if ax = x_axis: ypart else: xpart fi enddef;
=================
Def  para primary ax = if ax = x_axis: right else: up    fi enddef;
Def  orth primary ax = if ax = x_axis: up    else: right fi enddef;
=======================================================================
% To work with `cardinal points', i.e. `cardinal sides':
=================
% w_side, ...: cardinal points code (but denoting the side, not a point)
% axis  s:  axis, the side s belongs to
% axes_of:  list of sides --> list of axes
% tete  s:  is it the backside (-> 0) or the front (-> 1) on its axis?
% apart s:  `xpart'/`ypart' according to the axis, side s belongs to
% bpart s:  `xpart'/`ypart' according to the axis, side s not belongs to
% aunit s:  unitvector on axis, side s belongs to
% bunit s:  unitvector on axis, side s not belongs to
%  >>:  s:  `>'/`<' if s is the side, the axis goes to, or comes from
%  <<:  s:  `>'/`<' if s is the side, the axis comes from, or goes to
% tunit s: (1,0)/(0,1) if s is backside/front (tail/tete) on the axis
=======================================================================
Numer  w_side  =  2 x_axis + 0;   % 0
Numer  e_side  =  2 x_axis + 1;   % 1
Numer  s_side  =  2 y_axis + 0;   % 2
Numer  n_side  =  2 y_axis + 1;   % 3
=================
Def   axis   primary side    =  floor( side/2 )  enddef;
=================
Def   axes_of( text sides ) =
	for ax = x_axis, y_axis :
		for side = sides :
			if      axis\side = ax: , ax   fi
			exitif  axis\side = ax;
		endfor
	endfor
enddef;
=================
Def   tete   primary side  =  (  side mod 2 )   enddef;
=================
Def   apart  primary side  =  axis_apart axis\side   enddef;
Def   bpart  primary side  =  axis_bpart axis\side   enddef;
=================
Def   aunit  primary side  =  para  axis\side   enddef;
Def   bunit  primary side  =  orth  axis\side   enddef;
=================
Def    >>:   primary side  =  if  tete\side = 1: >  else: <  fi  enddef;
%Def   <<:   primary side  =  if  tete\side = 1: <  else: >  fi  enddef;
=================
Def   tunit  primary side  = ( 1 - tete\side, tete\side )  enddef;
=======================================================================
% x_w      : suffix to denote `xpart of west-bound' (of path/figure)
% x_e, ... : ...
% compass  : get this suffix from axis-code and part-code
=======================================================================
Def   compass_addendum_x =  x_w, x_e  enddef;
Def   compass_addendum_y =  y_s, y_n  enddef;
=================
Def   compass( expr axis )( expr partxy ) =
	if      ( axis = x_axis )  and  ( partxy = 0 ) :   x_w
	elseif  ( axis = x_axis )  and  ( partxy = 1 ) :   x_e
	elseif  ( axis = y_axis )  and  ( partxy = 0 ) :   y_s
	elseif  ( axis = y_axis )  and  ( partxy = 1 ) :   y_n
	else :  0/0
	fi
enddef;
=======================================================================
% ========================================================== |  sign  |
=======================================================================
% sign information: representing (glyph-)figure, bounds (, properties)
% It is stored in an array, indexed by sign list number and sign number.
=======================================================================
.      % sign_mem[ sigl ][ sign-number ]
save     sign_mem;
figure   sign_mem[][] ;
pair     sign_mem[][] _glyph_bounds[] ; % ...[ compass-point-pair-index ]
%numer   sign_mem[][] _properties;
=================
Def   glyph  primary sign_id  =                  % replaced later on
	sign_mem[ first sign_id ][ second sign_id ]
enddef;
=================
Def   glyph_bounds  primary sign_id  =
	sign_mem[ first sign_id ][ second sign_id ] _glyph_bounds
enddef;
=======================================================================
% ============================================== |  sign: attributes  |
=======================================================================
Numer  Z_SYM  = 1  ;   % central symmetrical to Point OQ
Numer  X_SYM  = 2  ;   %         symmetrical to y_axis
Numer  X_EQB  = 3  ;   %   bound-symmetrical to y_axis (i.e. iw = -ie)
Numer  X_any  = unk;
=================
Numer  Y_NORM = 1  ;   % sign with normal height
Numer  Y_ROOF = 2  ;   % sign with roof
Numer  Y_HIGH = 3  ;   % sign with full height
Numer  Y_any  = unk;
=======================================================================
% ======================================================== |  figure  |
=======================================================================
% A figure is a collection of paths (with transformations associated).
% It is organized as a binary tree with paths on the leafs.
% Non-leaf nodes represent a sum of two figures, may be transformed.
=================
% A figure so can be
%   the `zero figure': collects none paths at all,
%                      it's named `zero' and numbered by 0;
%   a `path figure': represents a path - given by path and transformation;
%   a `plus figure': sum of two figures, subjected to a transformation.
=================
% The numbering of figures is a little bit complicated, because to save
% memory there is some figure information stored in the number itself.
% Figures are numbered as
%    [-] aa + bb/256 + cc/(256*256) (aa, bb, cc: non-negative integers)
%
% Figures, newly created from a path or by figure/path addition,
% are numbered by non-negative integers. They are named `base figures'.
% Their number is
%    0               - if it is the zero figure,
%    1,    2,    ... - if it is a path figure,
%    4094, 4093, ... - if it is a plus figure.
%
% Figures, resulting from the transformation of another figure,
% inherit their base figure number as aa.
% Two of them, which differ by a shift only, get the same bb
% (bb is 0, iff the figure is a shifted base figure)
% - they will be differentiated by cc.
% cc is 0, iff (xpart, ypart) of the transformation is (0, 0).
%
% A reversed figure (i.e. a figure with all its paths reversed)
% is numbered by -f, if f is the number of the unreversed figure.
=================
% Information on the path/the summands are stored only for base figures.
%
% Derived information on bounds and extreme points is stored once only
% for figures differing by shift only (and sharing the base figure).
%
% A reversed figure borrows all information from their counterpart.
=======================================================================
save       fig_mem;         % figure representations
=================
numer      fig_mem .path_hix;    fig_mem .path_hix :=     0;
numer      fig_mem .plus_lox;    fig_mem .plus_lox :=  4095;
=================
% numer    fig_mem[] _op ;  % kind of node         %% will be computed now
figure     fig_mem[] _lft;  % left  operand on non-leaf node (else unknown)
figure     fig_mem[] _rgt;  % right operand on non-leaf node (else unknown)
path       fig_mem[] _pth;  % path on leaf node (else unknown)
=================
%transform fig_mem[]  _tra; % associated transformation (without shift part)
pair       fig_mem[]  _trx; % ( xxpart, xypart ) of transformation `_tra'
pair       fig_mem[]  _try; % ( yxpart, yypart ) of transformation `_tra'
pair       fig_mem[][]_shf; % shift part of associated transformation
=================
	% To implement `splitted' we need to know the fix summand of a sum;
	% we hold one focus value only, that of the last computed base figure:
numer      fig_mem ._foc     ;    % focus value held
numer      fig_mem ._foc_zero;    % for invalid focus access only
.          fig_mem ._foc_zero = 0;
numer      fig_mem ._foc_f   ;    % fig., stored foc value is taken from
=================
	% transformation dependent derived information
	% (stored for time efficiency only):
	% ((There is now doubt on the usefulness of caching this information.
	%  Maybe, it has faded away. But then it could become useful again.))
numer      fig_mem[][]  ; %[ figure ][ side -> bounds ]
numer      fig_mem[][][]; %[ figure ][ side ][ one/two extreme points ]
=================
	% at places we want to handle a path as a figure
	% for that, we simulate here a part of the figure information store:
Def  prepare_one_path_memory =
	save  one_path_mem;       % workplace to handle one path
	numer one_path_mem  []  ; %(( path ))[ side -> bounds ]
	numer one_path_mem  [][]; %(( path ))[ side ][ 1 or 2 extreme points ]
enddef;
=======================================================================
% op code: not stored in fig_mem[]_op now, but computed (to save memory)
%         (Possible extensions -deleted everywhere else- are indicated.)
=======================================================================
  Numer  op_zero             = 0;
% Numer  op_outer            = 1;
  Numer  op_path             = 2;
% Numer  op_outer_path       = op_outer + op_path;
% Numer  op_inner            = 4;
% Numer  op_outer_inner      = op_outer           + op_inner;
% Numer  op_path_inner       =            op_path + op_inner;
% Numer  op_outer_path_inner = op_outer + op_path + op_inner;
  Numer  op_plus             = 8;
=================
Def   op_string  primary fig_op  =
	if      fig_op = op_plus :  "op_plus"
	elseif  fig_op = op_path :  "op_path"
	else                     :  "op_zero"
	fi
enddef;
=================
Vardef    op  primary f  =    % fig_mem[ ixa f ] ._op
	if                f  =  0                :  op_zero
	elseif  floor abs f <= fig_mem .path_hix :  op_path
	else                                     :  op_plus
	fi
enddef;
=======================================================================
% lef, rgt, pth, trf : main information on the figure
% fig_left, fig_right: transformed left/right parts of a plus figure
=======================================================================
Def   lef  primary f  =  fig_mem[ ixa f ] ._lft   enddef;
Def   rgt  primary f  =  fig_mem[ ixa f ] ._rgt   enddef;
Def   pth  primary f  =  fig_mem[ ixa f ] ._pth   enddef;
=================
	% trf is defined for a path too, giving identity, see below at ixc
Vardef   trf  primary f  =
	if   ixb f = 0 :  identity
	else           :  build_trf( shf f, trx f, try f )
	fi
enddef;
=================
Vardef   fig_left   primary f  =  lef f  Transformed  trf f  enddef;
Vardef   fig_right  primary f  =  rgt f  Transformed  trf f  enddef;
=======================================================================
% Additional figure information:
% rev: is it a reversed figure?
% foc: has the focus of the figure building plus operation been
%      on the left (--> -1) / right (--> +1) / none (--> 0) operand?
%      (An operand gets the focus, if it should not be moved.)
%      ((This value is only needed shortly after the figure has been
%       constructed, so it's enough to store it for one figure only.))
=======================================================================
Def   rev  primary f  =  ( f < 0 )   enddef;
=================
Def   foc  primary f  =
	if ixa f = foc_f :  fig_mem ._foc
	else             :  fig_mem ._foc_zero   error( foc_forgotten )
	fi
enddef;
=================
Def   foc_f           =  fig_mem ._foc_f     enddef;
=======================================================================
% access functions
% ffm    : access on transformation (but not shift) dependent information
% bounds : access on bounds information
% extrema: access on extreme values for given side (as they are stored)
% extreme: get the lower or higher extreme value, or their middle
=======================================================================
Def   ffm    ( expr f )        =  fig_mem[ ixa f + ixb f / 256 ]  enddef;
Def   bounds ( expr f, side )  =
	if  figure f:  ffm( f )    [ side ]
	else        :  one_path_mem[ side ]   % not figure means path
	fi
enddef;
=================
Def   extrema( expr f, side ) primary col =            % col = 0 or 1
	bounds( f, side )[ col ]
enddef;
=================
Vardef  extreme( expr f )( expr side ) primary low_hig = % low_hig = 0/0.5/1
	if      low_hig = 0                   :      extrema( f )( side )\0
	elseif  unknown extrema( f )( side )\1:      extrema( f )( side )\0
	elseif  low_hig = 1                   :      extrema( f )( side )\1
	else                                  : 1/2[ extrema( f )( side )\0,
	.                                            extrema( f )( side )\1 ]
	fi
enddef;
=======================================================================
% helper functions (non-public)
=======================================================================
Def   trx  primary f  =  ffm( f ) ._trx  enddef;
Def   try  primary f  =  ffm( f ) ._try  enddef;
=================
Def   shf  primary f  =        % gives (0,0) for path, see below at ixc
	if   ixc f = 0 :  ( 0, 0 )
	else           :  ffm( f )[ ixc f ] _shf
	fi
enddef;
=======================================================================
% ixa: number of base figure                               , name above `aa'
% ixb: 2nd part of figure number -transformation dependent-, name above `bb'
% ixc: 3rd part of figure number -shift          dependent-, name above `cc'
=================
% by chance: abs=length, so ixb f = ixc f = 0 for path f (not for a pair!)
% we use it in get_bounds: trf f is defined for a path, result: identity
=======================================================================
Vardef  ixa  primary f = floor abs f                              enddef;
Vardef  ixb  primary f = floor       256 ( abs f mod 1 )          enddef;
Vardef  ixc  primary f =       256 ( 256 ( abs f mod 1 ) mod 1 )  enddef;
=======================================================================
% ============================================== |  figure: creation  |
=======================================================================
% create_figure( opr, l, r, c, focus, p ): creates a figure
%
%   opr:  op_zero / op_path / op_plus - kind of figure node
%   l  :  if opr = op_plus: known  left operand figure;  else: unk fi
%   r  :  if opr = op_plus: known right operand figure;  else: unk fi
% (c and focus are irrelevant if opr <> op_plus):
%   c  :  string, describing, how the operands should be transformed
%   focus: -1 / 0 / +1 = right / both / left operands should be shifted
%   p  :  if opr = op_path: known path to be represented by the figure
%         else: unknown     fi
=======================================================================
Vardef   create_figure( expr opr, l, r, c, focus, p ) =
	NUMER  f;

	if      opr = op_path :
		f = incr  fig_mem .path_hix;
		pth f = p;

	elseif  opr = op_plus :
		f = decr  fig_mem .plus_lox;

		lef f = l;
		rgt f = r;

		Transform  tl = identity  if  focus <> -1:  shifted unk_pr  fi;
		Transform  tr = identity  if  focus <> +1:  shifted unk_pr  fi;

		get_transformations( f, c )( tl, tr );

		lef f := lef f  Transformed  tl;
		rgt f := rgt f  Transformed  tr;

		foc_f := f;
		foc f := focus;

	else : % opr = op_zero
		f = 0;
	fi

%	op  f = opr;

	f
enddef;
=======================================================================
% ========================== |  figure: creation: path-, zero-figure  |
=======================================================================
Figure    zero      = create_figure( op_zero, unk, unk, "", 0, unk_path);
=================
Def  ++++ primary p = create_figure( op_path, unk, unk, "", 0, p )  enddef;
=======================================================================
% ==================================== |  figure: creation: addition  |
=======================================================================
% +++ : adds two figures (or paths)
% ++(z)+- : adds two figures, right figure  may shift
% +-(z)++ : adds two figures,  left figure  may shift
% ++(z)++ : adds two figures,  both figures may shift
% +-(z)+- : as ++(z)++ (both are unused now)
%   `z' is a shift describing string for all four operations
%    a shift may result not from the addition, but from a following split
=======================================================================
secondarydef l +++ r  =
	create_figure( op_plus
	.            , if  not figure l :  ++++  fi   l
	.            , if  not figure r :  ++++  fi   r
	.            , ""
	.            , 0
	.            , unk_path )
enddef;
=================
secondarydef  p +- q =
	if  not string p :  figure_add_string_right( p, q )( 0 )
	else             :  figure_add_string_left ( p, q )( 0 )
	fi
enddef;
=================
secondarydef  p ++ q =
	if  not string p :
		if  not string q :  p  plusplus  q
		else : figure_add_string_right( p, q )( -1 )
		fi
	else     : figure_add_string_left ( p, q )( +1 )
	fi
enddef;
=================
FIGURE  stacked_figure;    % simplified stacks, enough for actual use
NUMER   stacked_focus ;
=================
Def   figure_add_string_right( expr p, strng )( expr focus ) =
begingroup
	stacked_figure :=  if  not figure p :  ++++  fi   p;
	stacked_focus  :=  focus;
	strng
endgroup
enddef;
=================
Def   figure_add_string_left( expr strng, q )( expr focus ) =
	create_figure( op_plus
	.            , stacked_figure
	.            , if  not figure  q :  ++++  fi   q
	.            , strng
	.            , stacked_focus + focus
	.            , unk_path )
enddef;
=======================================================================
% ===================== |  figure: creation: compute transformations  |
=======================================================================
% get_transformations: local to create_figure,
%    computes for a new halfway-created plus-figure f
%    transformations tl and tr for applying them to the summands.
%    String c gives the equations, which should hold after transformation.
% All other functions are local to get_transformations.
% (There is a lot of code commented out here - it had worked already
%  and eventually it will be called into life again.)
=======================================================================
Def   get_transformations( expr f, c )( suffix tl, tr ) =
					% condition for efficiency only:
	if  c <> "" : interpret_seq( f,  c )( tl, tr );  fi
	interpret_empty_statement  ( f, "" )( tl, tr );
enddef;
=================
Def   interpret_seq( expr f, u )( suffix tl, tr ) = % statement sequence
begingroup
	String  v := u;
	NUMER  ix;
	forever:
		ix := find( v, ";" );
		exitif ix < 0;
		interpret_statement( f, substring( 0, ix ) of v )( tl, tr );
		v := substring( ix+1, infinity ) of v;
	endfor
	interpret_statement( f, v )( tl, tr );
endgroup
enddef;
=================
Def   interpret_statement( expr f, u )( suffix tl, tr ) =
begingroup
	Numer  ix = find( u, "=" );
	if     ix < 0 :
		interpret_other_statement( f, u )    % not equation, not assign

%	elseif  substring( ix-1, ix    ) of u = ":" :
%		interpret_right_to_left_assignment
%		.                 ( f, substring( 0   , ix-1     ) of u
%		.                    , substring( ix+1, infinity ) of u )

%	elseif  substring(  ix+1, ix+2 ) of u = ":" :
%		interpret_left_to_right_assignment
%		.                 ( f, substring( 0   , ix       ) of u
%		.                    , substring( ix+2, infinity ) of u )

	else :
		interpret_equation( f, substring( 0   , ix       ) of u
		.                    , substring( ix+1, infinity ) of u )
	fi
	. ( tl, tr )
endgroup
enddef;
=================
Def   interpret_equation( expr f, v, w )( suffix tl, tr ) =
	.  interpret_expression_on_left_side ( f, v )( tl, tr )
	=  interpret_expression_on_right_side( f, w )( tl, tr );
enddef;
=================
%Def interpret_right_to_left_assignment( expr f, v, w )( suffix tl, tr ) =
%	.  interpret_assignment_variable_side( f, v )( tl, tr )
%	=  interpret_expression_on_right_side( f, w )( tl, tr );
%enddef;
=================
%Def interpret_left_to_right_assignment( expr f, v, w )( suffix tl, tr ) =
%	.  interpret_assignment_variable_side( f, w )( tl, tr )
%	=  interpret_expression_on_left_side ( f, v )( tl, tr );
%enddef;
=================
Vardef   interpret_expression_on_left_side( expr f, u )( suffix tl, tr ) =
	interpret_expression_one_side( f, u )( lef )( tl )
enddef;
=================
Vardef   interpret_expression_on_right_side( expr f, u )( suffix tl, tr ) =
	interpret_expression_one_side( f, u )( rgt )( tr )
enddef;
=================
Vardef   interpret_expression_one_side( expr f, u )( text l_r )( suffix tt ) =
	forsuffixes  r = compass_point, alpha, omega : % i eliminated
		save  r;   vardef  r = ( l_r( f ) .?.r ) transformed tt enddef;
	endfor
	forsuffixes  r = compass_addendum_x :
		save  r;   vardef  r = ( l_r( f ) .?.r )  +  xpart tt  enddef;
	endfor
	forsuffixes  r = compass_addendum_y :
		save  r;   vardef  r = ( l_r( f ) .?.r )  +  ypart tt  enddef;
	endfor

	scantokens  u
enddef;
=================
%Vardef  interpret_assignment_variable_side( expr f, u )( suffix tl, tr ) =
%		% eliminated: assign value to o / i / compass_point_name
%enddef;
=================
Def   interpret_other_statement( expr f, u )( suffix tl, tr ) =
begingroup
%	if     u = "^"    :  interpret_equation( f, "y_n", "y_s" )
%	elseif u = "v"    :  interpret_equation( f, "y_s", "y_n" )
%
%	elseif u = ">>"   :  interpret_equation( f, "x_e", "x_w" )
%	elseif u = "<<"   :  interpret_equation( f, "x_w", "x_e" )
%
%	elseif u = ">>>"  :  interpret_equation( f, "x_e"
%	.                                         , "x_w-distance_x_low" )
%	elseif u = "<<<"  :  interpret_equation( f, "x_w"
%	.                                         , "x_e+distance_x_low" )
%
%	elseif u = ">>>>" :  interpret_equation( f, "x_e"
%	.                                         , "x_w-stroke_distance_x" )
%
%	elseif u = "<<<<" :  interpret_equation( f, "x_w"
%	.                                         , "x_e+stroke_distance_x" )
%
%	elseif u = "vvvv" :
%		if  known tl cand (tl=identity): tl := tl shifted( 0, unk ); fi
%		if  known tr cand (tr=identity): tr := tr shifted( 0, unk ); fi
%		interpret_seq( f, "y_n=yn_normal;ys_normal=y_s" )
%
%	elseif u = "^^^^" :
%		if  known tl cand (tl=identity): tl := tl shifted( 0, unk ); fi
%		if  known tr cand (tr=identity): tr := tr shifted( 0, unk ); fi
%		interpret_seq( f, "y_s=ys_normal;yn_normal=y_n" )
%
%	elseif u = "~^^^^":
%		if  known tl cand (tl=identity): tl := tl shifted( 0, unk ); fi
%		if  known tr cand (tr=identity): tr := tr shifted( 0, unk ); fi
%		interpret_seq( f, "y_s=ys_normal;yn_normal=y_n;x_w=x_w" )
%
%	elseif u = "^^^^~":
%		if  known tl cand (tl=identity): tl := tl shifted( 0, unk ); fi
%		if  known tr cand (tr=identity): tr := tr shifted( 0, unk ); fi
%		interpret_seq( f, "y_s=ys_normal;yn_normal=y_n;x_e=x_e" )
%
%	elseif u = "&&"   :
%		interpret_equation( f, "omega", "alpha" )
%
%	elseif substring(            0,        1 ) of u = " " :
%		interpret_other_statement( f, substring(1, infinity  ) of u )
%
%	elseif substring( length u - 1, length u ) of u = " " :
%		interpret_other_statement( f, substring(0, length u-1) of u )
%
%	else :
		if u <> "":  error( statement_string_unintended )  fi
%		interpret_empty_statement( f, "" )
%	fi
%	. ( tl, tr )
endgroup
enddef;
=================
		% no shift order means: don't shift
Def   interpret_empty_statement( expr f, u )( suffix tl, tr ) =
	if  unknown xpart tl  and  unknown xpart tr:  xpart tl = - xpart tr;  fi
	if  unknown ypart tl  and  unknown ypart tr:  ypart tl = - ypart tr;  fi

	if  unknown  xpart tl :    xpart tl = 0;   fi
	if  unknown  ypart tl :    ypart tl = 0;   fi

	if  unknown  xpart tr :    xpart tr = 0;   fi
	if  unknown  ypart tr :    ypart tr = 0;   fi
enddef;
=======================================================================
% The following tokens are unused now, but that could change again,
% so it's better to avoid conflicting use.

if check_names > 0 :
%	String  o   =   "o=o"  ; % standard use of `o' will be preferred now

	String  n   =   "n=n"  ;
	String  e   =   "e=e"  ;
	String  s   =   "s=s"  ;
	String  w   =   "w=w"  ;

	String  nw  =  "nw=nw" ;
	String  ne  =  "ne=ne" ;
	String  sw  =  "sw=sw" ;
	String  se  =  "se=se" ;

	String  nnw = "nnw=nnw";
	String  nne = "nne=nne";
	String  ssw = "ssw=ssw";
	String  sse = "sse=sse";

	String  wsw = "wsw=wsw";
	String  wnw = "wnw=wnw";
	String  ese = "ese=ese";
	String  ene = "ene=ene";

	String  ^   = "^" ;    % ? "y_n=y_s"
	String  v   = "v" ;    % ? "y_s=y_n"

	String  >>>  = ">>>" ; % ? "x_e=x_w-distance_x_low"
	String  <<<  = "<<<" ; % ? "x_w=x_e+distance_x_low"

	String  >>>> = ">>>>"; % ? "x_e=x_w-stroke_distance_x"
	String  <<<< = "<<<<"; % ? "x_w=x_e+stroke_distance_x"

	String   ^^^^  = "^^^^"  ;
	String  ~^^^^  = "~^^^^" ;
	String   ^^^^~ = "^^^^~" ;
	String   vvvv  = "vvvv"  ;

	save  >>;    string  >>;    >> = ">>" ;
	save  <<;    string  <<;    << = "<<" ;

	save  &&;    string  &&;    && = "&&" ;
fi
=======================================================================
% ======================================== |  figure: creation: copy  |
=======================================================================
% copy: creates a transformed copy of a figure (if necessary)
=======================================================================
Vardef copy( expr f, t ) =
	if     op f  =   op_zero :  f
	elseif   t   =  identity :  f
	else :
		Transform  xxxt  =  trf f  transformed  t;

		PAIR  tr_x, tr_y, tr_shi;
		tr_x   =  ( xxpart xxxt, xypart xxxt );
		tr_y   =  ( yxpart xxxt, yypart xxxt );
		tr_shi =  (  xpart xxxt,  ypart xxxt );

		Figure  ff  =  get_ix( f, tr_x, tr_y, tr_shi );

		trx ff  =  tr_x  ;
		try ff  =  tr_y  ;
		shf ff  =  tr_shi;

		ff
	fi
enddef;
=================
Vardef   get_ix( expr f, tr_x, tr_y, tr_shi ) =             % non-public
	xxxn_a := get_tra_ix( f, tr_x, tr_y );
	xxxn_b := get_shf_ix( f, xxxn_a, tr_shi );

%	if  xxxn_a > 255 :  error( transformations_per_figure )  fi
%                                            %% experience: xxxn_a <= 19
%	if  xxxn_b > 255 :  error( shifts_per_transf_figure   )  fi
%                                            %% experience: xxxn_b <= 30

	signature f * ( ixa  f  + 1/256 xxxn_a  + (1/256/256) * xxxn_b )
enddef;
=================
Vardef   get_tra_ix( expr f, tr_x, tr_y ) =                 % non-public
	Numer  k := 0;

	if  ( tr_x <> (0,0) )  or  ( tr_y <> (0,0) ):
		forever :
			exitif  unknown   fig_mem[ ixa f + (incr k )/256 ] _trx
%			.   or  unknown   fig_mem[ ixa f +       k  /256 ] _try
			;
			exitif ( tr_x  =  fig_mem[ ixa f +       k  /256 ] _trx )
			.  and ( tr_y  =  fig_mem[ ixa f +       k  /256 ] _try )
			;
		endfor;
	fi

	k
enddef;
=================
Vardef   get_shf_ix( expr f, bb, tr_shi ) =                 % non-public
	Numer  k := 0;

	if  tr_shi <> ( 0, 0 ) :
		forever :
			exitif  unknown   fig_mem[ ixa f + bb/256 ][ incr k ] _shf;
			exitif  tr_shi  = fig_mem[ ixa f + bb/256 ][      k ] _shf;
		endfor;
	fi

	k
enddef;
=======================================================================
% ================================= |  figure: ? (i.e. bound access)  |
=======================================================================
% ? :  gets wanted bound information for figure / path / pairp
%
% We can control, what is wanted, by giving as suffix one of:
%     o                : middle point wanted
%     n ,  e ,  s ,  w : point at n   wanted (etc.)
%    nnw, nne, ssw, sse: point at nnw wanted (etc.)
%    ese, ene, wsw, wnw: ditto
%    sw , se , nw , ne : ditto
%    y_n, x_e, y_s, x_w: y-value of most north point wanted (etc.)
%    we , sn           : pair wanted from what x_w and x_e would give
%    alpha, omega      : start/final point wanted of (path-)figure/path/p.
%
% Here means:
%    point at n   - the only point most at north,
%                   or the middle between the extreme points at north
%    point at nnw - the most west point of the points at north
%    point at ne  - intersectionpoint of north and east bound line,
%                   it's not necessarily a point on the figure
%    middle point - point with xpart halfwide between the xpart
%                   of points most west and most east. (ypart analogous)
=======================================================================
save  ?;     def  ?  =  implement_bound_access  str  enddef;
=================
primarydef  f  implement_bound_access  z  =                % non-public
	if   pair f :   get_bounds( f -- f, z )
	else        :   get_bounds(      f, z )
	fi
enddef;
=================
Def   get_bounds( expr f, z ) =                            % non-public
begingroup
	if       z = "alpha" :   beg ppath( f )   % path must be known
	elseif   z = "omega" :   fin ppath( f )
	elseif   z = "o"     :                    % (rarely used)
		( 1/2[ f.?.x_w, f.?.x_e ], 1/2[ f.?.y_s, f.?.y_n ] )

	else:
		if  path f:  prepare_one_path_memory;  fi

		% which bound sides do we need to compute?
		String  sides  =  ""
		for j =
			if    substring (1,2) of z = "_" :   2
			elseif            length z = 2   :   0, 1
			else                             :   0
			fi
		:
			&  ","  &  substring(j,j+1) of z  &  "_side"
		endfor;

		% which extreme points on the bound line do we need, if any?
		Numer  col =
			if     ( z = "nnw" )  or  ( z = "ssw" ) :  0 % low end
			elseif ( z = "nne" )  or  ( z = "sse" ) :  1 % high end
			elseif ( z = "wsw" )  or  ( z = "ese" ) :  0
			elseif ( z = "wnw" )  or  ( z = "ene" ) :  1
			elseif ( length z = 1 ):  0.5                % both
			else                   :  unk                % none
			fi;

		expandafter bound_info
		expandafter           (
		expandafter             f
		expandafter               )
		expandafter                ( scantokens sides )( known col );

		% compute the result:
		for  side = scantokens sides :
			+ ( bounds( f )( side )     +  apart\side trf f )
			.   if     ( substring(1,2) of z = "_"):  \
			.   elseif ( z = "we" ) or ( z = "sn" ):  *  tunit\side
			.   else                               :  *  aunit\side
			.   fi

			if  known col :
			+ ( extreme( f )( side ) col +  bpart\side trf f )
			.                                         *  bunit\side
			fi
		endfor
	fi
endgroup
enddef;
=======================================================================
% Five functions `bound_info...' (local to get_bounds) compute bounds.
% The information computed will be stored in fig_mem (/one_path_mem),
% it can be accessed after return to get_bounds.
%
% The parameters are for all these functions:
% f    :  figure or path
% sides:  list of sides, we want to get bound info for
% fine :  do we need the extreme values on the bound sides too?
=======================================================================
Def   bound_info( expr f )( text sides )( expr fine ) =
begingroup
	save  condition;
	if not fine:
		def  cond( expr side ) = unknown  bounds( f )( side )   enddef;
	else:
		def  cond( expr side ) = unknown extrema( f )( side )\0 enddef;
	fi

	save  hard_list;     filtered( hard_list )( sides )( cond );

	if not empty( hard_list ):
		expandafter bound_info_hard
		expandafter                (
		expandafter                 f
		expandafter                  )
		expandafter                   ( hard_list )( fine );
	fi
endgroup
enddef;
=======================================================================
Def   bound_info_hard( expr f )( text sides )( expr fine ) =
	if      path   f       :  bound_info_for_path_figure
	elseif  op f = op_plus :  bound_info_for_plus_figure
	elseif  op f = op_path :  bound_info_for_path_figure
	else                   :  bound_info_for_zero_figure
	fi
	.   ( f )( sides )( fine );
enddef;
=======================================================================
Def   bound_info_for_zero_figure( expr f )( text sides )( expr fine ) =
	for  side = sides :
		bounds ( f )( side ) = - signature tete\side;
		extrema( f )( side )\0 = 0;
	endfor
enddef;
=======================================================================
Def   bound_info_for_plus_figure( expr f )( text sides )( expr fine ) =
begingroup
	% (( 2001/03/19: 523 times called.
	%    The following 1046 calls of Transformed split into:
	%    842 where trf f is a shift
	%    105 where a new figure will be produced
	%     99 where it finds an existing figure
	%  ))
	Figure l = lef f  Transformed( trf f  shifted -ship trf f );
	Figure r = rgt f  Transformed( trf f  shifted -ship trf f );

	bound_info( l )( sides )( fine );
	bound_info( r )( sides )( fine );

	save  aa;    def  aa( expr lr, side ) = +  apart\side  trf lr  enddef;
	save  bb;    def  bb( expr lr, side ) = +  bpart\side  trf lr  enddef;

	for side = sides :
		if      ( bounds( l )( side )  aa( l, side ) )   =
		.       ( bounds( r )( side )  aa( r, side ) ) :

				xxxn := bounds( l )( side )  aa( l, side );
			if fine :
				xxxn_a := min(
					extreme( l )( side )\0  bb( l, side ),
					extreme( r )( side )\0  bb( r, side ) );
				xxxn_b := max(
					extreme( l )( side )\1  bb( l, side ),
					extreme( r )( side )\1  bb( r, side ) );
			fi

		else:
			if  ( bounds( l )( side )  aa( l, side ) )  >>:side
			.   ( bounds( r )( side )  aa( r, side ) )
			:
				Numer q = l;
			else:
				Numer q = r;
			fi

				xxxn   := bounds( q )( side )    aa( q, side );
			if fine :
				xxxn_a := extreme( q )( side )\0  bb( q, side );
				xxxn_b := extreme( q )( side )\1  bb( q, side );
			fi
		fi

		if  unknown bounds( f )( side ): bounds( f )( side ) = xxxn; fi
		if fine :
		.                          extrema( f )( side )\0 = xxxn_a;
		.   if  xxxn_a <> xxxn_b:  extrema( f )( side )\1 = xxxn_b;  fi
		fi
	endfor
endgroup
enddef;
=======================================================================
.                                       % f can be path figure or path:
Def   bound_info_for_path_figure( expr f )( text sides )( expr fine ) =
Begingroup
	Path  p = ppath( f )  shifted -ship trf f; % if path f: trf f=identity

	hope( known p )( error( unknown_path ) );

	save  qq;     numer  qq[], qq[][];
	for  side = sides :
		qq[ side ]   := apart\side ( fin p );
		qq[ side ]\0 := bpart\side ( fin p );
		qq[ side ]\1 := bpart\side ( fin p );
	endfor

	NUMER  tt;
	for ax = axes_of( sides ):
		save sids;    % sids := sides on ax (i.e. with axis\side = ax )
		filtered( sids )( sides )( ax = axis\. );

		for  k = 0  upto  Length p - 1 :
			% 0 or 1 extreme point assumed between 2 path points:
			for od = orth( ax ), -orth( ax ):
				tt := directiontime od of subpath(k, k+1) of p;
				exitif tt >= 0;
			endfor

			for q =                   point k      of p
				if floor tt <> tt:  , point k + tt of p  fi
			:
				for  sid = sids:
					if      apart\sid q   =      qq[ sid ]:
						qq[ sid ]\0 := min( qq[ sid ]\0, bpart\sid q );
						qq[ sid ]\1 := max( qq[ sid ]\1, bpart\sid q );

					elseif  apart\sid q  >>:sid  qq[ sid ]:
						qq[ sid ]   :=  apart\sid q;
						qq[ sid ]\0 :=  bpart\sid q;
						qq[ sid ]\1 :=  bpart\sid q;
					fi
				endfor % sid
			endfor % points on subpath
		endfor % subpath of p
	endfor % axis

	for  side = sides :
		if  unknown bounds( f )( side ):
			bounds( f )( side ) = qq[ side ];
		fi

		if fine :         % prefer memory efficiency on time efficiency
			.   extrema( f )( side )\0 = qq[ side ]\0;
			if  qq[ side ]\0 <> qq[ side ]\1:
				extrema( f )( side )\1 = qq[ side ]\1;
			fi
		fi
	endfor
Endgroup )
enddef;
=======================================================================
% ====================================== |  figure: diameter, radius  |
=======================================================================
% rrx, rry: diameter in x- vers. y-direction (i.e. bound line distance)
% rx , ry : radius   in x- vers. y-direction (i.e. 1/2 diameter)
=======================================================================
Vardef rrx primary f = xxxpr := f.?.we; (second xxxpr - first xxxpr) enddef;
Vardef rry primary f = xxxpr := f.?.sn; (second xxxpr - first xxxpr) enddef;
=================
Vardef  rx primary f =  0.5 rrx f  enddef;
Vardef  ry primary f =  0.5 rry f  enddef;
=======================================================================
% =========================================== |  figure: ` = reverse  |
=======================================================================
Def   `  =  reversed  true  enddef;
=================
primarydef  x  reversed  e  =
	if  e :
		if      boolean  x :      not  x
		elseif  path     x :  reverse  x
		elseif  pair     x :           x
		elseif  figure   x :          -x
		else               :           x   error( argument_type_first )
		fi
	else                  :            x
	fi
enddef;
=======================================================================
% ========================================================= |  glyph  |
=======================================================================
% To access the bounds (= minimal/maximal x-/y-values) of a glyph
% we need a lot of short names.
% Mostly we want to implicitly access the sign actual handled,
% but access to a sign with given number is necessary too.
% Example:
%    `iwe': `i'  - defines the sign list (IMa), the sign belongs to
%           `we' - we want the pair (minimal, maximal) of x-values
%    iwe\123 : values for glyph of sign 123 of list IMa wanted
%    iwe (without following suffix):
%              values for glyph of the actual sign of list IMa wanted
%              (we get the actual sign of list sigl from sid\sigl)
=================
% bound_access: solves the with/without suffix problem
% define_list_dependent_names: defines short names for a given sign list
=======================================================================
Def  bound_access( expr sigl, compass_pair ) suffix nom  =
	if not empty( nom ):                       % if nom is not empty,
		get_glyph_bounds( sigl, nom )          % ... take it
	else:
		glyph_bounds( sigl, second sid\sigl )  % else take actual sign
	fi  [ compass_pair ]
enddef;
=================
Def  get_glyph_bounds  primary sign_id =
	if  unknown glyph( sign_id ):
		hide( compute_glyph_with_context( sign_id ); )
	fi

	glyph_bounds( sign_id )
enddef;
=================
save  define_list_dependent_names;
Def   define_list_dependent_names( expr sigl )
	( suffix
		. iwe, isn       % `iwe' supplies `awe', ..., `iwe', ..., `zwe'
		, iw , ie , is , in
		, idx, idy
		, iw_base , ie_base , is_base , in_base
		, idx_base, idy_base
		, iWN, iON, iEN, iEO, iES, iOS, iWS, iWO
	)
=
	save
		. iwe, isn
		, iw , ie , is , in
		, idx, idy
		, iw_base , ie_base , is_base , in_base
		, idx_base, idy_base
		, iWN, iON, iEN, iEO, iES, iOS, iWS, iWO
	;

	def  iwe  suffix nom  =  bound_access( sigl, x_axis ) nom  enddef;
	def  isn  suffix nom  =  bound_access( sigl, y_axis ) nom  enddef;

	vardef  iw  @#  =   first iwe @#  enddef;
	vardef  ie  @#  =  second iwe @#  enddef;
	vardef  is  @#  =   first isn @#  enddef;
	vardef  in  @#  =  second isn @#  enddef;

	vardef  idx @#  = iw @#  -+  ie @#  enddef;
	vardef  idy @#  = is @#  -+  in @#  enddef;
	=================
	def   iw_base  =  first  iwe_base  enddef;
	def   ie_base  =  second iwe_base  enddef;
	def   is_base  =  first  isn_base  enddef;
	def   in_base  =  second isn_base  enddef;

	def  idx_base  =  ( iw_base  -+  ie_base )  enddef;
	def  idy_base  =  ( is_base  -+  in_base )  enddef;
	=================
	def  iWN  =  ( iw, in )  enddef;
	def  iON  =  (  0, in )  enddef;
	def  iEN  =  ( ie, in )  enddef;
	def  iEO  =  ( ie,  0 )  enddef;
	def  iES  =  ( ie, is )  enddef;
	def  iOS  =  (  0, is )  enddef;
	def  iWS  =  ( iw, is )  enddef;
	def  iWO  =  ( iw,  0 )  enddef;
enddef;
=================
save  names_handled;     boolean names_handled[];

for  sigl              =   ASL
.                        , sign_lists_implemented_stage_d
.   if  check_names = 1: , sign_lists_possible             fi
:
	if  unknown names_handled[ sigl ] :
		true  = names_handled[ sigl ];

		xxxs := sign_list_string_lc  sigl;

		define_list_dependent_names( sigl )
			(
				. scantokens(  xxxs  &  "we"      )  % iwe
				, scantokens(  xxxs  &  "sn"      )  % isn
				, scantokens(  xxxs  &  "w"       )  % iw
				, scantokens(  xxxs  &  "e"       )  % ie
				, scantokens(  xxxs  &  "s"       )  % is
				, scantokens(  xxxs  &  "n"       )  % in
				, scantokens(  xxxs  &  "dx"      )  % idx
				, scantokens(  xxxs  &  "dy"      )  % idy
				, scantokens(  xxxs  &  "w_base"  )  % iw_base
				, scantokens(  xxxs  &  "e_base"  )  % ie_base
				, scantokens(  xxxs  &  "s_base"  )  % is_base
				, scantokens(  xxxs  &  "n_base"  )  % in_base
				, scantokens(  xxxs  &  "dx_base" )  % idx_base
				, scantokens(  xxxs  &  "dy_base" )  % idy_base
				, scantokens(  xxxs  &  "WN"      )  % iWN
				, scantokens(  xxxs  &  "ON"      )  % iON
				, scantokens(  xxxs  &  "EN"      )  % iEN
				, scantokens(  xxxs  &  "EO"      )  % iEO
				, scantokens(  xxxs  &  "ES"      )  % iES
				, scantokens(  xxxs  &  "OS"      )  % iOS
				, scantokens(  xxxs  &  "WS"      )  % iWS
				, scantokens(  xxxs  &  "WO"      )  % iWO
			)
		;
	fi
endfor

save  define_list_dependent_names, names_handled;   % free memory
=======================================================================
% The short names defined above are related to a fixed sign list.
% We define some related to variable sign lists too
% (there is no need for implicit access here):
=======================================================================
Def   q_we primary sign_id = glyph_bounds( sign_id ) [ x_axis ] enddef;
Def   q_sn primary sign_id = glyph_bounds( sign_id ) [ y_axis ] enddef;
=================
Def   q_w  =   first q_we  enddef;
Def   q_e  =  second q_we  enddef;
Def   q_s  =   first q_sn  enddef;
Def   q_n  =  second q_sn  enddef;
=================
Vardef  q_dx  primary sign_id  =  q_w sign_id  -+  q_e sign_id  enddef;
Vardef  q_dy  primary sign_id  =  q_s sign_id  -+  q_n sign_id  enddef;
=======================================================================
% ========================================================= |  split  |
=======================================================================
% Operation `splitted' will be used to implement signs,
% containing one figure l inserted into another figure r,
% moving the parts of r to the left resp. right.
% So it will be used in the context
%    l   +++   r splitted,
% where r itself is a plus-figure.
%
% The splitted parts will be moved to the west/east figure bounds,
% unless the call will be done in the form `splitted_by <pair>'.
=======================================================================
PAIR   actual_split_distance;                      % needs to be global

Numer  split_distance_default  =  distance_x_mid;

Def   splitted  =  splitted_by  !! whatever   enddef;
=================
tertiarydef  sum  splitted_by  split_distance  =
begingroup
	actual_split_distance  :=  split_distance;
	(
		if  unknown split_distance:
			fig_left ( rgt sum )  xsh( ~.?.x_w  -+  iw )
			.                  +++
			.          lef sum
			.                  +++
			fig_right( rgt sum )  xsh( ~.?.x_e  -+  ie )
		else:
			fig_left ( rgt sum )
			.                  +-("x_e -first actual_split_distance=x_w")++
			.          lef sum
			.                  ++("x_e+second actual_split_distance=x_w")+-
			fig_right( rgt sum )
		fi
	) Transformed  trf sum
endgroup
enddef;
=======================================================================
% ===================================================== |  connected  |
=======================================================================
% A lot of signs are composed from two or more parts with `obvious'
% own significance, connected by a straight or sloping line.
% This connection-line seems to be a ligature forming line only,
% without own significance.
% Because these lines are very similar, they can be notated by an operator.
%
% The operator `connected' can only occur in the context
%      sum  connected( parameter_list )
% , where `sum' results in a figure with operator op_plus.
% It results in a sum of three operands: both operands of sum,
% shifted horizontally to give room for the new third summand,
% the connecting `bridge' - line.
%
% The following parameter combinations have been implemented:
%
% 1) point_left,             point_right             : straight line
% 2) point_left, angle_left, unk_pr     , unk        : straight line
% 3) unk_pr    , unk       , point_right, angle_right: straight line
% 4) point_left, angle_left, point_right, angle_right: sloping line
%
% A point can be given by itself, by its y-value only,
% or by its compass point name in a string - for ex. by "s".
%
% The angle is the outgoing angle on the left, but the ingoing at right.
%
% The bridge width normally is either
%     bridge_width_default_narrow (case 2) and 3) above)
% or  bridge_width_default_wide   (case 1) and 4) above),
% but it will be made greater, if this standard width would result
% in figures with distance less than distance_x_low.
%
% The implementation has to make sure (because it's assumed later on),
% that for the result holds:
%           rgt result  = right operand of the initial sum
%       lef lef result  =  left operand of the initial sum
=======================================================================
Numer  bridge_width_default_narrow = $ 1.2;
Numer  bridge_width_default_wide   = $ 2  ;
=================
		% postfix operator -> infix operator;  operator -> function
Def  connected = connection_op  dummy                             enddef;
primarydef  f  connection_op  dummy  =  connection_fu( f, foc f ) enddef;
=================
Def   connection_fu( expr f, focus )( text t ) =
	if      llength( t ) = 4 :  connection_fu_four( f, focus )( t )
	elseif  llength( t ) = 2 :  connection_fu_two ( f, focus )( t )
	else                     :  error( arguments_types )
	fi
enddef;
=================
Def   connection_fu_two ( expr f, focus )( expr u, v ) =
	connection_fu_four( f, focus )( u, unk, v, unk )
enddef;
=================
Vardef   connection_fu_four( expr f, focus )( expr ql, al, qr, ar ) =

	save ff;   figure ff[];   ff\1 = fig_left f;   ff\0 = fig_right f;
	save aa;   nangle aa[];   aa\1 = al;           aa\0 = ar;

	save rr;   def    rr  primary x  =  if x = 1: ql else: qr fi  enddef;
	save ZZ;   pairp  ZZ[];
	for  x = 1, 0 :
		ZZ[ x ] =
			if      pair   rr x :         rr x
			elseif  numer  rr x :  ( unk, rr x )
			elseif  string rr x :  ff[ x ].?.scantokens( rr x )
			else             :  ( unk, 0 ) error( arguments_types )
			fi;

		if   known  ypart ZZ[ x ]  and  unknown  xpart ZZ[ x ] :
			ZZ[ x ] := ff[ x ]   where_y_at( x )  ypart ZZ[ x ];
		fi  % `=' would result in little inconsistencies
	endfor;
%%
	Numer  bridge_width     =
		if ( unknown qr and unknown aa\0 )
		or ( unknown ql and unknown aa\1 ): bridge_width_default_narrow
		else                              : bridge_width_default_wide
		fi;

	save  futZZ;     pairp  futZZ[];  % assumption: there is a solution
	for x = 1, 0:
		futZZ[ x ] :=
			if known ZZ[ x ] :
				ZZ[ x ]
			else :
				ff[ x ]  where_y_at( x ) ( ypart ZZ[ 1-x ]
				.                          if x=1:  -  else:  +  fi
				.                          bridge_width * cotd aa[ 1-x ] )
			fi;
	endfor

	Numer  figure_distance = ff\1.?.x_e  -+  ff\0.?.x_w;
	Numer  shift_distance  = max( bridge_width - xpart( futZZ\1 -+ futZZ\0 )
	.                           , distance_x_low - figure_distance );
%%
	save  fac;   def  fac primary x = ( -x + ( 1 - focus )/2 )      enddef;
	save  dis;   def  dis primary x = ( fac x * shift_distance, 0 ) enddef;

	save  shftd_ff;     figure  shftd_ff[];
	save  shftd_ZZ;     pairp   shftd_ZZ[];
	for x = 1, 0:
		shftd_ff[ x ]     = ff[ x ] Transformed( identity shifted dis x );
		if  known ZZ[ x ]:
		.   shftd_ZZ[ x ] = ZZ[ x ]                       shifted dis x;
		fi
	endfor

	for x = 1, 0:
		if  unknown shftd_ZZ[ x ]:
			shftd_ZZ[ x ] =    shftd_ff[ x ]
			.           intersection_at( x )
			.             jet( shftd_ZZ[ 1-x ], aa[ 1-x ] + 180 x )
		fi
	endfor

	Path  bridge  =  shftd_ZZ\1
	.                if known aa\1:  { Dir aa\1 }  fi
	.                ..
	.                if known aa\0:  { Dir aa\0 }  fi
	.                shftd_ZZ\0;

	shftd_ff\1    +++    bridge    +++    shftd_ff\0
enddef;
=======================================================================
% ================================================ |  '' (= striped)  |
=======================================================================
% There are many glyphs with areas, filled with `stripes'.
% In most cases, the stripes are `regularly' distributed -
% so they can be generated from a minimum of parameters.
%
% The striping `operator' '' should be read as a binary operator,
% but it's not really one in the sense of Metafont,
% because the right `operand' is a collection of parameters only.
%
% Left operand:
%      either a path or (numeric, i.e.) figure: figure to become striped
%      or     a pair ( meaning two figures )  : bounds of the stripes
%   (I couldn't found a good way to allow for a pair of paths here.)
%
% Right operand: two or three parameters in a parenthesis pair:
%   1st parameter: number of stripes
%
%   2nd parameter:
%       either a point  - centre of ray-forming stripes (`ray'-case)
%       or     a number - angle  of parallel stripes
%
%   3rd parameter - optional parenthesized list:
%       in ray-case: list of angles or points -
%       .               if 2 angles: angles of bounding stripes
%       .               or 2 points: jets through them bound the stripes
%       .               else       : angles of or points on all stripes
%       else       : list of points -
%       .               if 2 points: points on bounding stripes
%       .               else       : list of points on all stripes
%
%   If there is no third parameter, the only or first figure
%   of the left operand should be full covered by the stripes.
%
%   Exception: If the stripe number is 1
%   and none or two points/angles are given with the 3rd parameter,
%   we want one stripe only, going through the middle of the given area.
=======================================================================
Def   ''    =  stripe_op dummy   enddef;       % postfix  -> infix
.                                              % operator -> function:
primarydef  bb stripe_op dummy = stripe_fu( bb ) enddef;
=================
Numer  stripe_eps  =  0.10 ;   % ignore `stripes' with lower length
=================
Vardef   stripe_fu( expr bounds )( text t ) =
	save  stripe_number, stripe_pongle, pongles; % pongle: point or angle

	get_list_arguments_two( stripe_number, stripe_pongle )( pongles )( t );

	save  ba, bb;
	if      path   bounds:  path   ba;       ba =             bounds;
	elseif  figure bounds:  figure ba;       ba =             bounds;
	elseif  pair   bounds:  figure ba, bb;   ba =      first  bounds;
	.                                             bb = second bounds;
	fi

	if  pongles .hix = -1 :
		if  pairp stripe_pongle: expandafter nangle
		else                   : expandafter pairp
		fi                                          pongles[];

		tangent_sector( ba, stripe_pongle )( pongles );
		pongles .hix := 1;   % exactly 2 tangents have been computed
	fi

	PathArray  stripe_paths;
	for  k = 0 upto pongles .hix: % linojet: num. 1st arg: line, else jet
		new stripe_paths = linojet( stripe_pongle, pongles[ k ] );
	endfor

	Pair  result_index_range = ( 0, stripe_number - 1 );

	if      stripe_number <= 0 :
		;
	elseif  stripe_paths .hix = stripe_number - 1 :
		;
	elseif  stripe_paths .hix = 1:
		Path pa = stripe_paths[ 0 ];
		Path po = stripe_paths[ 1 ];

		stripe_paths .hix :=  stripe_number - 1;
		if  stripe_number = 1:
			stripe_paths .hix  :=  2;
			result_index_range := ( 1, 1 );
		fi;

		stripe_paths[ stripe_paths .hix ] = po;

		for  j = 1  upto  stripe_paths .hix - 1 :
			xxxn := j / stripe_paths.hix;
			stripe_paths[ j ] :=
				if  nangle stripe_pongle :
				.        interpath ( xxxn, pa, po );
				else :
				.   jet( stripe_pongle
				.      , interangle( xxxn, Angle pa, Angle po ) );
				fi;
		endfor
	else :
		error( stripe_number_contra_list );
	fi

	FigureArray  fig;
	for  k = first result_index_range  upto  second result_index_range :
		new fig := implement_one_stripe( stripe_paths[ k ], ba, bb );

		if  abs( beg fig[ fig.hix ] -+ fin fig[ fig.hix ] ) < stripe_eps:
		.   fig.hix := fig.hix - 1;         % ignore very short stripes
		fi
	endfor

	if fig.hix < 0 :
		zero
	else :
		for  k = 0  upto  fig .hix :
			if k > 0: +++ fi    fig[ k ]
		endfor
	fi
enddef;
=================
Vardef  implement_one_stripe( expr li, fa, fb ) = % line & its bound figures
	PairpArray  poa;
	intersection_points( li, fa )( poa );    % seems to be better than
	.            % ... ( fa, li )... (Intersectionpoint_left will be used)

	if  poa .hix = -1 :  error( no_intersection_first )  fi

	if  known fb  cand  ( fa <> fb ):
		PairpArray  pob;
		intersection_points( li, fb )( pob ); % see above
		if  pob .hix = -1 :  error( no_intersection_second )  fi
	else :
		save  pob;     def  pob = poa  enddef;
	fi

	PAIR   jk;
	Numer  max_distance := -1;

	for  j = 0  upto  poa .hix :
	for  k = 0  upto  pob .hix :
		xxxn := length( pob[ k ] - poa[ j ] );
		if xxxn > max_distance :
			max_distance := xxxn;
			jk := ( j, k );
		fi
	endfor
	endfor

	++++ ( poa[ first jk ] -- pob[ second jk ] )
enddef;
=======================================================================
% ========================================================== |  roof  |
=======================================================================
% About twenty glyphs have a roof shaped part at top; three forms occur.
=======================================================================
Numer  r_acute    = 0;
Numer  r_sloping  = 1;
Numer  r_straight = 2;
=================
Numer  roof_height_default  =  dy_high - dy_shrinked;
=================
		% x-distance of roof from main part of the glyph:
numer  roof_distance;    numer  roof_distance[];
.      roof_distance[ r_straight ] =  1.25 stroke_distance_x;
.      roof_distance[ r_sloping  ] =  1.5  stroke_distance_x;
.      roof_distance[ r_acute    ] =       stroke_distance_x;
=================
% The sum `xxx +++ roof' will not be grouped,
% so we get the possibility to add roof-only transformations.
% (It's used for i131 only.)
=========
NUMER  roof_width;
=========
primarydef   f  roofed  how_and_maybe_width =
	hide(
		if pair how_and_maybe_width:
			how        := first  how_and_maybe_width;
			roof_width := second how_and_maybe_width;
		else:
			how        :=        how_and_maybe_width;

%			Numer  tmp_a := ypart( f.?.n )  -  $ 0.5;
%			Numer  tmp_b := ypart( f.?.n )  -  $ 1.0;

			roof_width := max(
				xpart(   f.?.nnw               -+   f.?.nne              )
				.   + 2   roof_distance[ how ]
%			,
%				xpart( (f first_where_y tmp_a) -+ (f last_where_y tmp_a) )
%				.   + 1.6 roof_distance[ how ]
%			,
%				xpart( (f first_where_y tmp_b) -+ (f last_where_y tmp_b) )
%				.   + 1.0 roof_distance[ how ]
			,
				2/3 rrx f
				.   + 1.0 roof_distance[ how ]
			,
				$ 2    if  how = r_sloping :  + 2 roof_height_default  fi
			);
		fi
		)
	f    +++    roof( how, roof_width )  xsh( OQ -+ f.?.n )
enddef;
=======================================================================
% ================================================== |  reduce width  |
=======================================================================
% If the x-width is strongly limited,
% we need to reduce the x-distance of parts of multi-part glyphs.
=================
% minimal_distance: minimal distance, we would like to get,
%                   for adjacent glyph parts, occurring anywhere
% reduce_simple   : reduce the width of a figure by scaling only,
%                   to a ratio of xscaled_limit by scaling the width only,
%                   after that by scaling width and height
% reduce_width: add listed figures,
%               resulting figure has x-extension (-dx_high/2, +dx_high/2).
%      (If the list has one element f only, rrx f > dx_high is assumed.)
=======================================================================
Vardef   minimal_distance  primary ff =          % ff: pair of figures
	if      unknown first ff                     :   0

	elseif  ff = ( L_parenthesis, ip\059        ):  -$ 0.4
	elseif  ff = ( ip\059       , R_parenthesis ):  -$ 0.4

	elseif  ff = ( L_parenthesis, ip\078        ):  -$ 0.6
	elseif  ff = ( ip\078       , R_parenthesis ):  -$ 0.5

	elseif  ff = ( ip\059  , ip\078   ):   -$ 0.2
	elseif  ff = ( ip\078  , ip\059   ):   +$ 0.2

	elseif  ff = ( ip\217.w, ip\217.e ):  0.8 distance_x_low
	elseif  ff = ( ip\218.w, ip\218.o ):  0.9 distance_x_low
	elseif  ff = ( ip\218.o, ip\218.e ):  0.9 distance_x_low

	elseif  ff = ( i___i   , ip\059   ):   +$ 0.2
	elseif  ff = ( ip\059  , ip\197\3 ):  0.8 distance_x_low
	elseif  ff = ( ip\197\3, i___i    ):      distance_x_low

	else                               :  0.9 distance_x_low
	.       hide( show "new_reduce: " & decimal fa & " " & decimal fb; )
	fi
enddef;
=================
Vardef  reduce_simple( expr fig )( expr width_a, width_o ) =
	if  width_o / width_a  >=  xscaled_limit :
		fig  Xscaled( width_o / width_a )
	else:
		fig  Xscaled    xscaled_limit
		.    Scaled ( 1/xscaled_limit * ( width_o / width_a ) )
	fi
enddef;
=================
Vardef  reduce_width( text list ) =
	FigureArray  figr;
	NumerArray   dist;
	Numer  minimal_width := 0;

	FIGURE  previous;
	for f = list :
		new figr = f;
		new dist = minimal_distance( previous, f );
		minimal_width := minimal_width  +  dist[ dist.hix ]  +  rrx f;
		previous := f;
	endfor;

	if  minimal_width >= dx_high :
		Figure  fig  =
			figr[ 0 ]  xsh( ~.?.x_w  -+  0 )
			for  j  =  1  upto  figr.hix :
			.   ++("x_e +(" & decimal(dist[j]) & ")=x_w")+-
			.   figr[ j ]
			endfor;

		reduce_simple( fig )( minimal_width, dx_high )
		.                    xsh( 0  -+  -dx_high/2 )

	else :
		Numer  gift = ( dx_high - minimal_width ) / dist.hix;

		Figure   left_fig  =
			figr[    0     ]  xsh( ~.?.x_w  -+  -dx_high/2 )
			for  j  =  1             upto  figr.hix / 2 :
			.   ++("x_e +(" & decimal(dist[ j ]+gift) & ")=x_w")+-
			.   figr[ j ]
			endfor;

		Figure  right_fig  =
			figr[ figr.hix ]  xsh( ~.?.x_e  -+  +dx_high/2 )
			for  j = dist.hix - 1  downto  ( figr.hix + 1 )/ 2 :
			.   ++("x_w=(" & decimal(dist[j+1]+gift) & ")+ x_e")+-
			.   figr[ j ]
			endfor;

		left_fig    +++    right_fig
	fi
enddef;
=======================================================================
% ============================================= |  figure components  |
=======================================================================
% ======================== |  figure components( 1 ): make functions  |
=======================================================================
% Functions to find a base figure component, already computed,
% but to compute and store it, if it not has been computed yet.
% ---------------------------------------------------
% make_fig_a :  for figure classes with only one numeric parameter
% make_fig_aa:  for figure classes with two numeric parameters
% make_fig_ax:  ... with one ..., but pretending to have two
=======================================================================
Vardef   make_fig_a ( suffix fig_p, fig_f )( expr w ) =
	if  unknown fig_f[ w ] :
		fig_f[ w ]  =  ++++ fig_p( w );
	fi

	fig_f[ w ]
enddef;
=================
				% make_fig_ax assumes: xpart fixes ypart too
Vardef   make_fig_ax( suffix fig_p, fig_f ) primary XY =
	if  unknown fig_f[ xpart XY ] :
		fig_f[ xpart XY ]  =  ++++ fig_p XY;
	fi

	fig_f[ xpart XY ]
enddef;
=================
Vardef   make_fig_aa( suffix fig_p, fig_f ) primary XY =
	if  unknown fig_f[ xpart XY ][ ypart XY ] :
		fig_f[ xpart XY ][ ypart XY ]  =  ++++ fig_p XY;
	fi

	fig_f[ xpart XY ][ ypart XY ]
enddef;
=======================================================================
% ======================== |  figure components( 2 ): path functions  |
=======================================================================
% Functions to produce paths for base figures.
% ---------------------------------------------------
% stroke_p
% rectangle_p, rect_open_p
% triangle_p, tri_open_p, tri_rect_p
% circle_p, oval_p, oval_p_with_corr, bend_p
% (roof_acute_p), roof_sloping_p, (roof_straight_p)
=======================================================================
Vardef   stroke_p( expr h ) =
	( 0 , -h )  --  ( 0 , +h )
enddef;
=================
Vardef   rectangle_p  primary XY =
	rect_open_p( XY )  --  cycle
enddef;
=================
Vardef   rect_open_p  primary XY =
	-XY  --  XY ||  --  XY  --  XY |:
enddef;
=================
Vardef   triangle_p  primary XY =
	tri_open_p( XY ) -- cycle
enddef;
=================
Vardef   tri_open_p  primary XY =
	-XY  --  ( 0, ypart XY )  --  XY |:
enddef;
=================
Vardef   tri_rect_p  primary XY =
	XY ||  --  -XY  --  XY |:  --  cycle
enddef;
=================
Vardef   circle_p( expr r ) =
	fullcircle  scy( 2 r )
enddef;
=================
Vardef   oval_p  primary XY =
	Path p =
	. (( 0, +ypart XY ) .. ( +xpart XY, 0 ) .. ( 0, -ypart XY ))
	& (( 0, -ypart XY ) .. ( -xpart XY, 0 ) .. ( 0, +ypart XY ));

	subpath( 0, 3 ) of p
	.. controls postcontrol 3 of p  and  precontrol 4 of p .. cycle
enddef;
=================
Numer  oval_corr   =  $ 0.2;   % oval correction to fight optical illusion
=========
Vardef   oval_p_with_corr  primary XY =
	Numer  correction =
		if    ypart XY <= $ 2 :   0.10 ( $ 2 - ypart XY )
		else                  :   0
		fi;

	oval_p( XY + ( correction, 0 ) )
enddef;
=================
Vardef   bend_p  primary XY =
	XY ||  ..  ( xpart XY, 0 )  ..  -XY
enddef;
=================
%Vardef roof_acute_p  primary XY =
%	tri_open_p( XY )
%enddef;
=================
Vardef roof_sloping_p  primary XY =
	Pairp PP = ( max( xpart XY - 2 ypart XY, $ 1 ), ypart XY );

	-XY  --  PP ||  --  PP  --  XY |:
enddef;
=================
%Vardef roof_straight_p  primary XY =
%	rect_open_p( XY )
%enddef;
=======================================================================
% ====================== |  figure components( 3 ): figure functions  |
=======================================================================
% Arrays to store computed base figures.
% Functions to produce base figures.
% ---------------------------------------------------
% | (for stroke)
% rectangle, rect_open
% triangle, tri_open, tri_rect
% circle, oval, bend
% roof
=======================================================================
save          stroke_f;     figure         stroke_f[]  ;
save          circle_f;     figure         circle_f[]  ;
% save roof_straight_f;     figure  roof_straight_f[]  ;
save    roof_sloping_f;     figure   roof_sloping_f[]  ;
% save    roof_acute_f;     figure     roof_acute_f[]  ;

save       rectangle_f;     figure      rectangle_f[][];
save       rect_open_f;     figure      rect_open_f[][];
save        triangle_f;     figure       triangle_f[][];
save        tri_open_f;     figure       tri_open_f[][];
save        tri_rect_f;     figure       tri_rect_f[][];
save            oval_f;     figure           oval_f[][];
save            bend_f;     figure           bend_f[][];
=================
Def     |     primary l  = make_fig_a (    stroke_p,    stroke_f )( l/2 )
enddef;
=========
Def   circle  primary d  = make_fig_a (    circle_p,    circle_f )( d/2 )
enddef;
=================
Def rectangle primary XY = make_fig_aa( rectangle_p, rectangle_f )(XY/2)
enddef;
=========
Def rect_open primary XY = make_fig_aa( rect_open_p, rect_open_f )(XY/2)
enddef;
=================
Def   triangle primary XY = make_fig_aa(  triangle_p,  triangle_f )
	( if known xpart XY :  xpart XY/2  else :  1 / sqrt 3 * ypart XY  fi
	, if known ypart XY :  ypart XY/2  else :  1/4 sqrt 3 * xpart XY  fi )
enddef;
=========
Def   tri_open primary XY = make_fig_aa(  tri_open_p,  tri_open_f )
	( if known xpart XY :  xpart XY/2  else :  1 / sqrt 3 * ypart XY  fi
	, if known ypart XY :  ypart XY/2  else :  1/4 sqrt 3 * xpart XY  fi )
enddef;
=========
Def   tri_rect primary XY = make_fig_aa(  tri_rect_p,  tri_rect_f )
	( if known xpart XY :  xpart XY/2  else :  ypart XY/2  fi
	, if known ypart XY :  ypart XY/2  else :  xpart XY/2  fi            )
enddef;
=================
Def   bend    primary XY = make_fig_aa( bend_p          , bend_f )( XY/2 )
enddef;
=================
Def   oval    primary XY = make_fig_aa( oval_p_with_corr, oval_f )( XY/2 )
enddef;
=================
Vardef   roof( expr how, xrr ) =
	Numer  yrr =  if      how = r_straight :  ( roof_height_default         )
	.             elseif  how = r_sloping  :  ( roof_height_default         )
	.             elseif  how = r_acute    :  ( roof_height_default - $ 0.5 )
	.             fi;

	if      how = r_straight:  rect_open  ( xrr  , yrr   )
	elseif  how = r_sloping :  make_fig_ax( roof_sloping_p, roof_sloping_f )
	.                                     ( xrr/2, yrr/2 )
	elseif  how = r_acute   :  tri_open   ( xrr  , yrr   )
	fi
	. ysh( yrr/2 -+ yn_high )
enddef;
=======================================================================
% ========================================= |  standard figures( 1 )  |
=======================================================================
% Frequently used special forms of base figures.
% ---------------------------------------------------
% square, square_open
% ovals
% bends
% parenthesis, parenthesis pairs
=======================================================================
Def   square          primary h  =  rectangle( h, h )  enddef;
Def   square_open     primary h  =  rect_open( h, h )  enddef;

Def   oval_norm       primary h  =  oval( h/1.5   , h )  enddef;
Def   oval_golden     primary h  =  oval( h * golden_ratio, h )  enddef;
Def   oval_medium     primary h  =  oval( h/2     , h )  enddef;
Def   oval_narrow     primary h  =  oval( h/2.5   , h )  enddef;
Def   oval_thin       primary h  =  oval( h/3     , h )  enddef;

Def   bend_very_thin  primary h  =  bend( h/12    , h )  enddef; % 1<-h=12
Def   bend_thin       primary h  =  bend( h/8     , h )  enddef; % 1.5
Def   bend_narrow     primary h  =  bend( h/6     , h )  enddef; % 2
Def   bend_medium     primary h  =  bend( h/(24/5), h )  enddef; % 2.5
Def   bend_broad      primary h  =  bend( h/4     , h )  enddef; % 3
Def   bend_fat        primary h  =  bend( h/3     , h )  enddef; % 4
Def   bend_very_fat   primary h  =  bend( h/(12/5), h )  enddef; % 5
=================
Def     oval_egg  =  oval_golden   enddef;

Figure  R_parenthesis    =  bend_thin     ( $$ )   ;
Figure  L_parenthesis    =  bend_thin     ( $$ ) ||;

Figure  R_bend_very_thin =  bend_very_thin( $$ )   ;
Figure  R_bend_narrow    =  bend_narrow   ( $$ )   ;
Figure  R_bend_medium    =  bend_medium   ( $$ )   ;
Figure  R_bow_narrow     =  bend_broad    ( $$ )   ;
Figure  R_bow_thick      =  bend_very_fat ( $$ )   ;

Figure  L_R_parenthesis  =  L_parenthesis    +++    R_parenthesis;
Figure  R_L_parenthesis  =  R_parenthesis    +++    L_parenthesis;
Figure  R_R_parenthesis  =  R_parenthesis    +++    R_parenthesis;
=======================================================================
% ========================================= |  standard figures( 2 )  |
=======================================================================
% one_of_two  : length of a stroke,
%               two of them with a gap of height distance_y_mid
%               fill the normal height
% one_of_three: ..., three of them ...
% long, shrt, midi, mini: standard stroke lengths
% i_mini: very oft used short stroke
% ii_mini, etc.: (may be two) rows of short strokes
=======================================================================
NUMER  one_of_two  ;
$$ + 2 o = 2 ( one_of_two   + ( bot 0 -+ top 0 ) ) + 1 distance_y_mid;
=========
NUMER  one_of_three;
$$ + 2 o = 3 ( one_of_three + ( bot 0 -+ top 0 ) ) + 2 distance_y_mid;
=================
Numer  long =  $ 10;
Numer  shrt =  one_of_two   ;
Numer  midi =  one_of_three ;
Numer  mini =  $  2;
=================
Figure    i_mini  =  |. mini;

Figure   ii_mini  =        i_mini  xsh( -0.5 stroke_distance_x )
.                    +++   i_mini  xsh( +0.5 stroke_distance_x );
Figure   ii_mini_narrow =  i_mini  xsh( -0.5 distance_x_low )
.                    +++   i_mini  xsh( +0.5 distance_x_low );
Figure  iii_mini  =       ii_mini  xsh( -0.5 stroke_distance_x )
.                    +++   i_mini  xsh( +    stroke_distance_x );

Figure   i___i    =        i_mini  ysh(         +mini/2  -+  yn_normal )
.                    +++   i_mini  ysh(         -mini/2  -+  ys_normal );
Figure   ii__i    =       ii_mini_narrow  ysh(  +mini/2  -+  yn_normal )
.                    +++   i_mini  shi( -0.5 distance_x_low,
.                                               -mini/2  -+  ys_normal );

Figure   ii_ii    =         i___i  xsh( -0.5 distance_x_low )
.                    +++    i___i  xsh( +0.5 distance_x_low );

Figure  iiii_iii  =   ii_ii   +++   ii__i;  % will be splitted ...
Figure  iiii_iiii =   ii_ii   +++   ii_ii;  % ... on every use
=======================================================================
% ========================================= |  standard figures( 3 )  |
=======================================================================
Figure   N_line = ++++ line( ( 0, +$ 6 ), 90 );
Figure   S_line = ++++ line( ( 0, -$ 6 ), 90 );
=======================================================================

% #####################################################################
% %%%%%%%%     % ########### |  END PART 1  : tools                   |

=======================================================================
% =========================|  parameter evaluation (for Indus signs)  |
=======================================================================
if  known first_indus_signs_wanted  <>  known last_indus_signs_wanted :
	first_indus_signs_wanted  =  not last_indus_signs_wanted;
fi

if  known first_indus_signs_wanted  cand ( not first_indus_signs_wanted ):
	last_only ( temporary_sin_first )
	.         ( list_of_indus_signs_wanted )( 256 );
	def  list_of_indus_signs_wanted = temporary_sin_first  enddef;
fi

if  known  last_indus_signs_wanted  cand ( not  last_indus_signs_wanted ):
	first_only( temporary_sin_last  )
	.         ( list_of_indus_signs_wanted )( 256 );
	def  list_of_indus_signs_wanted = temporary_sin_last   enddef;
fi

Boolean                indus_signs_needed =
.   not empty( list_of_indus_signs_wanted );
=======================================================================

if indus_signs_needed:
begingroup     % ########### |  BEG PART 2  : Indus glyph             |
% #####################################################################

if  progress_report >= 1 :
	show "Indus glyph generation starts ...";
fi

=======================================================================
% =========================================== |  sign temporary data  |
=======================================================================
% In producing the glyphs, we need to hold a lot of information on them,
% not needed afterwards. To avoid wasting memory, we store this information
% separate as a kind of appendix to `sign_mem' - say `sign_memA'.
%
% Information on sign variants not really belongs to these temporaries
% but until we handle them seriously, I don't know, what to do with them.
% So for now we store it in sign_memA too.
=======================================================================
save  sign_memA;    % glyph and sign temporary information
					% indexed as [sign_id] (technically: [][])
=========
figure  sign_memA[][] [];
	% special figures in glyph construction: index 0 - 9
	%    ( not used very often ((62 occurrences on 2001/03/01))
	%      and not very useful
	%      - so this possibility is candidate to be eliminated )
	% or glyph variants
	%    ( IMa: indices: .0001 - .9999 )    %% avoid infinity ( <4096 )
	%    ( APa: indices: a ... z, aa, ... zz = .001 - .052 )
=========
pair    sign_memA[][] .next; % loop connecting glyph function sharing glyphs
=========
Def   building_stone_tags  =  compass_point,
.                             we, sn,
.                             no, eo, so, wo,
.                             a, b, c, d, h, x, y, z
enddef;
=========
forsuffixes  r = building_stone_tags : % parts & building stones
	figure  sign_memA[][]   .r,
	.       sign_memA[][][] .r;        % candidate to become eliminated
endfor
=======================================================================
% ============================================== |  sign data access  |
=======================================================================
% To avoid cluttering the split sign_mem/sign_memA into the code,
% it will be hidden in the glyph access function
% - we replace this for the lifetime of sign_memA as follows:
=======================================================================
save  glyph;
def   glyph( expr sign_id ) suffix sfx  =
	if  str sfx = "": sign_mem
	else            : sign_memA
	fi
	.                 [ first sign_id ][ second sign_id ] sfx
enddef;
=======================================================================
% ======================================= |  variants identification  |
=======================================================================
% Glyph variants will be indexed by number, so we need a conversion
% of the variants identification form found in the source literature
% into numbers.
% Any new convention of variant naming demands an adaptation here! (XYz)
%
% For now we use:
% IMa: the variants have no own name,
%      but are designated by the number of one of the texts, it occurs in.
%      So we take this number, ranging from 0001 to 9999, as variant number
%      - but divided by 10000 to not collide with Metafonts infinity (<4096).
% APa: The variants are designated  by a, ... z, aa, ... zz.
%      We convert this into ( 1/100 * ) 1, ... 26, 27, ... 52.
%     (But this could be changed freely,
%      only the values 0,1, ..., 9 are taboo for their special figure use.)
=======================================================================
Vardef   variant  suffix sfx  =
	String  s  =  str sfx;
	if   length s > 2 :  sfx           % it already has fractional form
	else              :  1/100( ASCII s  -  ASCII "a"   +   1
	.                           if   length s = 2:      +  26  fi )
	fi
enddef;
=======================================================================
% ===================== |  functions to evaluate a glyph description  |
=======================================================================
% Glyph description functions are written with macro Dd (see below).
% Dd uses the following functions to evaluate the description:
%
% compute_glyph
%   computes a glyph from its description function;
%   the text can be the function body itself or a call to the function.
%
% associate_glyphs
%   chains given glyphs together, because only one of them
%   corresponds directly to a glyph description function.
%   The said chaining allows to reach this function
%   from the other glyphs too.
%   (The glyph description function will be defined at the end of Dd,
%   but only on the first pass through the long loop below.)
%
% prime_glyph
%   finds for a given glyph_id that associated glyph_id
%   (itself, maybe), which has a directly corresponding
%   glyph description function.
%
% evaluate_modes
%   evaluates the mode parameters of Dd
%   - i.e. only the bound information from y_mode yet -
%   and assigns these information to every listed glyph.
=======================================================================

=======================================================================
% ================================================= |  compute_glyph  |
=======================================================================
Numer  sign_count :=  0;
Numer  call_depth :=  0;
=================
Def   compute_glyph( expr sign_id )( text t ) =
begingroup
		% associate to every sign list that one of its sign numbers
		% (if there is such one), which corresponds to the given glyph
	save  actual_sign_no;    numer  actual_sign_no[];

	begingroup
		Pair  xxx := sign_id;
		forever:
			actual_sign_no[ first xxx ] = second xxx;
			xxx := glyph( xxx ) .next;
			exitif  xxx = sign_id;
		endfor
	endgroup;

	save  sid;
	def   sid  primary sigl  = ( sigl, actual_sign_no[ sigl ] )  enddef;

	%%%%

	if ( call_depth  > 0 )    % services will be done unconditionally
	cor(
		.     known sid\ASL
		cand( is_may_be_range_element( second sid\ASL )
		.                            ( list_of_indus_signs_wanted ) )
	):
	begingroup
			% compute list of sign lists, we have to handle with:
		save  sigl_list;
		def   sigl_list =  enddef;
		for  sigl = sign_lists_implemented_stage_d :
			if  known sid\sigl :
				scantokens "def sigl_list =" sigl_list, sigl  quote enddef;
			fi
		endfor

		Numer  sigl_prime  =
			if   is_element( ASL )( sigl_list ):  ASL
			else                               :  first sign_id
			fi;

		if  (   ( sigl_prime = ASL )  % produce a sign, if it's an ASL sign
		.    or ( call_depth > 0  ) ) % or if somebody called for it
		and  unknown glyph( sid\sigl_prime ) % not ready yet ?
		:
				% define shorthand symbols as I, Ip for actual sign lists
			for  sigl = sigl_list:
					% save I ;  def I  = glyph( sid\sigl ) enddef; ...
				xxxs   := sign_list_string_uc( sigl );     % I /A /...
				expandafter   save  scantokens xxxs;
				scantokens( "def "  &  xxxs   ) =  glyph( sid\sigl )
				.     quote  enddef;

					% save Ip;  def Ip = glyph( sid\sigl ) enddef; ...
				xxxs_a := xxxs & "p";                      % Ip/Ap/...
				expandafter   save  scantokens xxxs_a;
				scantokens( "def "  &  xxxs_a ) =  glyph( sid\sigl )
				.     quote  enddef;
			endfor

			sign_count := sign_count + 1;

			call_depth := call_depth + 1;
			if  progress_report >= 2 :
				show  "--- "
					for  d = 2  upto  call_depth :  & "--- "  endfor
					&  sign_name( sid\sigl_prime )
					&  " (no. "  &  decimal sign_count  &  " )";
			fi

			t;

			call_depth :=  call_depth - 1;
			if  progress_report >= 2 :
				if  call_depth > 0 :
					show  "--- "
					for  d = 2  upto  call_depth :  & "--- "  endfor;
				fi
			fi

				% if it has not worked by error - set glyph to zero figure
			for  sigl = sigl_list:
				if  unknown glyph( sid\sigl ):
					glyph( sid\sigl ) = zero;
				fi
			endfor

				% delete macro = free its memory:
			xxxpr := prime_glyph( sign_id );
			scantokens( "numeric "  &  glyph_function_name( xxxpr ) );

		fi
	endgroup ;
	fi
endgroup
enddef;
=======================================================================
% ================================================= |  evaluate_modes  |
=======================================================================
Def   evaluate_modes( text sign_ids )( expr x_mode, y_mode ) =
	% x_mode unused yet

	if known y_mode:
		for sign_id = sign_ids :
			if  unknown glyph_bounds( sign_id )[ y_axis ]:
				glyph_bounds( sign_id )[ y_axis ] =
					if      y_mode = Y_NORM :  sn_normal
					elseif  y_mode = Y_ROOF :  sn_roofed
					elseif  y_mode = Y_HIGH :  sn_high
					fi;
			fi
		endfor
	fi
enddef;
=======================================================================
% ============================================== |  associate_glyphs  |
=======================================================================
Def   associate_glyphs( text sign_ids ) =
	if  unknown glyph( lhead( sign_ids ) ).next:
		associate_glyphs_really( sign_ids );
	fi
enddef;
=================
Vardef   associate_glyphs_really( text sign_ids ) =
	PAIR  start, next;
	start = next;
	forsuffixes  actual = sign_ids :
		next = actual;
		pair   next;
		glyph( actual ) .next = next;
	endfor
	next = start;
enddef;
=======================================================================
% =================================================== |  prime_glyph  |
=======================================================================
Vardef   prime_glyph( expr sign_id ) =
	Pair  prime  := sign_id;

	Pair  actual := sign_id;
	forever:
		actual := glyph( actual ) .next;
		exitif  actual = sign_id;
		prime  := min( prime, actual );
	endfor

	prime
enddef;
=======================================================================
% ======================================== |  immediate glyph access  |
=======================================================================
% We want to be able to access every glyph from everywhere,
% without to worry on the order to compute them.
%
% And we want to write the glyph descriptions in their numeric order.
% (There is some doubt, what that means,
%  when we handle more than one sign list seriously
%  - but now it means: in the IMa numbering order.
%  (The only exception made, will be i418.))
%
% So every glyph description function must be accessible,
% as soon as the first glyph starts to be constructed.
% This will be managed by the long loop following shortly - it collects
% the functions in a first run and evaluates them in a second one.
%
% So we can build immediately an accessed glyph,
% which has not been produced yet, by calling its function
% - but it's a little bit complicated
% because the functions have different environments.
=======================================================================
% ip, ap, ...
%   This is the family of the `public' functions in this group,
%   used to access a glyph from out of its description function.
%   For example: ip\222 accesses glyph number 222 from the IMa list,
%   if it's already computed or not.
%   But the real work will be done by:
%
% zzp
%   returns the wanted glyph,
%   either immediately - if it's already there -
%   or after its construction has been organized by:
%
% compute_glyph_with_context
%   computes a glyph, called for from another glyph description
%   function, which was not computed yet.
%   The call for the wanted glyph will be done in that's glyph
%   simulated environment by constructing the group structure
%   and evaluating the context functions associated to the groups.
=======================================================================

=======================================================================
% =================================================== |  ip, ap, ...  |
=======================================================================
% The following loop produces definitions as
%     Def  ip suffix sfx = zzp( IMa )( sfx )  enddef;
% ditto for ap, etc.
=======================================================================
for  sigl = sign_lists_implemented_stage_d :
	scantokens( "Def "  &  sign_list_string_lc( sigl ) & "p" )
	.            suffix sfx
	.            =
	.            zzp( sigl )( sfx )
	.    quote   enddef;
endfor
=======================================================================
% =========================================================== |  zzp  |
=======================================================================
Vardef   zzp( expr sigl )( suffix sfx ) =
	Pair  sign_id = ( sigl, suffix_head sfx );
	if  unknown glyph( sign_id ) :
		compute_glyph_with_context( sign_id );
	fi
	scantokens( "glyph( sign_id )" & suffix_tail_string sfx )
enddef;
=======================================================================
% ==================================== |  compute_glyph_with_context  |
=======================================================================
Vardef   compute_glyph_with_context( expr sign_id ) =
	Numer  sigl = first  sign_id;

		% Irregularities of numbering in one sign list
		% or disharmonies between two seriously handled sign lists
		% could demand for an advanced method to hold context information.
		% For now we run it with one hack:
	Numer  nom =
		if   sign_id = ( IMa, 418 ):  015.418 % not worth not to hack
		else                       :  second sign_id
		fi;

		% build and enter the environment
	Numer  group_counter := -1;
	for  c = 0  upto  context[ sigl ] .hix :
		exitif  nom < second context[ sigl ][ c ][ 0 ] - 0.5;
		if      nom < second context[ sigl ][ c ][ 1 ] + 0.5  :
			group_counter := group_counter + 1;
			begingroup
				context_function( context[ sigl ][ c ][ 0 ] % ,
				.               , context[ sigl ][ c ][ 1 ] ) ;
		fi
	endfor

		% call the function
	compute_glyph( sign_id )
	.            (
	.              glyph_function( prime_glyph( sign_id ) );
	.            );

		% remove the environment
	for  k = group_counter  downto  0 :
			endgroup ;
	endfor
enddef;
=======================================================================
% ==================================================== |  shorthands  |
=======================================================================
% some shorthands for writing/calling glyph description functions
% (we want to write glyph descriptions with little redundancy)
=======================================================================

=======================================================================
% ============================ |  shorthands: compute function names  |
=======================================================================
% Names cannot contain digits, point, minus sign -
% so take converted forms instead.
% Convert these characters using:
=========
save   charname;
string charname[];
begingroup
	charname[ ASCII "0" ] = "Zero" ;
	charname[ ASCII "1" ] = "One"  ;
	charname[ ASCII "2" ] = "Two"  ;
	charname[ ASCII "3" ] = "Three";
	charname[ ASCII "4" ] = "Four" ;
	charname[ ASCII "5" ] = "Five" ;
	charname[ ASCII "6" ] = "Six"  ;
	charname[ ASCII "7" ] = "Seven";
	charname[ ASCII "8" ] = "Eight";
	charname[ ASCII "9" ] = "Nine" ;
	charname[ ASCII "." ] = "Point";
	charname[ ASCII "-" ] = "Minus";
endgroup;
=================
% a number as a name part must be represented by letters and `_' only:
=========
Vardef   number_name   primary number =
	String  n_string  =  decimal number;

	for  n = 0  upto  length n_string - 1 :
		if n > 0 : & fi  charname[ ASCII substring (n, n + 1) of n_string ]
	endfor
enddef;
=================
String           glyph_function_name_head = "DC" ;
String  glyph_variants_function_name_head = "DCv";
String         context_function_name_head = "DC" ;
=================
% compute the name of a glyph description (vardef-) function
%   example: ( Xyz, 111 ) --> DC.x.OneOneOne
=========
Def   glyph_function  primary sign_id =
	scantokens  glyph_function_name( sign_id )
enddef;
=========
Vardef   glyph_function_name  primary sign_id =
		glyph_function_name_head
		&  "."
		&  sign_list_string_lc(  first sign_id )
		&  "."
		&  number_name        ( second sign_id )
enddef;
=================
% compute the name of a glyph variant description (vardef-) function
%   example: ( Xyz, 111 ) --> DCv.x.OneOneOne
=========
Def   glyph_variants_function  primary sign_id =
	scantokens  glyph_variants_function_name( sign_id )
enddef;
=========
Vardef   glyph_variants_function_name  primary sign_id =
		glyph_variants_function_name_head
		&  "."
		&  sign_list_string_lc(  first sign_id )
		&  "."
		&  number_name        ( second sign_id )
enddef;
=================
% compute the name of a context producing (def-) function
%   example: ( ( Xyz, 111 ), ( Xyz, 222 ) ) --> DC_x_OneOneOne_TwoTwoTwo
=========
Def   context_function( expr bound_a, bound_b ) =
	scantokens  context_function_name( bound_a, bound_b )
enddef;
=========
Vardef   context_function_name( expr bound_a, bound_b ) =
		context_function_name_head
		&  "_"
		&  sign_list_string_lc(  first bound_a )
		&  "_"
		&  number_name        ( second bound_a )
		&  "_"
		&  number_name        ( second bound_b )
enddef;
=======================================================================
% ============================================= |  define shorthands  |
=======================================================================
% The following definitions (Fi, ... ZZP)
% are only used for the `future looking' code for i176 - i180
% i.e. for the code, which produces glyph variants too.
%
% Because the lack on experience on the real needs to do this,
% there is a high probability on two sorts of misdesign here:
% 1) there is something missing, we will need or want to have;
% 2) there is something there, we don't really need.
%    Especially:
%    Do we really need sign list specific function triples as Fi, FI, IP
%    resp. Fa, FA, AP etc.? Or would one triple alone do it?
=======================================================================

=======================================================================
% ======================================= |  shorthands: Fi, Fa, ...  |
=======================================================================
% Glyph variants constructing functions can be written using Fi, Fa, ...
% The following loop produces definitions for them in the form
%     Def  Fi = Fzz( IMa );
% ditto Fa, etc.
%
% With these definitions instead of:
%   vardef DCv.i.OneOneOne( expr a, b, alpha, beta, main ) = ... enddef;
% we can write :
%             Fi          ( expr a, b, alpha, beta, main )(  ... )     ;
% .
=======================================================================
for  sigl = sign_lists_implemented_stage_d :
	scantokens( "Def "   &   "F" & sign_list_string_lc( sigl ) )
	.            =  Fzz( sigl )
	.    quote   enddef;
endfor
=================
Def   Fzz( expr sigl )( text params )( text t )  =
	scantokens( "vardef "  &  glyph_variants_function_name( sid\sigl ) )
	.            ( params )
	.            =  t
	.    quote   enddef;
enddef;
=======================================================================
% ======================================= |  shorthands: FI, FA, ...  |
=======================================================================
% to call a glyph variants constructing function
% from inside of its glyph description function
% and to define all variants from the Mahadevan/Parpola/... source,
% we have associated this realized variant to,
% we use FI, FA, ... (FI to call Fi, FA to call Fa, etc).
%
% The following loop defines them in the form
%     Def  FI = FZZ( IMa )  enddef;
% ditto FA, etc.
=======================================================================
for  sigl = sign_lists_implemented_stage_d :
	scantokens( "Def "  &  "F" & sign_list_string_uc( sigl ) )
	.            =  FZZ( sigl )
	.    quote   enddef;
endfor
=========
Def   FZZ( expr sigl_prime ) % sign list, the variants function is named after
.        ( text ilist )
.        ( text alist )
%        ( text xlist )         % XYz
.        ( text params ) =

		% compute the glyph:
	xxxpr :=  sid\sigl_prime;
	xxxf  :=  glyph_variants_function( xxxpr )( params );

		% distribute the glyph:
	for  sigl = sign_lists_implemented_stage_d :
		if known sid\sigl:
			forsuffixes sfx =
				if      sigl = IMa: ilist
				elseif  sigl = APa: alist
%				elseif  sigl = XYz: xlist
				fi:
					glyph( sid\sigl ) .[ variant sfx ] = xxxf;
			endfor
		fi
	endfor
enddef;
=======================================================================
% ======================================= |  shorthands: IP, AP, ...  |
=======================================================================
% To call a glyph variants constructing function
% (normally) from outside of its glyph description function
% we use IP, AP, ...
% , defined by the following loop in form of
%    Def  IP( nr ) = ZZP( ( IMa, nr ) )  enddef;
% ditto AP, etc.
=======================================================================
for  sigl = sign_lists_implemented_stage_d :
	scantokens( "Def "  &  sign_list_string_uc( sigl ) & "P" )( expr nr )
	.            =  ZZP( ( sigl, nr ) )
	.    quote   enddef;
endfor
=========
Def   ZZP( expr sign_id )( text params ) =
	if  llength( params ) > 0:  glyph_variants_function( sign_id )( params )
	else                     :  glyph_variants_function( sign_id )
	fi
enddef;
=======================================================================

% #####################################################################
begingroup     % ########### |  BEG PART 2.1: Indus glyph production  |
% #####################################################################

=======================================================================
% Indus glyphs are produced by looping through the glyph descriptions
% two times - defining them (and their context) as macros on first,
% evaluating them on second loop.
=======================================================================

=======================================================================
% ========================================= |  production: variables  |
=======================================================================
% (Context functions (`DC_...') will not be saved here
%  - for technical reasons: def's have no common first token -,
%  but their storage will be reclaimed
%  behind of the glyph producing loop.)
=======================================================================
save  DC ,     % combines all glyph description macros
.     DCv;     % combines all glyph variant description macros
=================
save  context; % information on glyph groupings, allows to associate
.              % a glyph with all groups embodying its description
pair  context[][][] ;     % [sigl] [context-index] [0=start,1=end]
numer context[] .hix;
=========
	for  sigl = sign_lists_implemented_stage_c :
		context[ sigl ] .hix := -1;
	endfor
=======================================================================
% ========================================== |  production: The Loop  |
=======================================================================
for stage = 0 upto 1 :

	================= ================= =================
	% stage dependent macros: Cc, Dd
	% ( two definitions are more efficient than one )
	================= ================= =================

	================= ================= =================
	% ========================================== |  Dd  |
	================= ================= =================
	save  Dd;

	if stage  =  0 :

		def   Dd( text glyphs )( expr x_mode, y_mode )( text body ) =
			xxxpr :=
			begingroup
				forsuffixes  xx  =  sign_lists_implemented_suffixes:
					save   xx;
					vardef xx @# = (sign_list_number str xx, @#) enddef;
				endfor

				associate_glyphs( glyphs );
				evaluate_modes( glyphs )( x_mode, y_mode );

				prime_glyph( lhead( glyphs ) )
			endgroup;

			scantokens( "vardef "  &  glyph_function_name( xxxpr ) )
			.            =  body;
			.quote quote enddef;
		enddef;

	else:
		def   Dd( text glyphs )( expr x_mode, y_mode )( text body ) =
			xxxpr :=
			begingroup
				forsuffixes  xx  =  sign_lists_implemented_suffixes:
					save   xx;
					vardef xx @# = (sign_list_number str xx, @#) enddef;
				endfor

				lhead( glyphs )
			endgroup;

			compute_glyph( xxxpr )( body; );
		enddef;
	fi

	================= ================= =================
	% ========================================== |  Cc  |
	================= ================= =================
	save  Cc;

	if stage  =  0 :
		def  Cc( suffix bound_beg, bound_fin )( text t ) =
		begingroup
			PAIR   glyph_beg, glyph_fin;
			begingroup
				forsuffixes  xx  =  sign_lists_implemented_suffixes:
					save   xx;
					vardef xx @# = (sign_list_number str xx, @#) enddef;
				endfor

				glyph_beg = bound_beg;
				glyph_fin = bound_fin;
			endgroup;

			scantokens( "def "
			.         &  context_function_name( glyph_beg, glyph_fin ))
			.            =  t;
			.quote quote enddef;

			Numer    sigl  =  first glyph_beg;
			context[ sigl ][incr context[ sigl ] .hix ][ 0 ] = glyph_beg;
			context[ sigl ][     context[ sigl ] .hix ][ 1 ] = glyph_fin;
		endgroup
		enddef;

	else:
		def  Cc( suffix bound_beg, bound_fin )( text t ) =
			t;
		enddef;
	fi

=======================================================================
% ================================= |  production: glyph description  |
=======================================================================
	begingroup %% i000 - i419

Cc( i000, i419 )( %%
	Pair  isn_base = sn_normal;
;
	Transform  ysc_shrink = identity  yscaled( dy_shrinked   /  dy_normal )
	.                             shifted( 0, -dy_shrinked/2  -+  is_base );

	Transform  scy_shrink = identity   scaled( dy_shrinked   /  dy_normal )
	.                             shifted( 0, -dy_shrinked/2  -+  is_base );
); %%

Dd( i000 )( X_EQB  )( Y_NORM )( % s; k
;
	iwe = !! $ 4;
;
	Path  p = iWS  --  iWN  --  iEN  --  iES  --  cycle;
;
; I      =   p  ''( 5, Angle iEN, ( 0.9 iWN, 0.9 iES ) )
%                   7, not 5, originally
);

		begingroup %% i001 - i015, i418, i016 - i046

Cc( i001, i046 )( %%
	Pair   iwe_base = !! good.x $ 7/3;
;
	Numer  man_height       =   $$;
	Numer  head_neck_length =  3/12 man_height;
	Numer  body_length      =  4/12 man_height;
	Numer  leg_height       =  5/12 man_height;

	Numer  leg_width        =   ie_base ;
	Numer  arm_width        =  leg_width;

	Nangle arm_body_angle   =  55;                       % angle with body
;
	Nangle leg_angle  = Angle( leg_width, leg_height ); % with `down', ~ 25

	NUMER  arm_height;
	sind arm_body_angle  *  arm_height  =  cosd arm_body_angle  *  arm_width;

	Numer  leg_length =  leg_height  ++  leg_width;
%
	Pairp   head_top  = ( 0, in_base );
	Pairp   neck_bot  = Good.y( head_top - ( 0, head_neck_length ) );
	Pairp   crotch    = Good.y( neck_bot - ( 0, body_length      ) );
	Pairp   foot_l    = Good.z( crotch   + ( - leg_width , - leg_height ) );
	Pairp   foot_r    = foot_l ||;
	Pairp   hand_l    = Good.z( neck_bot + ( - arm_width , - arm_height ) );
	Pairp   hand_r    = hand_l ||;
%
	Path    head_neck = head_top -- neck_bot;
	Path    body      = neck_bot -- crotch  ;
	Path    arm_l     = neck_bot -- hand_l  ;
	Path    arm_r     = neck_bot -- hand_r  ;
	Path    leg_l     = crotch   -- foot_l  ;
	Path    leg_r     = crotch   -- foot_r  ;
%
	Figure  head_neck_f = ++++   head_neck;
	Figure  arm_l_f     = ++++   arm_l;
	Figure  arm_r_f     = arm_l_f  ||;
%
	Figure  arms        = arm_l_f    +++    arm_r_f;
	Figure  legs        = ++++ ( leg_l`    &  leg_r );
	Figure  head_body   = ++++ ( head_neck &  body  );
%
	Figure       head_legs  =  head_neck_f  +++    legs;
	Figure       body_legs  =       body    +++    legs;
	Figure  head_body_legs  =  head_body    +++    legs;
	Figure  head_body_arms  =  head_body    +++    arms;
%
	Figure  man             =  head_body_legs    +++    arms;
%
	Path    hand_r_bridge_jet  =  jet( hand_r, arm_body_angle );
	Pairp   hand_r_con_bridge  =  hand_r_bridge_jet
	.               where_x  ( xpart hand_r + bridge_width_default_narrow );
	Path    hand_r_bridge      =  hand_r -- hand_r_con_bridge;
	Figure  man_con_bridge     =  man    +++    hand_r_bridge;
); %%

Dd( i001 )( X_SYM  )( Y_NORM )( % s015; k013
;
	iwe = iwe_base;
;
; I      =   man
; I\0    =   head_body_legs   % for i126
);

Dd( i002 )( X_SYM  )( Y_NORM )( % s017; k015
;
	iwe = !! ( ie_base  +  split_distance_default  +  0 );
;
; I  .h  =   ip\001
; I      =   I.h    +++    ip\087  splitted
);

Dd( i003 )( X_SYM  )( Y_NORM )( % s016; k014
;
	iwe = iwe_base;
;
; I  .h  =   ip\001
; I  .s  =   i_mini  ysh( -1/2 mini  -+  is )
; I      =   I.h    +++    I.s
);

Dd( i004 )( X_EQB  )( Y_NORM )( % s008; k007
;
	iwe = iwe_base;
;
; I  .h  =   ip\001
;
	Pairp  NN  =  1/5 [ head_top, neck_bot ];
	Pairp  SS  =  1/5 [ neck_bot, head_top ];
	Pairp  EE  =  1/2 [ SS, NN ]  +  ( ie, 0 );
	Path  nose = NN { right |>5 }  ..  EE    &    EE  ..  { left |<5 } SS;
;
; I      =   I.h   +++   nose   +++   nose ''( 1, 0, ( 0.40[ NN, EE ] ) )
);

Dd( i005 )( X_SYM  )( Y_NORM )( % s009; k008
;
	iwe = !! good.x 3/2 ie_base;
;
; I  .h  =   ip\001
;
	Pairp   NN  = Good.y 1/4 [ head_top, neck_bot ];
	Pairp   SS  = Good.y 1/4 [ neck_bot, head_top ];
	Pairp   WW  = good.lft( SS  +  ( iw, -$ 1.5 ) );
	Path   moon_w =                  NN { left }
	.               .. { down |>20 } WW { WW  -+  head_top }
	.               .. { right     } SS;
	Path   moon    =  moon_w  &  moon_w || `;
;
; I  .n  =   ++++ moon
; I  .nw =   I.n ''( 2, crotch, ( Point 0.25 of moon, Point 0.55 of moon ) )
; I  .ne =   I.nw  ||
; I      =   I.h    +++    I.n    +++    I.nw    +++    I.ne
);

Dd( i006 )( X_EQB  )( Y_NORM )( % s; k
;
	iwe = iwe_base;
;
; I  .h  =   ip\001
; I  .b  =   arm_r_f
; I  .ne =   I.b  shi( - vect head_neck )
; I      =   I.h    +++    I.ne
);

Dd( i007 )( X_EQB  )( Y_NORM )( % s; k
;
	iwe = iwe_base;
;
; I  .h  =   ip\001
; I  .b  =   arm_l_f
; I  .ne =   I.b  shi( - vect arm_l )
; I      =   I.h    +++    I.ne
);

Dd( i008 )( X_SYM  )( Y_NORM )( % s011; k009
;
	iwe = iwe_base;
;
; I  .h  =   ip\001
;
	Pairp  NO       =  Good.y 1/3 [ neck_bot, head_top ];
	Path   crown_w  =  iWN { down |<25 }  ..  { right } NO;
	Path   crown    =  crown_w   &   crown_w  ||  `;
;
; I  .n  =   ++++ crown
; I      =   I.h    +++    I.n
);

Dd( i009 )( X_EQB  )( Y_NORM )( % s012.1; k010.071
;
	iwe = !! ( ie\008  +  split_distance_default  +  rrx L_parenthesis );
;
; I  .h  =   ip\008
; I      =   I.h    +++    R_R_parenthesis  splitted
);

Dd( i010 )( X_SYM  )( Y_NORM )( % s002; k001.143
;
	iwe = !! $ 3;
;
; I  .h  =   head_body_legs
;
	Pairp  NN  =  Good.y 1/2 [ head_top, neck_bot ];
	Pairp  SW  =  Good.z( jet( neck_bot, hand_l )  where_x  iw );
	Pairp  NW  =  ( iw , ypart NN );
	Path   yoke_short_w = neck_bot  --  SW  --  NW  --  NN;
	Path   yoke_short   = yoke_short_w   &   yoke_short_w || `;
;
; I  .n  =   ++++ yoke_short
; I      =   I.h    +++    I.n
);

Dd( i011 )( X_SYM  )( Y_NORM )( % s004; k003.341
; I  .h  =   body_legs
;
	Numer  tria_side = teqla_s( head_neck_length );
;
	iwe = !! good.x 3/2 tria_side;
;
	Pairp  CC  =  neck_bot;
	Pairp  WW  =  CC  xsh( 0  -+  iw );
	Pairp  SW  =  CC  +  ( 2/3 iw, - head_neck_length );
	Path    p  =  WW  --  SW  --  iON  --  SW ||  --  WW ||  --  cycle;
;
; I  .n  =   ++++ p
; I      =   I.h    +++    I.n
);

			begingroup %% i012 - i015, i418

Cc( i012, i015 )( %%
	Pair   iwe_base = !! $ 6;

	Numer  sack_height  = $ 5  ;
	Numer  sack_breadth = $ 2.5;
;
	Pairp  NW = ( iw_base + 1/2 sack_breadth, ypart neck_bot );
	Pairp  WW = line( arm_l )  Intersectionpoint_right  jet( NW, 180 );

	Path  yoke_w     = NW  --  neck_bot;
	Path  rope_w     = WW  --  NW      ;
	Path  arm_long_w = WW  --  neck_bot;
	Path  sack_w     = oval_p( 1/2 sack_breadth, 1/2 sack_height )
	.                   shi( ( 0, +1/2 sack_height )  -+  WW );

	Path  yoke_ropes_sacks_w = sack_w   &  rope_w & yoke_w;
	Path  yoke_ropes_sacks   = yoke_ropes_sacks_w & yoke_ropes_sacks_w || `;
	Path  arms_long          = arm_long_w         &  arm_long_w || `;
); %%

Dd( i012 )( X_SYM  )( Y_NORM )( % s001; k001.144
;
	iwe = iwe_base;
;
; I  .a  =   legs    +++    yoke_ropes_sacks
; I  .b  =   body    +++    arms_long    +++    I.a
; I  .c  =   head_neck_f
; I      =   I.b    +++    I.c
);

Dd( i013 )( X_SYM  )( Y_NORM )( % s; k002
;
	iwe = iwe_base;
;
; I  .h  =   ip\012
; I  .s  =   ip\003.s
; I      =   I.h    +++    I.s
);

Dd( i014 )( X_SYM  )( Y_NORM )( % s003; k003.244
;
	iwe = iwe_base;
;
; I  .h  =   ip\012.b
; I  .b  =   tri_open( unk, head_neck_length )
; I  .n  =   I.b  ysh( head_neck_length/2  -+  in )
; I      =   I.h    +++    I.n
);

Dd( i015 )( X_SYM  )( Y_NORM )( % s005; k004
;
	iwe = iwe_base;
;
; I  .h  =   ip\012.b
; I  .b  =   ip\342\2  scy head_neck_length
; I  .n  =   I.b  ysh( head_neck_length/2  -+  in )
; I      =   I.h    +++    I.n
);

Dd( i418 )( X_any  )( Y_HIGH )( % s; k005
;
	Numer  nh  =  3/4 * ( yn_shrinked  -+  in );
;
; I  .a  =   oval_norm. nh
; I  .n  =   I.a  ysh( +nh/2  -+  in )
;
; I  .b  =   ip\015.n
;
	Pairp  PP  =  Point 0.11 of yoke_w;
	Pairp  QQ  =  PP  +  $( 0.5, -2 );
	Pairp  NA  =  neck_bot - 1/2( 0, stroke_thickness_y );
	Pairp  NB  =  neck_bot -    ( 0, stroke_thickness_y );
;
	Pairp  P_shrinked  =  PP  transformed ysc_shrink;
;
	Path   my_arm_w      =  PP  ---  QQ  ---  NA;
	Pairp  my_foot_l     =  foot_l  xsh( foot_l  -+  1/3[ foot_l, iOS ] );
	Pairp  my_crotch     =  crotch  ysh( crotch  -+  1/3[ crotch, iOS ] );
	Path   my_body_leg_w =  my_foot_l --- my_crotch  .. tension 0.8 ..  NB;
	Path   my_arms       =  my_arm_w        &   my_arm_w      || `;
	Path   my_body_legs  =  my_body_leg_w   &   my_body_leg_w || `;
;
; I  .c  =   my_body_legs   +++   my_arms   +++  yoke_ropes_sacks   +++  I.b
; I  .h  =   I.c  Transformed ysc_shrink
;
;    pit:=   ip\176   % make sure, we can access IP(176)
;
; I  .nnw=   IP( 176 )( $ 5 , $ 4/3, -90, 0, tT, 6 )
; I  .d  =   |. ($ 1.5)  ysh( -($ 1.5)/2  -+  0 )
; I  .x  =   I.nnw  ysh( ~.?.y_s  -+  ($ 1.5) )
; I  .y  = ( I.x    +++    I.d )  |< ( 90 - arm_body_angle )
;
	scf_nw := min( 1, ( ypart P_shrinked  -+  in ) / ( 0  -+  I.y.?.y_n ) );
;
; I  .z  =   I.y  Scaled scf_nw
; I  .nw =   I.z  shi( OQ  -+  P_shrinked )
;
; I      =   I.h    +++    I.n    +++    I.nw
;
	iwe = min( iwe_base, ( I.nw.?.x_w, ie_base ) );
;
);

			endgroup ; %% i012 - i015, i418

Dd( i016 )( X_EQB  )( Y_NORM )( % s007; k006
;
	Numer  rx_mid    = $ 1.5;
	Numer  tria_side = teqla_s( head_neck_length );
;
	iwe = !! rx_mid  +  !! 2 tria_side;
;
; I  .a  =   head_body_legs
;
	Pairp  CC  =  neck_bot;
	Pairp  WW  =  CC  xsh( - tria_side );
	Pairp  EE  =  CC  xsh( + tria_side );
	Pairp  SW  =  CC - ( 1/2 tria_side, head_neck_length );
	Path    p  =  WW  --  SW  --  CC  --  SW ||  --  EE  --  cycle;
;
; I  .x  =   I.a    +++    p
; I  .w  =   I.x  xsh( xpart WW  -+  iw )
; I  .e  =   I.x  xsh( xpart EE  -+  ie )
;
	Pairp  WW = EE  xsh( xpart WW  -+  iw );
	Pairp  EE = WW  xsh( xpart EE  -+  ie );

	Path  m = WW  --  CC  -- $( -1.5, -5.5 ) -- $( +1.5, -5.5 ) -- CC -- EE;
;
; I  .o  =   m     +++    m ''( 2, 45, ( $(0,-3.6), $(0,-1.1) ) )
; I      =   I.w   +++    I.o    +++    I.e
);

Dd( i017 )( X_any  )( Y_NORM )( % s013; k011
;
	Pairp  PP      =  hand_l  shi( vect body );
;
	Path   p_w     =  ( neck_bot { Dir -125 }  ..  { Dir 170 } PP )
	.                  softjoin  ( PP  --  crotch );
	Path   p_e     =  p_w  ||;
	Path   my_body =  p_w    &    p_e `;
;
	Path   tool_l  =  leg_r   Rotatedaround( crotch, 170 );
	Pairp  RR      =  tool_l  Intersectionpoint_right  p_w;
	Path   tool_r  =  crotch  --  ( RR || );
;
; I  .b  =   ++++ ( tool_l`  &  tool_r )
; I      =   head_legs    +++    my_body    +++    I.b
;
	xxxn := max( xpart foot_r, p_e.?.x_e );
;
	iwe = ( min( -xxxn, xpart fin tool_l ), xxxn );
;
);

Dd( i018 )( X_EQB  )( Y_NORM )( % s023; k023
;
	iwe = iwe_base;
;
; I  .h  =   ip\001
; I  .b  =   head_neck_f
; I  .ne =   I.b  shi( vect arm_r )
; I      =   I.h    +++    I.ne
);

Dd( i019 )( X_any  )( Y_NORM )( % s027; k026
;
	iwe = iwe\032;
;
; I  .h  =   ip\001
; I  .b  =   ip\176  Scaled( ($ 5) / idy\176 )  |< 90
; I  .c  =   |. ($ 1.5)  ysh( -($ 1.5)/2  -+  0 )
; I  .x  =   I.b  ysh( ~.?.y_s  -+  ($ 1.5) )
; I  .y  = ( I.c    +++    I.x )  |> arm_body_angle
; I  .z  =   I.y  Scaled( ( xpart hand_r -+ ie ) / (I.y.?.x_e ) )
; I  .ne =   I.z  shi( OQ  -+  hand_r )
; I      =   I.h    +++    I.ne
);

Dd( i020 )( X_any  )( Y_NORM )( % s028; k027
; I  .h  =   ip\019
;
	iwe = iwe\019;
;
; I  .s  =   ip\003.s
; I      =   I.h    +++    I.s
);

Dd( i021 )( X_any  )( Y_NORM )( % s025; k025
;
	iwe = iwe\032;
;
; I  .h  =   ip\001
; I  .b  =   ip\166\4.n  ysh( -($ 4)/2  -+  0 )
; I  .x  =   I.b  |> arm_body_angle  scx( xpart hand_r -+ ie )
; I  .ne =   I.x  shi( OQ  -+  hand_r )
; I      =   I.h    +++    I.ne
);

Dd( i022 )( X_any  )( Y_NORM )( % s; k
;
	iwe = iwe\032;
;
; I  .h  =   man_con_bridge
; I  .b  =   ip\176\3.3
; I  .y  =   I.b  |> arm_body_angle
; I  .z  =   I.y  Scaled( ( xpart hand_r_con_bridge -+ ie ) / ( I.y.?.x_e ) )
; I  .ne =   I.z  shi( OQ  -+  hand_r_con_bridge )
; I      =   I.h    +++    I.ne
);

Dd( i023 )( X_any  )( Y_NORM )( % s029; k028
;
	iwe = iwe\032;
;
; I  .h  =   ip\001
; I  .b  =   ip\177\3.5.x
; I  .x  =   I.b  |> arm_body_angle  scx( xpart hand_r  -+  ie )
; I  .ne =   I.x  shi( OQ  -+  hand_r )
; I      =   I.h    +++    I.ne
);

Dd( i024 )( X_SYM  )( Y_NORM )( % s; k029
; I  .h  =   ip\023
; I      =   I.h    +++    I.h ||
;
	iwe = !! ie\023;
;
);

Dd( i025 )( X_any  )( Y_NORM )( % s031; k031
; I  .h  =   man_con_bridge
; I  .b  =   |. idy
; I  .e  =   I.b  xsh( OQ  -+  hand_r_con_bridge )
; I      =   I.h    +++    I.e
;
	iwe = ( iw_base, xpart hand_r_con_bridge );
;
);

Dd( i026 )( X_any  )( Y_NORM )( % s032; k032
;
	iwe = iwe\025  +  !! ( split_distance_default  +  0 );
;
; I  .h  =   ip\025
; I      =   I.h    +++    ii_ii  splitted
);

Dd( i027 )( X_any  )( Y_NORM )( % s034; k034
;
	iwe = iwe\032;
;
; I  .h  =   ip\001
; I  .e  =   R_bow_narrow  xsh( rx R_bow_narrow  -+  ie )
;
	Pairp  PP = jet( hand_r, arm_body_angle )  Intersectionpoint_right  I.e;
;
; I  .c  =   ++++ ( hand_r -- PP )
; I      =   I.h   +++    I.e    +++    I.c
);

Dd( i028 )( X_any  )( Y_NORM )( % s035; k035
;
	iwe = ( iw_base, xpart hand_r_con_bridge  +  rrx R_bow_narrow );
;
; I  .h  =   ip\025
; I  .e  =   R_bow_narrow  xsh( rx R_bow_narrow  -+  ie )
; I  .c  =   ++++ ( ( ie\025, 0 )  --  iEN )
; I      =   I.h    +++    I.e    +++    I.c
);

Dd( i029 )( X_SYM  )( Y_NORM )( % s036; k036
; I  .h  =   ip\028
; I      =   I.h    +++    I.h ||
;
	iwe = !! ie\028;
;
);

Dd( i030 )( X_any  )( Y_NORM )( % s038; k038
;
	iwe = iwe\032;
;
; I  .h  =   ip\001
; I  .b  =   arm_l_f
; I  .e  =   I.b  xsh( hand_l  -+  hand_r )
; I  .c  =   ip\261  ysh( in\261 -+ 0 )  scx 2( 2 xpart hand_r  -+  ie )
; I  .ne =   I.c  shi( OQ  -+  ( neck_bot  xsh 2 arm_width ) )
; I      =   I.h    +++    I.e    +++    I.ne
);

Dd( i031 )( X_any  )( Y_NORM )( % s039; k039
;
	iwe = iwe\032;
;
	Numer  hh  =  $ 6.0  +  oval_corr;
;
; I  .h  =   man
; I  .b  =   oval_medium. hh         % 6.0 + 0.2: fight optical illusion
; I  .c  =   oval_medium. 1/2 hh
;
	Pairp  CC  =  ( ie - I.b.?.x_e, $ 1.5 );
	Path   p   =  ( ppath I.b )  shi( OQ  -+  CC );
	Pairp  MM  =  hand_r_bridge_jet  first_intersection  p;
	Path   br  =  hand_r  --  MM;
;
; I\1    =   I.h    +++    I.b  shi( OQ  -+  CC )    +++    br
; I      =   I\1    +++    I.c  shi( OQ  -+  CC )
);

Dd( i032 )( X_any  )( Y_NORM )( % s041; k040
; I  .h  =   ip\001
; I  .b  =   ip\328  scy $ 6
; I  .x  =   I.b  shi( -rx I.b  -+  xpart hand_r_con_bridge, $ 1.5 )
; I  .e  =   hand_r_bridge    +++    I.x
; I      =   I.h    +++    I.e
;
	iwe = ( iw_base, xpart hand_r_con_bridge  +  rrx I.b );
;
);

Dd( i033 )( X_any  )( Y_NORM )( % s040; k
; I  .a  =   ip\032
; I  .b  =   ip\031\1  ||
; I      =   I.a    +++    I.b
;
	iwe = ( -ie\031, ie\032 );
;
);

Dd( i034 )( X_any  )( Y_NORM )( % s042; k041
; I  .h  =   ip\032
;
	iwe = iwe\032;
;
; I  .b  =   |. $ 4  shi( ( 0, +$ 2 ) -+ ( ie - rx ip\032.b, in - $ 0.5 ) )
; I      =   I.h    +++    I.b
);

Dd( i035 )( X_any  )( Y_NORM )( % s043; k042
; I  .h  =   ip\032
;
	iwe = iwe\032;
;
	Pairp  XX  =  ( ie\032, $ 3.2 );
	Pairp  YY  =  XX  xsh -rrx ip\032.b;
	Path    p  =  YY { Dir 100 }  ..  { Dir 80 } XX;
;
; I  .b  =   ++++ p
; I  .c  =   ( I.b, ip\032.x ) ''( 2, 0, ( 1/3[ YY, XX ], 1/3[ XX, YY ] ) )
; I  .x  =   I.b    +++    I.c
; I      =   I.h    +++    I.x
);

Dd( i036 )( X_any  )( Y_NORM )( % s037; k037
;
	iwe = ( iw_base, xpart hand_r_con_bridge + 0.5 idx\216 );
;
; I  .h  =   man_con_bridge
; I  .b  =   ip\216  xsh( iw\216  -+  0 )  Scaled 0.5
; I  .e  =   I.b  shi( OQ  -+  ( xpart hand_r_con_bridge, $ 1.5 ) )
; I      =   I.h    +++    I.e
);

Dd( i037 )( X_any  )( Y_NORM )( % s024; k
;
	iwe = iwe\032;
;
	Pairp  NW  =  ( ie - $ 3.0, $ 4.5 );
	Pairp  NE  =  ( ie - $ 0.5, $ 4.5 );
	Pairp  SE  =  ( ie        , $-1.5 );
	Path   p   =  NW { down }  ...  ( ie - $ 2.1, 0 )  ...  { Dir 110 } SE;
	Path   q   =  NE { down }  ...  ( ie - $ 0.4, 0 )  ...  { Dir 160 } SE;
	Path   r   =  p  &  reverse q  --  cycle;
;
	Pairp  PP  =  hand_r_bridge_jet  Intersectionpoint_right  p;
;
; I  .h  =   man
; I  .b  =   ++++ r
; I  .e  =   I.b    +++    I.b ''( 5, 90, ( 0.16[NW, SE], 0.80[NW, SE] ) )
; I  .o  =   ++++ (  hand_r -- PP )
; I      =   I.h    +++    I.o    +++    I.e
);

Dd( i038 )( X_SYM  )( Y_NORM )( % s022; k022
; I  .h  =   ip\001
; I  .b  =   ip\176  Yscaled( ($ 4) / idy\176 )  Xscaled( ($ 1) / idx\176 )
; I  .o  =   I.b  |>90  ysh( OQ  -+  0.58[ hand_l, crotch ] )
; I      =   I.h    +++    I.o
;
	iwe = !! max( ie_base, ($ 4)/2 );
;
);

Dd( i039 )( X_EQB  )( Y_NORM )( % s; k
;
	iwe = iwe_base;
;
; I  .h  =   ip\001
; I  .b  =   arm_r_f
; I  .se =   I.b  shi( vect body )
; I      =   I.h    +++    I.se
);

Dd( i040 )( X_any  )( Y_NORM )( % s020; k019
; I  .h  =   ip\001
; I  .b  =   rectangle $( 3, 1.2 )  |<leg_angle
; I  .se =   I.b  shi( OQ  -+  Point 0.6 of leg_r )
; I      =   I.h    +++    I.se
;
	iwe = ( iw_base, max( ie_base, I.se.?.x_e ) );
;
);

Dd( i041 )( X_any  )( Y_NORM )( % s021; k020
;
	iwe = iwe\032;
;
	Pairp  AA  =  0.5[ foot_r, iES ]  ysh 0.6 xpart( foot_r -+ iES );
;
; I  .h  =   ip\001
; I  .sse=   ++++ ( foot_r -- AA -- iES )
; I      =   I.h    +++    I.sse
);

Dd( i042 )( X_EQB  )( Y_NORM )( % s; k021
;
	iwe = !! $ 3;
;
; I  .h  =   head_body_arms
;
	PAIRP  axis_l;
	axis_l  =  whatever[ foot_l, crotch ];
	iw  -+  xpart axis_l  =  is  -+  ypart axis_l;
;
	Numer  radius  =  iw -+ xpart axis_l;
;
	Pairp  PP  =  ( 0, +1/3 radius );
	Pairp  QQ  =  ( 0, -1/3 radius );
;
; I  .b  =   circle( 2 radius )
; I  .d  =   |. 2 radius
; I  .x  =   I.d    +++    I.d  |>60    +++    I.d  |<60
; I  .y  =   I.b  ''( 2, 90-leg_angle, ( PP |<leg_angle, QQ |<leg_angle ) )
					% 3 stripes are to dark
;
	Pairp RR = axis_l + radius * unitvector( axis_l -+ crotch );
	Figure  my_legs      =  ++++ ( RR  --  crotch  --  RR || );
;
; I  .sw = ( I.b    +++    I.x )  shi( axis_l     )
; I  .se = ( I.b    +++    I.y )  shi( axis_l  || )
; I      =   I.h    +++    my_legs     +++    I.sw    +++    I.se
);

Dd( i043 )( X_SYM  )( Y_NORM )( % s019; k017
;
	iwe = !! $ 3;
;
; I  .h  =   head_body_arms
;
	Numer  rayus  = $ 0.8;
;
; I  .b  =   rectangle( idx, 2 rayus )
;
	Pairp   RR = leg_l  where_y  ( is + 2 rayus );
	Figure  my_legs      =  ++++ ( RR  --  crotch  --  RR || );
;
; I  .s  =   I.b  ysh( -rayus  -+  is )
; I      =   I.h    +++    my_legs    +++    I.s
);

Dd( i044 )( X_any  )( Y_NORM )( % s; k
; I  .a  =   head_body_arms
;
	Pairp  AA  =  crotch;
	Pairp  BB  =  AA  + $( -2, -2 );
	Pairp  DD  =  ( xpart BB , is );
	Pairp  CC  =  DD  + $( +1, +1 );
;
	Path    my_leg_l =  AA  ---  BB  ---  CC  ---  DD;
	Figure  my_legs  =  ++++ ( my_leg_l `  &  my_leg_l || );
;
; I  .h  =   I.a    +++    my_legs
; I  .e  =   ip\032.e
; I      =   I.h    +++    I.e
;
	iwe = ( min( -arm_width, xpart BB ), ie\032 );
;
);

			begingroup %% i045 - i046

Cc( i045, i046 )( %%
	Nangle arm_angle =  110;
	Numer  arm_width =  idx_base;                % $ 14/3
;
	Pairv  arm_v     =  arm_width * ( 1, cotd arm_angle );
%
	Pairp  neck_bot  =  ( iw_base, in_base  -  $ 2 );
	Pairp  hand      =  neck_bot + arm_v;
%
	Path   arm       =  neck_bot -- hand    ;
); %%

Dd( i045 )( X_any  )( Y_NORM )( % s; k
; I  .ne =   ip\032.e  ysh( hand_r  -+  hand )
; I  .e  =   arm    +++    I.ne
;
	iwe = iwe\032;
;
	PAIRP  AA, CC, EE, GG, II, KK, RR, TT, VV, XX;
	PATH   p , q ;

	AA  = iWN;
	CC  = iWS  ysh +$ 1.5;
	EE  = iWS  xsh +$ 1.5;
	GG  =  KK  + ( -$ 1.6, +$ 4.0 );
	II  =  KK  + ( -$ 0.8, +$ 0.0 );
	KK  = iWS  xsh +$ 7.5;
;
	p   =  AA  --  CC { down }
	.      ...  { right } EE
	.      .. tension 1.9 ..  { curl 0.1 } GG { curl 0.1 }
	.      ...  { curl 0.1 } II
	.      ...  {    right } KK;
;
	RR  =  Point 2.6 of p;
	TT  =  KK  + ( +$ 0.3, $ 2.6 );
	VV  =  KK  + ( -$ 2.9, $ 0.7 );
	XX  =  KK  xsh -$ 2.7;

	q   =  RR  ---  TT
	.      .. tension 3.0 ..  { curl 0.1 } VV { curl 0.1 }
	.      .. tension 2.0 ..  XX;
;
; I  .h  =   p     +++    q
; I      =   I.h   +++    I.e
);

Dd( i046 )( X_any  )( Y_NORM )( % s; k
;
	iwe = ( iw\033, ie\045 );
;
; I  .h  =   ip\045
; I  .b  =   ip\177\3.5.x  |< arm_angle  scx( iw\033 -+ iw\045 )
; I  .w  =   I.b  shi( OQ  -+  neck_bot )
; I      =   I.h    +++    I.w
);

			endgroup ; %% i045 - i046

		endgroup ; %% i001 - i015, i418, i016 - i046

		begingroup %% i047 - i048

Cc( i047, i048 )( %%
	Pair     iwe_base = !! $ 3.25;
;
	PAIRP  AA, CC, EE, GG, II;
	PATH   p , q , r , pqr;

	AA  =  (     iw_base,     is_base );
	CC  =  ( -$ 1.75    , 1/3 is_base );
	EE  =  ( -$ 0.25    ,     is_base );
	GG  =  (     ie_base,    $ 1      );
	II  =  ( -$ 0.75    ,     in_base );

	p   =  AA  --  CC  --  EE;
	q   =  EE  ..  GG { up }  ..  { Dir -80 } II;
	r   =  II { Dir 175 }  ..  Point 1.3 of q;
	pqr =  p  &  q  &  r;
); %%

Dd( i047 )( X_any  )( Y_NORM )( % s199; k193
;
	iwe = iwe_base;
;
; I      =   ++++ pqr
);

Dd( i048 )( X_any  )( Y_NORM )( % s200; k194
; I  .h  =   ip\047
;
	PAIRP  ZZ, VA, VO, WW, XX;

	ZZ  =  $( -9, 1 );
	VO  =  ( $ 2.75, is );
	VA  =  ( ZZ -- VO )  Intersectionpoint_right  q;
	WW  =  q  where_y   $ 1.0;

	Numer     l  = length( VA  -+  VO );
	Nangle  alf  =  Angle( ZZ  -+  VO );
	Nangle  bet  =  Angle( ZZ  -+  WW );
;
; I      =   I.h    % +++
	for  gam = alf, 1/3[alf, bet], 2/3[alf, bet], bet :
		hide( XX  :=  jet( ZZ, gam )  Intersectionpoint_right  q; )
		+++   ( XX  --  good.rt( XX  +  l * Dir gam ) )
	endfor
;
	iwe = ( iw\047, xpart( ( fig_right I ).?.omega ) );
;
);

		endgroup ; %% i047 - i048

Dd( i049 )( X_any  )( Y_NORM )( % s048; k
;
	PAIRP  OO , NE , NN , NW , ESE, SE , SSE, SS , WSW;
	PATH   p , q , r , pqr;

	OO   =  $ (  0  ,  0   );
	NE   =  $ (  1.5,  4.0 );
	NN   =  $ (  0.0,  6   );
	NW   =  $ ( -1.1,  4.5 );
	ESE  =  $ (  0.9, -3   );
	SE   =  $ (  1.5, -6   );
	SSE  =  $ (  0.6, -5   );
	SS   =  $ ( -0.4, -6   );
	WSW  =  $ ( -1.5, -5.6 );
;
	p   =  OO { (OO -+ NE) |> 8 }  ..  NE { up }  ..  { left } NN;
	q   =  NN { left }  ..  NW { down }  ..  OO  ..  ESE  ..  SE;
	r   =  SE  ---  SSE  ---  SS  ---  WSW;
	pqr =  p  &  q  &  r;
;
; I  .h  =   ++++ pqr
; I  .o  =   I.h  ''( 3, 45, ( 3/16[ NN, OO ], 11/16[ NN, OO ] ) )
; I      =   I.h    +++    I.o
;
	iwe = ( xpart WSW, xpart SE );
;
);

Dd( i050 )( X_any  )( Y_NORM )( % s044; k043.288
;
	iwe = isn;
;
	Numer  body_l  =  7/10 idx;
	Numer  head_l  =  3/10 idx;
;
	PAIRP  PP , PQ , QQ , RR , SS , TT , UU , VV , WW , XX , YY , ZZ ,
	.      DD , AA , BB , CC;
	PATH   p , q , r;

	PP  =  ( iw             , -$ 2   );
	PQ  =  ( iw + 5/6 body_l, -$ 2   );
	QQ  =  ( iw +     body_l, -$ 1.8 );
	RR  =  ( xpart QQ + 1/3 head_l,  $ 1   );
	SS  =  (           $ 4.3,  $ 2.2 );
	TT  =  (           $ 5.0,  $ 2.0 );
	UU  =  ( ie             ,  $ 2.5 );
	VV  =  (           $ 5.4,  $ 4   );
	WW  =  (           $ 4.7,  in    );
	XX  =  (           $ 3.5,  $ 4.3 );
	YY  =  ( iw +     body_l,  $ 2.3 );
	ZZ  =  ( iw + 5/6 body_l,  $ 2   );
	DD  =  ( iw             ,  $ 2   );

	p  =  PP  --  PQ {right}  ...  QQ
	.    ..  RR  ..  {curl 0.5} SS {curl 0.5}  ..  TT ..   { up } UU  .. VV
	.    ..  {curl 0.5} WW {curl 0.5}  ..  XX  ..  YY .. { left } ZZ  -- DD;
	q  =                       RR  --  YY  --  QQ  --  ( xpart QQ, is );

	AA  =  Point  0.6  of Subpath  WW -- YY  of p;
	BB  =  Point  1.3  of Subpath  WW -- YY  of p;
	CC  =  ( xpart YY , ypart AA );

	r  =  AA  --  CC  --  BB;

; I  .e  =   p    +++    q    +++    r
; I  .o  =   p  ''( 5, 0, ( PP xsh 1/6 body_l, PP xsh 5/6 body_l ) )
; I  .w  =   |. idy  xsh iw

; I  .c  =   rect_open  ( 3/5 body_l, $ 4 )
; I  .s  =   I.c  shi( ( 0, ($ 4) )/2  -+  ( iw + 1/2 body_l, -($ 4)/2 ) )
; I      =   I.w     +++    I.e    +++    I.s    +++    I.o
);

Dd( i051 )( X_any  )( Y_NORM )( % s080; k073
;
	Pairp  RA   =  $ (  1.5,  5.5 );
	Pairp  LA   =  $ ( -1  ,  6   );
	Pairp  RO   =  $ (  1.5, -6   );
	Pairp  LO   =  $ ( -2.5, -6   );

	Path   rlr  =  RA { Dir  -95 } .. { Dir  135 } RO;
	Path   lrl  =  LA { Dir  135 } .. { Dir -125 } LO;

	NUMER  la, ra, lo, ro;
	( la, ra ) =    rlr      intersectiontimes    lrl    ;
	( lo, ro ) =  ( rlr ` )  intersectiontimes  ( lrl ` );

	Path   l  =  subpath ( la, length rlr - lo ) of  rlr;
	Path   r  =  subpath ( ra, length lrl - ro ) of  lrl;

	Path   ne_p  =  RA  ..  { Dir -125 } point 0.2 of r;

	Path   se_p  =  ( subpath( 0, lo ) of ( rlr ` ) )
	.                                 shi( fin ~  -+  point 0.85 of r );

	Path   sw_q  =  ( subpath( 0, ro ) of ( lrl ` ) )
	.                                 shi( fin ~  -+  point 0.90 of l );
	Pairp  VV    =  beg sw_q  +  $( -0.5, 0.5 );
	Path   sw_p  =  LO  --  VV  --  subpath( 0.15, 1 ) of sw_q;

	Numer  z   =  0.15;
	Path  nw_a = ( subpath( 0, ra ) of lrl ) shi( fin ~ -+ point  z of l );
	Path  nw_b = ( subpath( 0, ra ) of lrl ) shi( fin ~ -+ point 2z of l );
	Path  nw_c = ( subpath( 0, 2z ) of l   ) shi( beg ~ -+  LA );

	Pairp  RR  = 1/2[ beg l, fin l ] + $( 0, 1.5 );
	Pairp  SS  = 1/2[ beg l, fin l ] - $( 0, 1.5 );

; I  .w  =   ++++ rlr
; I  .e  =   ++++ lrl
; I  .o  =   I.w    +++   I.e    +++   ( I.w, I.e ) ''( 3, 70, ( RR, SS ) )
; I  .nw =   nw_a   +++   nw_b   +++   nw_c
; I\0    =   I.o    +++   ne_p   +++   se_p    +++    sw_p    +++    I.nw
;
	iwe = !! $ 3;
;
; I\1    =   I\0  xsh( xpart VV  -+  0 )
; I\2    =   I\1  Xscaled( idx / ( xpart VV  -+  xpart beg se_p ) )
; I      =   I\2  xsh( 0  -+  iw )
);

Dd( i052 )( X_any  )( Y_NORM )( % s081; k074
; I  .h  =   |. idy
; I  .b  =   ip\051
; I      = ( I.h    +-("")++    I.b )  connected( -$ 0.8, +$ 0.8 )
;
	iwe = ( xpart( (fig_left fig_left I).?.alpha ), ie\051 );
;
);

Dd( i053 )( X_any  )( Y_NORM )( % s082; k075.168
;
	iwe = !! $ 4.5;
;
; I  .a  =   oval_medium. $$
; I  .h  =   I.a  xsh( xpart Point 3 of I.a  -+  iw )
;
	Pairp  PP  =  Point 0.6 of I.h;
	Pairp  QQ  =  jet( PP,       35 )  where_y  in;
	Pairp  RR  =  jet( QQ, 180 - 35 )  where_x  ie;
	Path   pne = PP  --  QQ  --  RR;
;
; I  .ne =   ++++ pne
; I  .se =   I.ne  |:
; I      =   I.h    +++    I.ne    +++    I.se
;
	Path   px  = pne  shi( PP  -+  OQ );     % for i181
	Path   py  = px  |:;
	Path   pz  = px `  &  py;
;
; I  .z  =   ++++ pz                         % for i181
);

Dd( i054 )( X_any  )( Y_NORM )( % s085; k076
;
	iwe = !! $ 4;
;
; I  .h  =   oval_medium. $ 6
;
	Pairp  WW = Point 3 of I.h;
	Pairp  CC = OQ  xsh( WW -+ iWO );
;
; I  .o  =   I.h  xsh( OQ -+ CC )
; I  .n  = ( I.o, N_line ) ''( 3, CC, ( iWN, iWN + 2(iWO -+ CC) ) )
; I  .s  =   I.n  |:
; I  .w  =   I.o    +++    I.n   +++    I.s
;
	Pairp  PP = Point 0.85 of I.o;
;
; I  .ne =   ++++ ( PP { Dir 80 }  ..  { up } iEN )
; I  .se =   I.ne  |:
; I      =   I.w    +++    I.ne    +++    I.se
;
; I  .c  =   i_mini  xsh( OQ -+ CC )     % for i055
);

Dd( i055 )( X_any  )( Y_NORM )( % s; k
; I  .h  =   ip\054
;
	iwe = iwe\054;
;
; I  .c  =   ip\054.c
; I      =   I.h    +++    I.c
);

Dd( i056 )( X_any  )( Y_NORM )( % s090; k083
;
	iwe = !! $ 2.75;
;
	Numer  hh  =  $ 4;
;
; I  .a  =   oval_medium. hh
;
	Pairp  WW  =  Point 3 of I.a;
;
; I  .h  =   I.a  xsh( WW  -+  iWO )  ysh( -hh/2  -+  0 )
;
	Pairp  PP  =  3/4 WW  xsh( WW  -+  iWO );
	Pairp  NN  =  Point 0 of I.h;
;
	Path   pa  =  Subpath( 0, 1 ) of I.h;
;
; I  .n  =   I.h    +++    ( ++++ pa, N_line ) ''( 4, PP, ( NN, iEN ) )
; I  .s  =   I.n  |:
; I      =   I.s    +++    I.n
);

Dd( i057 )( X_any  )( Y_NORM )( % s089; k082
;
	iwe = !! $ 3;
;
	Numer  h = $ 6;
	Numer  my_stroke_distance = 0.70 stroke_distance_y;
;
; I  .a  =   oval_narrow. h
; I  .x  =   I.a  xsh $ 0.4
; I  .o  =   I.x    +++    I.x  ''( 3, 70, ( (0, -0.22 h), (0, +0.22 h) ) )
;
	Numer  wl   =  my_stroke_distance / sind 45;

	Pairp  Lx   =  I.x  first_where_y  wl/2;
	Pairp  Ly   =  ( 0.40[ iw, xpart Lx ], ypart Lx - $ 0.8 );
	Pairp  Lz   =  ( iw, ypart Lx );
	Path   lu   =  Lx  --  Ly  --  Lz;
;
; I  .nw =   ++++ lu                                    % for i077
; I  .sw =   I.nw  ysh -wl
; I  .w  =   I.sw     +++    I.nw
;
	Numer  wr   =  my_stroke_distance / sind 45;

	Pairp  Rx   =  I.x  last_where_y  wr/2;
	Pairp  Ry   =  jet( Rx, 45 )  where_x  ie;
	Path   ru   =  Rx  --  Ry;
;
; I  .ne =   ru     +++    ru  ysh -wr
; I  .se =   I.ne  |:
;
; I  .h  =   I.o    +++    I.w
; I  .n  = ( I.h    +++    I.ne )  ysh( +h/2  -+  in )
; I  .s  = ( I.h    +++    I.se )  ysh( -h/2  -+  is )
; I      =   I.s    +++    I.n
);

		begingroup %% i058 - i075

Cc( i058, i075 )( %%
	Pair   iwe_base = !! $ 2.75;

	Numer  body_l        = $ 9.5;
	Numer  fin_over_tail = $ 1  ;

	Pairp  body_a  =  ( 0, in_base );
	Pairp  body_o  =  body_a - ( 0, body_l );
	Pairp  body_m  =  1/2[ body_o, body_a ];

	Nangle  alf    =  38;  % 43.60222 would result by using oval_narrow
	Pairp   XY = body_l * ( 1/2.5, 1 )/2;

	Path  bod  =
		. (  ( 0, +ypart XY )    {Dir(180-alf)} .. ( +xpart XY, 0 )
		.                     .. {Dir(180+alf)}    ( 0, -ypart XY )  )
		& (  ( 0, -ypart XY )    {Dir( 0 -alf)} .. ( -xpart XY, 0 )
		.                     .. {Dir( 0 +alf)}    ( 0, +ypart XY )  );

	Path  body =
		subpath( 0, 3 ) of bod
		.. controls postcontrol 3 of bod  and  precontrol 4 of bod .. cycle;

	Nangle  tail_angle = 180  +  alf;

	Pairp   tail_a    =  body_o;
	Pathj   tail_jet  =  jet( tail_a, tail_angle );
	Pairp   tail_o    =  tail_jet  Intersectionpoint_right  S_line;

	Pairp   fin_c     =  OQ;
	Pairp   fin_o     =  ( iw_base, ypart body_o + fin_over_tail );
	Nangle  fin_angle =  Angle( fin_c  -+  fin_o );
); %%

Dd( i058 )( X_SYM  )( Y_NORM )( % s; k
;
	iwe = !! good.x $ 3.5;
;
; I  .o  =   ++++ body
; I  .n  = ( I.o, N_line )  ''( 2, OQ, ( iWN, iEN ) )
; I  .s  =   I.n  |:
; I      =   I.s    +++    I.o    +++     I.n
);

Dd( i059 )( X_SYM  )( Y_NORM )( % s055; k050
;
	iwe = iwe_base;
;
; I  .o  =   ip\058.o  ysh ( +body_l/2  -+  in )
;
	Path   fin_pth =  fin_c  --  fin_o;

	Pairp  fin_a   =  fin_pth  Intersectionpoint_right  I.o;

	Path   tail    =  tail_o --  tail_a  --  tail_o ||;
	Path   fin_sw  =  fin_a  --  fin_o;
;
; I  .we =   fin_sw    +++    fin_sw ||
; I  .sn =   I.o       +++    tail
; I      =   I.sn      +++    I.we
);

Dd( i060 )( X_SYM  )( Y_NORM )( % s056; k051
;
	iwe = !! ( ie_base  +  split_distance_default  +  0 );
;
; I      =   ip\059    +++    ii_ii  splitted
);

Dd( i061 )( X_EQB  )( Y_NORM )( % s057; k052
; I  .a  =   ip\059
; I  .b  =   ip\197\3
;
	Numer  raxus_a = ( rx I.a  +  rx I.b )  +  1/2 distance_x_low;
;
	iwe = !! ( raxus_a  +  split_distance_default  +  0 );
;
; I  .w  =   I.a  xsh( -rx ~  -+  -raxus_a )
; I  .e  =   I.b  xsh( +rx ~  -+  +raxus_a )
; I  .x  =   I.w    +++    I.e
; I      =   I.x    +++    ii_ii  splitted
;
  if  idx > dx_high :
; I     :=   reduce_width( i___i, ip\059, ip\197\3, i___i )
;
	iwe := !! ( dx_high/2 );
	isn := I.?.sn;
;
  fi
);

Dd( i062 )( X_any  )( Y_NORM )( % s058; k053
;
	iwe = iwe\059  +  !! split_distance_default
	.              +  ( -rrx L_parenthesis, +rrx ip\295\1.e );
;
; I      =   ip\059    +++   ( L_parenthesis   +++   ip\295\1.e )  splitted
);

Dd( i063 )( X_EQB  )( Y_NORM )( % s060; k055
; I  .a  =   ip\078
; I  .b  =   ip\059
;
	Numer  raxus_a = ( idx\078  +  idx\059 )/2  +  distance_x_low/2;
;
	iwe = !! ( raxus_a  + split_distance_default  + rrx L_parenthesis );
;
; I  .w  =   I.a  xsh( iw\078  -+  -raxus_a )
; I  .e  =   I.b  xsh( ie\059  -+  +raxus_a )
; I  .x  =   I.w    +++    I.e
; I      =   I.x    +++    L_R_parenthesis  splitted
;
  if  idx > dx_high :
; I     :=   reduce_width( L_parenthesis, ip\078, ip\059, R_parenthesis )
;
	iwe := !! ( dx_high/2 );
	isn := I.?.sn;
;
  fi
);

Dd( i064 )( X_EQB  )( Y_NORM )( % s059; k054
; I  .a  =   ip\059
; I  .b  =   ip\078
;
	Numer  raxus_a = ( idx\059  +  idx\078 )/2  +  distance_x_low/2;
;
	iwe = !! ( raxus_a  +  split_distance_default  +  rrx L_parenthesis );
;
; I  .w  =   I.a  xsh( iw\059  -+  -raxus_a )
; I  .e  =   I.b  xsh( ie\078  -+  +raxus_a )
; I  .x  =   I.w    +++    I.e
; I      =   I.x    +++    L_R_parenthesis  splitted
;
  if  idx > dx_high :
; I     :=   reduce_width( L_parenthesis, ip\059, ip\078, R_parenthesis )
;
	iwe := !! ( dx_high/2 );
	isn := I.?.sn;
;
  fi
);

Dd( i065 )( X_SYM  )( Y_ROOF )( % s065; k060
; I  .h  =   ip\059
; I\1    =   I.h  Transformed ysc_shrink
; I      =   I\1  roofed( r_acute )
;
	iwe = !! max( ie_base, rx fig_right I );
;
);

Dd( i066 )( X_SYM  )( Y_ROOF )( % s066; k061
;
	iwe = !! ( ie\065  +  split_distance_default  +  0 );
;
; I      =   ip\065    +++    ii_ii  splitted
);

Dd( i067 )( X_SYM  )( Y_NORM )( % s067; k062.180
; I  .h  =   ip\059
; I  .n  =   ip\059.we  Reflectedabout  ( body_m, body_m + right )
; I      =   I.h    +++    I.n
;
	iwe = iwe_base;
;
);

Dd( i068 )( X_SYM  )( Y_NORM )( % s068; k063
;
	iwe = !! ( ie\067  +  split_distance_default  +  0 );
;
; I      =   ip\067    +++    ii_ii  splitted
);

Dd( i069 )( X_SYM  )( Y_NORM )( % s069; k062.236
;
	iwe = !! $ 3.25;
;
; I  .h  =   ip\059
;
	Pairp  CC = body_m + $( 0, 1 );
;
; I  .nw = ( I.h, N_line )  ''( 2, CC, ( iWN, 0.5[iWN, iON] ) )
; I  .ne =   I.nw  ||
; I      =   I.h    +++    I.nw    +++    I.ne
);

Dd( i070 )( X_SYM  )( Y_NORM )( % s061; k056
; I  .h  =   ip\059
; I  .o  =   i_mini  ysh( OQ  -+  body_m )
; I      =   I.h    +++    I.o
;
	iwe = iwe_base;
;
);

Dd( i071 )( X_SYM  )( Y_NORM )( % s062; k057
;
	iwe = !! ( ie\070  +  split_distance_default  +  0 );
;
; I      =   ip\070    +++    ii_ii  splitted
);

Dd( i072 )( X_EQB  )( Y_NORM )( % s063; k058
; I  .h  =   ip\059
; I  .o  =   ip\059.o
; I  .d  =   I.o  ''( 1, fin_angle, ( body_m ) )
; I      =   I.h    +++    I.d
;
	iwe = iwe_base;
;
);

Dd( i073 )( X_EQB  )( Y_NORM )( % s064; k059
;
	iwe = !! ( ie\072  +  split_distance_default  +  0 );
;
; I      =   ip\072    +++    ii_ii  splitted
);

Dd( i074 )( X_SYM  )( Y_NORM )( % s070; k064
;
	iwe = !! $ 4.25;
;
; I  .sn =   ip\059.sn
; I  .o  =   ip\059.o
;
	Pairp PP  =  Point  2.33  of I.o;
	Pairp QQ  =  Point  3     of I.o;
	Pairp WW  =  jet( QQ, fin_angle )  where_x  iw;
	Path   p  =  Subpath( 2, 4 ) of I.o;
	Path   q  =  line( iOS, WW );
;
; I  .sw =   ( ++++ p, ++++ q ) ''( 3, fin_angle, ( PP, WW ) )
; I  .se =   I.sw  ||
; I  .h  =   I.sw    +++    I.se
; I      =   I.sn    +++    I.h
);

Dd( i075 )( X_EQB  )( Y_ROOF )( % s053; k048
; I  .sn =   ip\059.sn
; I  .o  =   ip\059.o
; I  .x  =   I.o ''( 4, 45, ( 0.23[body_a, body_o], 0.23[body_o, body_a] ) )
; I  .h  =   I.sn    +++    I.x
; I\1    =   I.h  Transformed ysc_shrink
; I      =   I\1  roofed( r_acute, idx\065 )
;
	iwe = !! max( -xpart tail_o, rx I.o, rx fig_right I );
;
);

		endgroup ; %% i058 - i075

Dd( i076 )( X_any  )( Y_NORM )( % s076; k066.531
;
	PAIRP  PP , QQ , RR , SS , TT , UU , VV , ZZ , BB , CC , DD , WW;

	PP  =  (  -$ 6  ,   $ 4    ); % iw
	QQ  =  (  -$ 5  ,   $ 5    );
	RR  =  (  -$ 4  ,   $ 6    ); % in
	SS  =  (  -$ 3  ,   $ 5    );
	TT  =  (  -$ 2  ,   $ 2    );
	UU  =  (   $ 0  ,   $ 2.5  );
	VV  =  (   $ 2  ,   $ 2    );
	ZZ  =  (   $ 6  ,   $ 4    ); % ie

	BB  =  (  -$ 5  ,   $ 4    );
	CC  =  (  -$ 4  ,   $ 0    );
	DD  =  (   $ 0  ,  -$ 2    );
;
; I  .n  =   ++++ ( PP  ---  QQ  ..  RR {right}    ..  SS  ..  TT
.                                          ..  UU  ..  VV  ..  ZZ )
; I  .we =   ++++ ( PP  ---  BB  ..  CC  ..  DD { right }  ..  ZZ )
; I  .o  = ( ++++ ( Subpath TT .. VV of I.n ), I.we ) ''( 4, 170 )
;
	WW  =  VV  projection( 170 )  I.we;
;
; I  .e  =   ++++ interpath( 1/2, Subpath VV .. ZZ of I.n,
.                                 Subpath WW .. ZZ of I.we )
;
	Pairv  vlx   =  ( +($ 1.1), -($ 2.7) );
	Pairv  vly   =  ( -($ 1.1), -($ 1.3) );
	Numer  fac   =  min( abs cosd Angle vlx, abs cosd Angle vly );
	Numer  width =  0.60 stroke_distance_x / fac;
;
	PAIRP  GG, Lx, Ly, Lz, Rz, Ry, Rx;
	PATH   ll, rr;

	GG   =  DD;                   % directionpoint  right
	Lx   =  I.we  where_x  ( xpart GG - width/2 );
	Ly   =  jet( Lx, Lx + vlx )  where_y  ( is + abs ypart vly );
	Lz   =  Ly  +  vly;
	Rz   =  Lz  xsh width;
	Ry   =  Rz  -  vly;
	Rx   =  jet( Ry, Ry - vlx )  Intersectionpoint  I.we;
;
	ll   =  Lx  --  Ly  --  Lz;
	rr   =  Rx  --  Ry  --  Rz;
;
; I  .s  =   ll     +++    rr
; I      =   I.n    +++    I.we    +++    I.o    +++    I.e    +++    I.s
;
	iwe = isn;
;
);

		begingroup %% i077 - i081

Cc( i077, i081 )( %%

	Pair  iwe_base  =  !! $ 3;

	PAIRP  PP, QQ, RR, SS, UU, WW, Zp, Zq,
	.      Pw, BB, CC, DD, Fp, Fq, GG, Pa, Po;
	PATH   pe_common, pw_common, common_p;

	PP  =  ( ie_base - $ 3.7 , $   5.6  );
	QQ  =  ( ie_base - $ 2.0 , $   6    ); % in
	RR  =  ( ie_base - $ 0.8 , $   5.8  );
	SS  =  ( ie_base - $ 1.0 , $   4.7  );
	UU  =  ( ie_base - $ 0.0 , $   0.5  );
	WW  =  ( ie_base - $ 1.3 , $ - 3    );
	Zp  =  ( ie_base - $ 0.9 , $ - 6    ); % is
	Zq  =  ( ie_base - $ 2.4 , $ - 5.7  );

	Pw  =    PP;
	BB  =  ( ie_base - $ 2.5 , $   5.0  );
	CC  =  ( ie_base - $ 3.9 , $   0.5  );
	DD  =  ( ie_base - $ 2.5 , $ - 3    );
	Fp  =  ( ie_base - $ 2.9 , $ - 6    ); % is
	Fq  =  ( ie_base - $ 3.6 , $ - 5.7  );

	GG  =  ( xpart 1/2[ Fq, Zq ] , is_base );

	Pa  =  1/2[ SS, BB ];
	Po  =  1/2[ WW, DD ];

	pe_common = PP  --- QQ  --- RR  .. SS { down }  .. UU { down }  .. WW;
	pw_common = DD  ..  {up} CC  ..  BB    softjoin    BB  --  Pw;

	common_p = pw_common   &   pe_common;
); %%

Dd( i077 )( X_any  )( Y_NORM )( % s; k
;
	iwe = iwe_base;
;
	Path   p  =  Fp  ---  common_p  ---  Zp;
;
; I  .h  =   ++++ p
; I  .o  =   common_p  ''( 4, 60, ( 0.15[Pa, Po], 0.15[Po, Pa] ) )
;
; I  .x  =   ip\057.sw
; I  .y  =   ip\057.nw
;
	Pairp  SW  =  pw_common  where_y  ypart beg I.x;
	Pairp  NW  =  pw_common  where_y  ypart beg I.y;
;
; I  .sw =   I.x  scx( iw -+ xpart SW )  xsh( xpart fin ~  -+  iw )
; I  .nw =   I.y  scx( iw -+ xpart NW )  xsh( xpart fin ~  -+  iw )
;
; I  .w  =   I.sw   +++    I.nw
; I      =   I.h    +++    I.o    +++    I.w
);

Dd( i078 )( X_any  )( Y_NORM )( % s072; k066.188
;
	iwe = iwe_base;
;
	Path   pe_add    =  WW { ( WW -+ Zq ) |< 10 }  ..  Zq;
	Path   pe_local  =  pe_common  softjoin  pe_add;
;
	Path   pw_add    =  Fq { ( Fq -+ DD ) |> 10 }  ..  DD;
	Path   pw_local  =  pw_add  softjoin  pw_common;
;
	Path   ph =  pe_local  ..  {left} GG  ..  pw_local;
;
; I  .e  =   ++++ pe_local    % for i080
; I  .h  =   ++++ ph
; I  .o  =   ip\077.o
; I  .w  =   ip\077.w
; I      =   I.h    +++    I.o    +++    I.w
);

Dd( i079 )( X_any  )( Y_NORM )( % s; k
;
	iwe = iwe_base + $( 0, 2.5 );
;
	PAIRP  Ra, Rb, Rc, Rd, Re;

	Ra  =    RR                            ; % ( ie_base, 0 ) - $( 0.8, 5.8 )
	Rb  =  ( ie_base, 0 ) + $( 0.9 , 6.0  );
	Rc  =  ( ie_base, 0 ) + $( 1.8 , 5.6  );
	Rd  =  ( ie_base, 0 ) + $( 2.5 , 3.7  );
	Re  =  ( ie_base, 0 ) + $( 2.1 , 3.0  );
;
	Path   p  =  Ra  ..  Rb { right }  ..  Rc  ..  { down } Rd  ..  Re;
;
; I  .h  =   ip\078
; I  .ne =   ++++ p
; I      =   I.h    +++    I.ne
);

Dd( i080 )( X_any  )( Y_NORM )( % s077 (?); k070 (?)
;
	PAIRP  Ra, Rc, Re, Rg, Ri;
;
	iwe = ( iw_base, xpart Rg );
;
; I  .a  =   ip\078.e
;
	Path  r = Subpath( 3.52, 4.4 ) of I.a;

	Ra  =  ( ie_base, 0 ) + $( 2.1 ,  6.0  ); % in
	Rc  =  ( ie_base, 0 ) + $( 3.1 ,  3.4  );
	Re  =  ( ie_base, 0 ) + $( 2.1 ,  1.05 );
	Rg  =  ( ie_base, 0 ) + $( 3.5 , -1.0  ); % ie
	Ri  =  ( ie_base, 0 ) + $( 2.4 , -3.5  );

	Path  p  =                beg r { Dir   75 }
	.          .. { Dir  -15 }  Ra  { Dir  120 }
	.          .. { down     }  Rc  { down     }
	.          .. { Dir  210 }  Re  { Dir  130 }
	.          .. { down     }  Rg  { down     }
	.          .. { Dir  210 }  Ri  { Dir  -05 }
	.          .. { Dir  -85 } fin r;

	Path  q  =  r  &  p `;
;
; I  .b  =   ++++ p
; I  .h  =   ip\078
; I  .e  =   I.b    +++    q ''( 6, 60, ( 1/6[Ra, Ri], 1/6[Ri, Ra] ) )
.                              % 8 originally, not 6
; I      =   I.h    +++    I.e
);

Dd( i081 )( X_any  )( Y_NORM )( % s073; k067
;
	Pair  correction     =  0.2 $ ( 1, 1 );
	Pair  split_distance = !! split_distance_default  +  correction;
;
	iwe = iwe\078  +  split_distance  +  !! rrx L_parenthesis;
;
; I      =   ip\078    +++    L_R_parenthesis  splitted
);

		endgroup ; %% i077 - i081

Dd( i082 )( X_EQB  )( Y_any  )( % s074; k068
;
	isn = 4/5 * isn_base;
	iwe = !! $ 6;
;
	Pairp eye = (  $ 2.5,  $ 2.5 );

	Path  p   =                 ( -$ 4.0  ,    $ 1.3   )
	.           .. { right    } ( -$ 2.5  ,    $ 0.9   )
	.           .. { right    } ( -$ 1    ,    $ 1.2   )
	.           .. { right    } (  $ 1    ,    $ 0.2   )
	.           .. { up       } ( eye + ( -$ 0.5, -$ 1.0 ) )
	.           .. { up       } ( eye + ( -$ 1.0,  $ 0.2 ) )
	.           .. { right    } ( eye + (  $ 0.0,  $ 1.0 ) )
	.           .. { Dir  140 } ( eye + (  $ 1.2, -$ 0.5 ) ) { Dir  110 }
	.           .. { Dir  110 } ( eye + (  $ 2.2, -$ 0.8 ) ) { Dir -120 }
	.           .. { Dir -110 } ( eye + (  $ 1.2, -$ 1.2 ) ) { Dir - 80 }
	.           .. { left     } ( eye + (  $ 0.8, -$ 1.1 ) )
	.           .. { down     } ( eye + (  $ 0.7, -$ 1.2 ) )
	.           .. { down     } (  $ 3.5  ,   -$ 1.0   )
	.           .. { left     } (  $ 1    ,   -$ 3     )
	.           .. { left     } ( -$ 1.5  ,   -$ 2.5   )
	.           .. { Dir -100 } ( -$ 3.5  ,   -$ 3.0   )
	.          ---              ( -$ 4.7  ,   -$ 2.0   )
	.           .. { up       } ( -$ 3.5  ,   -$ 0.3   )
	.           .. { Dir - 40 } ( -$ 4.7  ,    $ 0.5   )
	.           .. { Dir   40 } ( -$ 4.0  ,    $ 1.3   );

	Path   q  = eye;
	Path   r  = superellipse( iEO, iON, iWO, iOS, 0.75 );
;
; I      =   p    +++     q    +++     r
);

Dd( i083 )( X_SYM  )( Y_NORM )( % s071; k065
; I  .sn =   ip\059.sn
; I  .o  =   ip\059.o
;
	Nangle  alpha = 70;

	PAIRP  PP, QQ, RR, SS, TT, UU, VV;
	PATH   p , q , r , pq, z ;

	PP  =  ( -$ 3   ,  -$ 1.5  );
	RR  =  ( -$ 5   ,  +$ 1.0  );
	SS  =  ( -$ 5.5 ,  +$ 0.5  );
	TT  =  ( -$ 6   ,  +$ 1.3  ); % iw

	UU  =  TT + 2.5 ( SS  -+  RR );
	QQ  =  3/4[ PP, RR ];

	r   =  Subpath( 2, 4 ) of I.o;

	p   =          PP   --  (         PP   projection( alpha )  r );
	q   =          QQ   --  (         QQ   projection( alpha )  r );
	pq  =  1/2[PP, QQ]  --  ( 1/2[PP, QQ]  projection( alpha )  r );

	VV  = jet( UU, Angle( RR -- PP ) )  Intersectionpoint  q;

	z  = PP  ---  QQ  ---  RR  ---  SS  ---  TT  ---  UU  ---  VV;
;
; I  .d  =   p    +++    q    +++    pq
; I  .w  =   z    +++    I.d
; I  .e  =   I.w  ||
; I      =   I.sn    +++    |. idy    +++    I.w    +++    I.e
;
	iwe = !! -xpart TT;
;
);

Dd( i084 )( X_EQB  )( Y_NORM )( % s049; k045
;
	PAIRP  Rb, Rd, Rf, Rh, Rj, Rl, Rn, Rp, Rr, Rt;

	Rb  =  (   $ 0.0  ,    $ 6.0   ); % in
	Rd  =  (   $ 1.5  ,    $ 3.5   );
	Rf  =  (   $ 0.3  ,   -$ 1.0   );
	Rh  =  (   $ 1.6  ,   -$ 6.0   ); % ie, is
	Rj  =  (  -$ 0.4  ,   -$ 6.0   ); % is
	Rl  =  (  -$ 0.9  ,   -$ 5.0   );
	Rn  =  (  -$ 0.7  ,   -$ 4.0   );
	Rp  =  (  -$ 1.8  ,   -$ 1.0   );
	Rr  =  (  -$ 1.5  ,    $ 0     );
	Rt  =  (  -$ 2.2  ,    $ 3.0   ); % iw
;
	Path   p  =                   Rb { right    }
	.             .. { down     } Rd
	.             .. { down     } Rf
	.             .. { Dir  140 } Rh { left     }
	.            ---              Rj { Dir - 20 }
	.             .. { Dir - 70 } Rl { Dir   30 }
	.             .. { up       } Rn
	.             .. { Dir - 30 } Rp { Dir   30 } % point 7 of p
	.             .. { up       } Rr
	.             .. { up       } Rt
	.             ..              cycle;

	Pairp  Za =  jet( Rr, 50 )  where_x  0;
	Pairp  Zb =  0.8[ Za, Rb ];
	Path   q  =  subpath( 7, 2 + length p )  of  p;
;
; I  .h  =   ++++ p
; I  .b  =   q  ''( 4, 50, ( Za, Zb ) )
; I\0    =   I.h    +++    I.b
;
	Pair   iwe_a =  ( xpart Rt, max( xpart Rd, xpart Rh ) );
	Numer  idx_a =  first iwe_a  -+  second iwe_a;
	Numer  idx_b =  $ 6  *  golden_ratio;
;
	iwe = !! ( idx_b/2 );
;
; I\1    =   I\0  xsh -1/2[ first iwe_a, second iwe_a ]
; I      =   I\1  Xscaled( idx_b / idx_a )
);

Dd( i085 )( X_EQB  )( Y_NORM )( % s051; k046
;
	iwe = iwe\084  +  !! split_distance_default  +  !! rrx ip\093.b;
;
; I      =   ip\084    +++    ( ip\093.b    +++    ip\093.b  || )  splitted
);

Dd( i086 )( X_SYM  )( Y_NORM )( % s150; k144
;
	iwe = !! 0;
;
; I      =   |. idy
);

Dd( i087 )( X_SYM  )( Y_NORM )( % s151; k145
;
	iwe = !! 1/2 stroke_distance_x;
;
; I  .w  =   ip\086  xsh( iw\086  -+  iw )
; I  .e  =   ip\086  xsh( ie\086  -+  ie )
; I      =   I.w     +++    I.e
);

Dd( i088 )( X_SYM  )( Y_NORM )( % s; k146
;
	iwe = !! ( ie\087  +  split_distance_default  +  0 );
;
; I      =   ip\087    +++    ii_ii  splitted
);

Dd( i089 )( X_SYM  )( Y_NORM )( % s152.1; k147
;
	iwe = !! 2/2 stroke_distance_x;
;
; I  .w  =   ip\087  xsh( iw\087  -+  iw )
; I  .e  =   ip\086  xsh( ie\086  -+  ie )
; I      =   I.w     +++    I.e
);

Dd( i090 )( X_any  )( Y_NORM )( % s153; k148
; I  .h  =   ip\089
; I  .b  =   ip\162
; I  .x  =   I.b  ysh( is\162  -+  0 )
; I  .y  =   I.x  |>45  scy in
; I  .e  =   I.y  xsh( 0  -+  ie\089 )
; I      =   I.h    +++    I.e
;
	iwe = iwe\089  +  ( 0, I.y.?.x_e );
;
);

Dd( i091 )( X_any  )( Y_NORM )( % s; k
; I  .h  =   ip\089
;
	Numer   h_stick = $ 3;
;
; I  .b  =   |. h_stick  ysh( -h_stick/2  -+  0 )
; I  .c  =   ip\176\3.3  ysh( 0  -+  h_stick )    % left oriented flag
; I  .x  =   I.b    +++    I.c
; I  .y  =   I.x  |>45  scy in
; I  .e  =   I.y  xsh( 0  -+  ie\089 )
; I      =   I.h    +++    I.e
;
	iwe = iwe\089  +  ( 0, I.y.?.x_e );  % I.y.?.x_e = 4/5 in  = $ 4.8
;
);

Dd( i092 )( X_SYM  )( Y_ROOF )( % s; k149
; I  .h  =   ip\089
; I\1    =   I.h  Transformed ysc_shrink
; I      =   I\1  roofed( r_acute )
;
	iwe = !! rx fig_right I;
;
);

Dd( i093 )( X_any  )( Y_NORM )( % s156; k152
;
	iwe = !! ( stroke_distance_x + 1/12 idy );
;
; I  .b  =   ip\086  sla (1/6)
; I  .w  =   ip\087  xsh( iw\087  -+  iw )
; I  .e  =   I.b     xsh( (ie\086 + (1/6)*in)  -+  ie )
; I      =   I.w     +++    I.e
);

Dd( i094 )( X_any  )( Y_NORM )( % s; k
;
	iwe = !! ( stroke_distance_x + 1/12 idy );
;
; I  .b  =   ip\087  sla (1/6)
; I  .w  =   ip\086  xsh( iw\086  -+  iw )
; I  .e  =   I.b     xsh( (ie\087 + (1/6)*in)  -+  ie )
; I      =   I.w     +++    I.e
);

Dd( i095 )( X_SYM  )( Y_NORM )( % s154; k150
;
	iwe = !! 3/2 stroke_distance_x;
;
; I  .w  =   ip\089  xsh( iw\089  -+  iw )
; I  .e  =   ip\086  xsh( ie\086  -+  ie )
; I      =   I.w     +++    I.e
);

Dd( i096 )( X_SYM  )( Y_NORM )( % s155; k151
;
	iwe = !! 4/2 stroke_distance_x;
;
; I  .w  =   ip\095  xsh( iw\095  -+  iw )
; I  .e  =   ip\086  xsh( ie\086  -+  ie )
; I      =   I.w     +++    I.e
);

Dd( i097 )( X_SYM  )( Y_any  )( % s126.2; k121.023
; I  .a  =   ip\098
;
	isn = ( is\098 + ( in\098 -+ in_base ), in_base );
	iwe = iwe\098;
;
; I      =   ip\098  ysh( in\098  -+  in )
);

Dd( i098 )( X_SYM  )( Y_any  )( % s126.1; k121.001
;
	isn = !! 1/2 shrt;
	iwe = !! 0;
;
; I      =   |. idy
);

Dd( i099 )( X_SYM  )( Y_any  )( % s124; k119
; I  .a  =   ip\100            % access now possible
;
	isn = ( is\100 + ( in\100 -+ in_base ), in_base );
	iwe = iwe\100;
;
; I      =   ip\100  ysh( in\100  -+  in )
);

Dd( i100 )( X_SYM  )( Y_any  )( % s127; k122.002
; I  .a  =   ip\098            % access now possible
;
	isn = isn\098;
	iwe = !! 1/2 stroke_distance_x;
;
; I  .w  =   ip\098  xsh( iw\098  -+  iw )
; I  .e  =   ip\098  xsh( ie\098  -+  ie )
; I      =   I.w     +++    I.e
);

		begingroup %% i101 - i118

Cc( i101, i118 )( %%
	Numer  l_shrt  =  shrt;  % stroke length for i101, i103, i105, ..., i118
	Numer  l_long  =  long;  % stroke length for i102, i104, i106, ..., i115
); %%

Dd( i101 )( X_SYM  )( Y_NORM )( % s145; k140
;
	iwe = !! 0;
;
; I  .a  =   |. l_shrt
; I  .n  =   I.a  ysh( +1/2 l_shrt  -+  in )
; I  .s  =   I.a  ysh( -1/2 l_shrt  -+  is )
; I      =   I.s    +++    I.n
);

Dd( i102 )( X_SYM  )( Y_any  )( % s128; k123.766
;
	isn = !! 1/2 l_long;
	iwe = !! 2/2 stroke_distance_x;
;
; I  .a  =   |. idy
; I  .w  =   I.a  xsh( 0  -+  iw )
; I  .e  =   I.a  xsh( 0  -+  ie )
; I  .o  =   I.a
; I  .x  =   I.o    +++    I.e
; I      =   I.w    +++    I.x
);

Dd( i103 )( X_SYM  )( Y_NORM )( % s144; k139
;
	iwe = !! 1/2 stroke_distance_x;
;
; I  .nw =   ip\101.n  xsh( iw\101  -+  iw )
; I  .ne =   ip\101.n  xsh( ie\101  -+  ie )
; I  .n  =   I.nw    +++    I.ne
; I  .s  =   ip\101.s
; I      =   I.s     +++    I.n
);

Dd( i104 )( X_SYM  )( Y_any  )( % s129; k124.767
;
	isn = !! 1/2 l_long;
	iwe = !! 3/2 stroke_distance_x;
;
; I  .w  =   ip\102    xsh( iw\102  -+  iw )
; I  .e  =   ip\102.e  xsh( ie\102  -+  ie )
; I      =   I.w    +++    I.e
);

Dd( i105 )( X_SYM  )( Y_NORM )( % s146; k124.016
;
	iwe = !! 1/2 stroke_distance_x;
;
; I  .e  =   ip\101    xsh( ie\101  -+  ie )
; I  .w  =   ip\101    xsh( iw\101  -+  iw )
; I      =   I.e    +++    I.w
);

Dd( i106 )( X_SYM  )( Y_any  )( % s130.1; k125.005
;
	isn = !! 1/2 l_long;
	iwe = !! 4/2 stroke_distance_x;
;
; I  .w  =   ip\104    xsh( iw\104  -+  iw )
; I  .e  =   ip\102.e  xsh( ie\102  -+  ie )
; I      =   I.w    +++    I.e
);

Dd( i107 )( X_EQB  )( Y_NORM )( % s130.2; k125.017
;
	iwe = !! 2/2 stroke_distance_x;
;
; I  .e  =   ip\105    xsh( ie\105  -+  ie )
; I  .nw =   ip\101.n  xsh( iw\101  -+  iw )
; I      =   I.e     +++    I.nw
);

Dd( i108 )( X_SYM  )( Y_any  )( % s131.1; k126.006
;
	isn = !! 1/2 l_long;
	iwe = !! 5/2 stroke_distance_x;
;
; I  .w  =   ip\106    xsh( iw\106  -+  iw )
; I  .e  =   ip\102.e  xsh( ie\102  -+  ie )
; I      =   I.w    +++    I.e
);

Dd( i109 )( X_SYM  )( Y_NORM )( % s131.2; k126.018
;
	iwe = !! 2/2 stroke_distance_x;
;
; I  .e  =   ip\105    xsh( ie\105  -+  ie )
; I  .w  =   ip\101    xsh( iw\101  -+  iw )
; I      =   I.e    +++    I.w
);

Dd( i110 )( X_SYM  )( Y_any  )( % s132.1; k127.007
;
	isn = !! 1/2 l_long;
	iwe = !! 6/2 stroke_distance_x;
;
; I  .w  =   ip\108    xsh( iw\108  -+  iw )
; I  .e  =   ip\102.e  xsh( ie\102  -+  ie )
; I      =   I.w    +++    I.e
);

Dd( i111 )( X_SYM  )( Y_NORM )( % s141.2; k136.529
;
	iwe = !! ( ie\110  +  split_distance_default  +  rrx L_parenthesis );
;
; I      =   ip\110    +++    L_R_parenthesis  splitted
);

Dd( i112 )( X_EQB  )( Y_NORM )( % s132.2; k127.019
;
	iwe = !! 3/2 stroke_distance_x;
;
; I  .e  =   ip\109    xsh( ie\109  -+  ie )
; I  .nw =   ip\101.n  xsh( iw\101  -+  iw )
; I      =   I.e    +++    I.nw
);

Dd( i113 )( X_EQB  )( Y_NORM )( % s141.1; k136.397
;
	iwe = !! ( ie\112  +  split_distance_default  +  rrx L_parenthesis );
;
; I      =   ip\112    +++    L_R_parenthesis  splitted
);

Dd( i114 )( X_SYM  )( Y_NORM )( % s133; k128
;
	iwe = !! 3/2 stroke_distance_x;
;
; I  .e  =   ip\109    xsh( ie\109  -+  ie )
; I  .w  =   ip\101    xsh( iw\101  -+  iw )
; I      =   I.e    +++    I.w
);

Dd( i115 )( X_SYM  )( Y_any  )( % s134.2; k129.314
;
	isn = !! 1/2 l_long;
	iwe = !! 8/2 stroke_distance_x;
;
; I  .w  =   ip\110    xsh( iw\110  -+  iw )
; I  .e  =   ip\102.x  xsh( ie\102  -+  ie )
; I      =   I.w    +++    I.e
);

Dd( i116 )( X_EQB  )( Y_NORM )( % s134.1; k129.021
;
	iwe = !! 4/2 stroke_distance_x;
;
; I  .e  =   ip\114    xsh( ie\114  -+  ie )
; I  .nw =   ip\101.n  xsh( iw\101  -+  iw )
; I      =   I.e    +++    I.nw
);

Dd( i117 )( X_EQB  )( Y_ROOF )( % s142; k137
; I  .h  =   ip\116
; I\1    =   I.h  Transformed ysc_shrink
; I      =   I\1  roofed( r_straight )
;
	iwe = !! rx fig_right I;
;
);

Dd( i118 )( X_SYM  )( Y_NORM )( % s135; k130
;
	iwe = !! 4/2 stroke_distance_x;
;
; I  .e  =   ip\114    xsh( ie\114  -+  ie )
; I  .w  =   ip\101    xsh( iw\101  -+  iw )
; I      =   I.e    +++    I.w
);

		endgroup ; %% i101 - i118

Dd( i119 )( X_EQB  )( Y_NORM )( % s; k
;
	iwe = !! ( stroke_distance_x + $ 1.0 );
;
	Numer fac = 4;             % only purpose: avoid overflow
	Numer  a  = (midi/4/fac)**2 + (idx/4/fac)**2;
	Numer  b  = (stroke_distance_x/2/fac) * (midi/2/fac);
	Numer  c  = (stroke_distance_x/2/fac)**2 - (idx/4/fac)**2;
	% a * (cos alf)**2 + b * (cos alf) + c = 0;
	Numer cos = second quadr_eq( a, b, c );
	Numer alf = angle( cos, 1 +-+ cos );
;
	Numer  slant    =  cosd alf / sind alf;
	NUMER  distance;     slant * midi  +  2 distance  =  idx;
;
; I  .a  =   |. midi  sla slant
; I  .x  =   I.a  xsh( -1/2 distance )    +++    I.a  xsh( +1/2 distance )
; I  .y  =   I.x  xsh( -1/2 distance )    +++    I.x  xsh( +1/2 distance )
; I  .n  =   I.x  ysh( +midi/2  -+  in )
; I  .s  =   I.y  ysh( -midi/2  -+  is )
; I  .o  =   I.y  ||
; I  .h  =   I.s    +++    I.o
; I      =   I.h    +++    I.n
);

Dd( i120 )( Z_SYM  )( Y_NORM )( % s147.1; k141.130
; I  .h  =   ip\119.h
; I  .n  =   ip\119.y  ysh( +midi/2  -+  in )
;
	iwe = iwe\119;
;
; I      =   I.h    +++    I.n
);

Dd( i121 )( X_SYM  )( Y_NORM )( % s148; k142
;
	iwe = !! 3/2 stroke_distance_x;
;
; I  .a  =   |. midi
; I  .x  =   I.a  xsh( 0  -+  -1/2 stroke_distance_x )
; I  .y  =   I.a  xsh( 0  -+  +1/2 stroke_distance_x )
; I  .z  =   I.x    +++    I.y
; I  .w  =   I.z  xsh( - 1/2 stroke_distance_x  -+ iw )
; I  .e  =   I.z  xsh( + 1/2 stroke_distance_x  -+ ie )
; I  .o  =   I.w    +++    I.e
; I  .n  =   I.o  ysh( +midi/2  -+  in )
; I  .s  =   I.o  ysh( -midi/2  -+  is )
; I      =   I.s    +++    I.o    +++    I.n
);

Dd( i122 )( X_any  )( Y_NORM )( % s149; k143
;
	iwe = !! ( ie\121  +  split_distance_default  +  rrx L_parenthesis );
;
; I      =   ip\121    +++    R_R_parenthesis  splitted
);

Dd( i123 )( X_any  )( Y_NORM )( % s125; k120
;
	iwe = !! stroke_distance_x;
;
; I  .w  =   ip\097  xsh( iw\097  -+  iw )
; I  .e  =   ++++ ( iWS  ..  { up } iEO  ---  iEN )
; I      =   I.w    +++    I.e
);

Dd( i124 )( X_any  )( Y_NORM )( % s209; k204
;
	iwe = !! $ 2.5;
;
; I  .w  =   |. idy  sla 2/6
; I  .e  =   |. ($ 4)  ysh( -($ 4)/2  -+  is )  sla -3/6
; I      = ( I.w    +++    I.e )  xsh - $ 0.5
);

Dd( i125 )( X_any  )( Y_NORM )( % s206; k201
;
	iwe = !! $ 2.5;
;
; I  .w  =   |. idy  sla 2/6
; I  .e  =   |. ($ 6)  ysh( -($ 6)/2  -+  is )  sla -3/6
; I      = ( I.w    +++    I.e )  xsh - $ 0.5
);

Dd( i126 )( X_SYM  )( Y_NORM )( % s208; k203
; I      =   ip\001\0
;
	iwe = iwe\001;
;
);

Dd( i127 )( X_EQB  )( Y_NORM )( % s287; k283
;
	iwe = !! stroke_distance_x;
;
; I      =   ++++ ( ( iWN - ( 0, idx ) )  --  iWN  --  iEN  --  iES )
);

Dd( i128 )( X_EQB  )( Y_NORM )( % s288; k284.477
; I  .h  =   ip\127
;
	iwe = iwe\127;
;
; I      =   I.h    +++    |. $ 1  sla -4/6  shi $( -0.1, 1.1 )
);

Dd( i129 )( X_EQB  )( Y_NORM )( % s191; k185
;
	Numer  u  =  $ 1.5;
	iwe = !! 3/2 u;
;
; I      =   ++++ ( iWS  --  2/3[ iWN, iEN ]  --  iEO )
);

Dd( i130 )( Z_SYM  )( Y_NORM )( % s194; k188
;
	Numer  u  =  $ 1.5;
	iwe = !! 4/2 u;
;
	Pairp  WSW  =  ( iw, is + u );
	Pairp  SSW  =  ( -u, is     );
;
; I      =   ++++ ( WSW  --  SSW  --  -SSW  --  -WSW )
);

Dd( i131 )( X_any  )( Y_ROOF )( % s195; k189
;
	iwe = !! 1/2 $ 11.5;
;
	Numer  u    =  1/6 ( idx - roof_distance[ r_straight ] );
	Numer  m    =  1/2 roof_distance[ r_straight ];
	Numer  r    =  4 u + 2 roof_distance[ r_straight ];
;
	Pairp  NW   =  ( m - 3 u, yn_shrinked );
	Pairp  SSW  =  ( m - 1 u, is  );
	Pairp  NNE  =  ( m + 1 u, yn_shrinked );
	Pairp  SE   =  ( m + 3 u, is  );
;
; I\1    =   ++++ ( NW  --  SSW  --  NNE  --  SE )
; I      =   I\1  roofed( r_straight, r )  xsh( ~.?.x_w -+ iw ) % roof shifted
);

Dd( i132 )( Z_SYM  )( Y_any  )( % s197; k191
;
	isn = !! $ 4;
	iwe = !! $ 6;
;
	Numer  delta_a = 1/36 ie;
	Numer  delta_b = 1/36 iw;
;
	Pair   shift_a = ( 0.9/9 iw, -$ 1 );
	Pair   shift_b = ( 1.1/9 ie, -$ 1 );
;
	Pairp  SW  =  ( 5/5 iw          , is );   % = iWS
	Pairp  Nw  =  ( 3/5 iw + delta_a, in );
	Pairp  Sw  =  ( 1/5 iw + delta_b, is );
	Pairp  Nwa =  Nw + shift_a;
	Pairp  Nwb =  Nw + shift_b;
	Pairp  Swa =  Sw - shift_b;
	Pairp  Swb =  Sw - shift_a;
;
	Path   q   =  SW  ---  Nwa  ..  Nw {right}  ..  Nwb
	.                 ---  Swa  ..  Sw {right}  ..  Swb  ---  OQ;
	Path   p   =  q   &   ( q rotated 180 ) `;
;
; I      =   ++++ p
);

Dd( i133 )( Z_SYM  )( Y_NORM )( % s198; k192
;
	iwe = isn;
;
	Numer  hhp  =  idy / 4; % half height of the parts
;
	Pairp  PS  =  ( 5/5 iw, -hhp );
	Pairp  QN  =  ( 3/5 iw, +hhp );
	Pairp  RS  =  ( 1/5 iw, -hhp );
;
	Path   pp  =  PS  --  QN  --  RS  --  -RS  --  -QN  --  -PS;
;
; I  .h  =   ++++ pp
; I  .n  =   I.h  ysh( +hhp  -+  in )
; I  .s  =   I.h  ysh( -hhp  -+  is )
; I      =   I.s    +++    I.n
);

		begingroup %% i134 - i136

Cc( i134, i136 )( %%
% We want the same sloping for these signs (and the full height),
% so we need to accept differing widths.
%
% Parameters: q, iwe_base_a
;
	Numer q = 5/6;           % for i135, i136: a base line point divides
	.                        %                 its base line side as (1-q)/q
	Numer r = (1-q)+q+(1-q); % height splits into 3 parts as (1-q)/q/(1-q)
;
	Pair   iwe_base_a = !! $ 6;                        % width of i134
	Pair   iwe_base   = (( (1-q) + q)/r) * iwe_base_a; % width of i135, i136
;
	Pairp  NN  =  (   0         , in_base                    );
	Pairp  SSW =  ( q * iw_base , is_base                    );
	Pairp  WSW =  (     iw_base , in_base - (1/r) * idy_base );
	Pairp  NNE =  NN  + ( WSW  -+  SSW );
	Pairp  NNW =  NNE ||;
	Pairp  NO  =  NN  +  2( 1/2[NNW, NNE] - NN );
); %%

Dd( i134 )( X_SYM  )( Y_NORM )( % s189.2; k184
;
	iwe = iwe_base_a;
;
; I      =   tri_open( idx, idy )
);

Dd( i135 )( X_SYM  )( Y_NORM )( % s202; k197
;
	iwe = iwe_base;
;
	Path  west  =  NN  --  NNE  --  SSW  --  WSW  --  cycle;
;
; I  .w  =   ++++ west
; I  .e  =   I.w  ||
; I      =   I.w    +++    I.e
);

Dd( i136 )( X_SYM  )( Y_NORM )( % s201; k195
; I  .h  =   ip\135
;
	iwe = iwe\135;
;
	Path  p  =     1/4[ NNW, WSW ]  --  1/4[ NO , SSW ]
	.          --  2/4[ NO , SSW ]  --  2/4[ NNW, WSW ]
	.          --  3/4[ NNW, WSW ]  --  3/4[ NO , SSW ];
;
; I  .sw =   ++++ p
; I  .se =   I.sw  ||
; I      =   I.h    +++    I.sw    +++    I.se
);

		endgroup ; %% i134 - i136

		begingroup %% i137 - i152

Cc( i137, i152 )( %%
	Pair     iwe_base =  !! $ 3;
;
	save  cross;
	vardef  cross( expr half_width, half_height ) =
		Pairp  NW  =  ( -half_width, 2 half_height +is );
		Pairp  SE  =  ( +half_width,                is );
		Path   p   =  SE  --  NW;
		Path   q   =  p  ||;
		p    +++    q
	enddef;
); %%

Dd( i137 )( X_SYM  )( Y_NORM )( % s244; k240
;
	iwe = iwe_base;
;
; I      =   cross( idx/2, idy/2 )
; I\2    =   cross( $ 2  , $ 2   )
);

Dd( i138 )( X_SYM  )( Y_ROOF )( % s248; k244
; I\1    =   cross( ie_base, dy_shrinked/2 )
; I      =   I\1  roofed( r_acute )
;
	iwe = iwe_base  +  !! roof_distance[ r_acute ];
;
);

Dd( i139 )( X_SYM  )( Y_ROOF )( % s247; k243
; I\1    =   ip\138\1
; I      =   I\1  roofed( r_straight )
;
	iwe = iwe_base  +  !! roof_distance[ r_straight ];
;
);

Dd( i140 )( X_SYM  )( Y_NORM )( % s246; k242
;
	iwe = !! good.x ( ie_base  +  1/2 distance_x_low );
;
; I  .h  =   ip\137
; I  .s  =   ii_mini_narrow  ysh( -mini/2  -+  is )
; I  .w  =   ii_mini_narrow  xsh( -distance_x_low/2  -+  iw )
; I  .sw =   I.s    +++    I.w
; I  .ne =   I.sw  shi( +distance_x_low/2  -+  ie, +mini/2  -+  in )
; I      =   I.h    +++    I.sw    +++    I.ne
);

Dd( i141 )( X_SYM  )( Y_NORM )( % s249; k245
;
	iwe = iwe_base;
;
	Numer  dist  =  1.2 stroke_distance_x;
;
; I  .h  =   ip\137
; I  .b  =   |. idy
; I  .sn =   I.b  xsh( 0  -+  -dist/2 )    +++    I.b  xsh( 0  -+  +dist/2 )
; I      =   I.h    +++    I.sn
);

Dd( i142 )( X_SYM  )( Y_ROOF )( % s252; k248
; I  .h  =   ip\139
; I  .sn =   ip\141\sn  Transformed ysc_shrink
; I      =   I.h    +++    I.sn
;
	iwe = iwe\139;
;
);

Dd( i143 )( X_SYM  )( Y_NORM )( % s250; k246
;
	iwe = !! ( ie_base  +  split_distance_default  +  distance_x_low );
;
; I      =   ip\141    +++    iiii_iiii  splitted
);

Dd( i144 )( X_SYM  )( Y_NORM )( % s251; k247
;
	iwe = !! ( ie_base  +  split_distance_default  +  rrx L_parenthesis );
;
; I      =   ip\141    +++    R_L_parenthesis  splitted
);

Dd( i145 )( X_SYM  )( Y_NORM )( % s253; k249
; I  .h  =   ip\141
; I  .b  =   ip\176  Yscaled( ($ 8)/ idy\176 )  Xscaled( ($ 1.5)/ idx\176 )
; I  .o  =   I.b  |>90  ysh( ($ 1.5)/2  -+  0 )
; I      =   I.h    +++    I.o
;
	iwe = !! max( ie_base, ($ 8)/2 );
;
);

			begingroup %% i146 - i147

Cc( i146, i147 )( %%
	Pair   iwe_base = !! $ 4.5;
;
	Numer  a  =  $ 2;   % oval height
); %%

Dd( i146 )( X_SYM  )( Y_NORM )( % s257; k254
;
	iwe = iwe_base;
;
; I  .a  =   oval_medium. a
;
	Path  oval_p  =  ppath I.a;
	save  oval_r;     path   oval_r;  % oval rotated
	save  Oval_C;     pairp  Oval_C;  % oval centre

	save   fit;
	vardef fit( expr alf ) =            % alf = Angle( OQ -+ Oval_C )
		oval_r :=  oval_p  |>( alf - 90 );
		Oval_C :=  iEN - ( rx oval_r, ry oval_r );
		alf  <  Angle( OQ -+ Oval_C )
	enddef;

	Nangle  beta = solve fit( 0, 90 ); % nearly 10 iterations required
	.                                 % better bounds?: not worth the effort
	oval_r :=  oval_p  |>( beta - 90 );
	Oval_C :=  iEN - ( rx oval_r, ry oval_r );
;
; I  .b  =   I.a  |>( beta - 90 )
; I  .c  =   I.b  shi( OQ  -+  Oval_C )
;
	Pairp  Oval_X  =  ( OQ  --  Oval_C )  Intersectionpoint_right  I.c;
;
; I  .d  =   ++++ ( OQ -- Oval_X )
; I  .x  =   I.c    +++    I.d
; I  .y  =   I.x    +++    I.x  |> 180
; I      =   I.y    +++    I.y  ||
);

Dd( i147 )( X_SYM  )( Y_NORM )( % s; k
;
	iwe = iwe_base;
;
; I  .h  =   ip\146
; I  .a  =   ip\146.a
; I  .n  =   I.a  ysh( +a/2  -+  in )
; I  .s  =   I.a  ysh( -a/2  -+  is )
; I  .sn =   I.s    +++    |.( idy - 2a )    +++    I.n
; I      =   I.h    +++    I.sn
);

			endgroup ; %% i146 - i147

Dd( i148 )( Z_SYM  )( Y_NORM )( % s; k
;
	iwe = isn;
;
; I  .a  =   ++++ ( iWS  --  iOS  --  iON  --  iEN )
; I      =   I.a    +++    I.a  |>90
);

			begingroup %% i149 - i152

Cc( i149, i152 )( %%
	% We can choose one of two possibilities (or to interpolate them):
	% a) take the  angle  as for i137 (and the x-width a little bit greater)
	% b) take the x-width as for i137 (let it   slope  a little bit stronger)
	% We choose a).

	Nangle  beta  =  Angle( ie_base, in_base );  % sloping gradient
	Numer      a  =  $ 1.5;                      % side length

	% The little triangle at north-east says:
		Numer  ene_en   =  sind beta * a;      % EN -- ENE
		Numer  nne_en   =  cosd beta * a;      % EN -- NNE

	% The triangle above it means:
		Numer  en_above =  cotd beta * nne_en; % EN{up} -- intersection ...

	% (_v + _w) projected to OQ gives:
		Pairp  OON  =  ( 0, 1/2( ene_en + en_above ) );
		.                                      % intersection above OQ

	% Let's take the easy way now:
		Pairp  NNE  =  OON  projection(       beta )  N_line;
		Pairp  OOE  =  OON  projection( 180 - beta )  jet( OQ, right );
		Pairp  ENE  =  NNE + ( nne_en, -ene_en );

	Path  p_n  =  NNE ||  --  OON  --  NNE    ;
	Path  p_e  =  ENE     --  OOE  --  ENE |: ;
	Path  r    =  OON  --  NNE  --  ENE  --  OOE ;
); %%

Dd( i149 )( X_SYM  )( Y_NORM )( % s258; k255
; I  .ne =   p_n     +++    p_e
; I  .sw =   I.ne |||:
; I      =   I.ne    +++    I.sw
;
	iwe = !! xpart ENE;
;
);

Dd( i150 )( X_SYM  )( Y_NORM )( % s259; k256
;
	Path  rr    =  r    &    r  |: `;
	Path  rrrr  =  rr   &    rr || `;
;
; I      =   ++++ rrrr
;
	iwe = !! xpart ENE;
;
);

Dd( i151 )( X_any  )( Y_HIGH )( % s260; k257
;
	Pairp  myNNE = NNE  transformed scy_shrink;
	Pairp  myENE = ENE  transformed scy_shrink;
;
; I  .h  =   ip\150  Transformed scy_shrink
; I  .b  =   ip\231.a  |>( Angle( myNNE -+ myENE ) - 90 )
;
	Pairp  NE = 1/2[ myNNE, myENE ];
	Numer  scalefactor  =   ( ypart NE  -+  yn_high   )
	.                     / (        0  -+  I.b.?.y_n );
;
; I  .ne =   I.b  Scaled scalefactor  shi( OQ  -+  NE )
; I      =   I.h    +++    I.ne
;
	iwe = ( I.h.?.x_w, I.ne.?.x_e );
;
);

Dd( i152 )( X_any  )( Y_any  )( % s261; k258
;
	isn = ( unk, in_base );
;
; I  .w  =   ip\150
;
	Nangle  angle_l = 180 - beta;
	Nangle  angle_r = 10;
;
	Pairp   SE =  1/2[ NNE, ENE ]  |:;
;
; I  .e  =   ip\166\9.n  |> angle_r  ysh( 0 -+ in )  % ip\166\9.n.?.nw = OQ
; I      = ( I.w  ++("")+-  I.e )  connected ( SE, angle_l, "s", angle_r )
;
	isn = ( ( fig_right fig_left I ).?.y_s, in_base );
	iwe = ( iw\150 , ( fig_right I ).?.x_e );
;
);

			endgroup ; %% i149 - i152

		endgroup ; %% i137 - i152

Dd( i153 )( X_SYM  )( Y_NORM )( % s143; k138
;
	Numer  sh  =  $ 8;
	Numer  nh  =  $ 4;
;
; I  .s  =   |. sh  ysh( -sh/2  -+  is )
; I  .n  =   tri_open( unk, nh )    ysh( +nh/2  -+  in )
; I      =   I.s    +++    I.n
;
	iwe = !! ( teqla_s( nh ) / 2 );
;
);

Dd( i154 )( X_SYM  )( Y_NORM )( % s; k
;
	Numer  sh  =  $ 8;
	Numer  nh  =  $ 4;
;
; I  .s  =   ip\153.s
; I  .n  =   oval_norm. nh  ysh( +nh/2  -+  in )
; I      =   I.s    +++    I.n
;
	iwe = !! ( I.n.?.x_e );
;
);

		begingroup %% i155 - i160

Cc( i155, i160 )( %%
;
	Numer  sh  =  $ 10;
	Numer  nh  =  $  2;
;
); %%

Dd( i155 )( X_SYM  )( Y_NORM )( % s119.2; k114.091
;
	iwe = !! $ 4/2;
;
; I  .b  =   tri_open( idx, ($ 1) )
; I  .we =   I.b  ysh( +($ 1)/2  -+  ( in - nh ) )
; I  .nw =   ++++ Subpath( 0, 1 ) of I.we
; I  .w  =   |. idy    +++    I.nw
; I      =   |. idy    +++    I.we
; I  .n  =   |. ($ 6)  ysh( -($ 6)/2  -+  0 )    +++    I.we
);

Dd( i156 )( X_SYM  )( Y_NORM )( % s120; k115
;
	iwe = !! ( ie\155  +  split_distance_default  +  rrx L_parenthesis );
;
; I      =   ip\155    +++    R_L_parenthesis  splitted
);

Dd( i157 )( X_any  )( Y_NORM )( % s; k
; I  .nw =   ip\155.nw  ysh( (in - nh)  -+  in )
; I  .w  =   ip\155.w    +++    I.nw
; I      =   ip\155      +++    I.nw
;
	iwe = iwe\155;
;
);

Dd( i158 )( X_SYM  )( Y_NORM )( % s254; k250
;
	iwe = !! nh;
;
; I  .s  =   |. sh  ysh( -sh/2  -+  is )
; I  .n  =   ip\137\2  ysh( nh  -+  sh )
; I      =   I.s    +++    I.n
);

Dd( i159 )( X_SYM  )( Y_ROOF )( % s; k253
;
	iwe = !! $ 2.75;
;
; I  .o  =   |. dy_shrinked  ysh( -dy_shrinked/2  -+  is )
; I  .n  =   ip\137\2  ysh( ( is + nh ) -+ ( yn_shrinked - ( nh ++ nh ) ) )
; I\1    =   I.o    +++    I.n
; I      =   I\1  roofed( r_acute, idx )
);

Dd( i160 )( X_any  )( Y_NORM )( % s255; k251
; I  .h  =   ip\158
; I  .b  =   ip\204\3  ysh( in  -+  0 )  zsc $( 2, 5 )  |>30
; I  .w  =   I.b  shi( OQ  -+  ( -nh, in ) )
; I      =   I.h    +++    I.w
;
	iwe = ( I.w.?.x_w, ie\158 );
;
);

		endgroup ; %% i155 - i160

Dd( i161 )( X_SYM  )( Y_NORM )( % s092; k085
;
	iwe = !! $ 2;
;
	vardef  upsilon  primary l  =
		Numer   nh     =  l  +-+  l/2;     Numer    sh = idy - nh;
		Figure  north  =  tri_open( l, unk ) |:  ysh( +nh/2  -+  in );
		Figure  south  =  |. sh  ysh( -sh/2  -+  is );
		south    +++    north
	enddef;
;
; I      =   upsilon  idx
; I\1    =   upsilon  $ 2
);

		begingroup %% i162 - i164

Cc( i162, i164 )( %%
	Pair     iwe_base = !! $ 3;
);

Dd( i162 )( X_SYM  )( Y_NORM )( % s093.1; k086.126
;
	iwe = iwe_base;
;
	save  bowl;
	def   bowl( expr dx, dy ) =
		(-dx/2, in) {Dir (180-10)} .. (0, in-dy) .. {Dir (0+10)} (+dx/2, in)
	enddef;
;
	Numer  nh  =  $ 4;
	Numer  nhx =  $ 6;
;
	Path   p   =  bowl(          idx, nh  );
	Path   q   =  bowl( nhx/nh * idx, nhx );
;
; I  .n  =   ++++ p
; I  .s  =   |. idy
; I      =   I.s    +++    I.n
;
; I\1.n  =   ++++ q
; I\1    =   I.s    +++    I\1.n
;
; I  .o  =   I.n    +++    |. nh  ysh( +nh/2 -+ in )
);

Dd( i163 )( X_SYM  )( Y_ROOF )( % s095; k089
; I  .n  =   ip\162.n  ysh( dy_normal  -+  dy_shrinked )
; I  .s  =   |. dy_shrinked  ysh( -dy_shrinked/2  -+  is )
; I\1    =   I.s    +++    I.n
; I      =   I\1  roofed( r_acute )
;
	iwe = iwe_base  +  !! roof_distance[ r_acute ];
;
);

Dd( i164 )( X_SYM  )( Y_NORM )( % s; k087
;
	iwe = !! ( ie_base  +  split_distance_default  +  distance_x_low );
;
; I      =   ip\162    +++    iiii_iiii  splitted
);

		endgroup ; %% i162 - i164

		begingroup %% i165 - i166

Cc( i165, i166 )( %%
	Pair     iwe_base = !! $ 3;

	vardef  broom( expr h, tri_w, tri_h ) =
		Figure  tria   =  tri_open( tri_w, tri_h )  |:;
		Figure  stick  =  |. h;
		stick    +++    tria  ysh( tri_h/2  -+  h/2 )
	enddef;

	Numer  tria_w  = $ 4;
	Numer  tria_h  = $ 2;
);

Dd( i165 )( X_SYM  )( Y_NORM )( % s094.2; k088.547
;
	iwe = iwe_base;
;
; I  .b  =   ip\176  Scaled( idx / idy\176 )
;
	NUMER  sh, nh;    sh + distance_y_mid + nh = idy;
	nh  =  2 ( I.b.?.x_e );
;
; I  .n  =   I.b  |< 90  ysh( +nh/2  -+  in )
; I  .s  =   broom( sh, tria_w, tria_h )  ysh( -sh/2  -+  is )
; I      =   I.s    +++    I.n
);

Dd( i166 )( X_SYM  )( Y_NORM )( % s094.1; k088.466
;
	iwe = iwe_base;
;
; I  .n  =   broom( idy, tria_w, tria_h )
; I  .s  =   ip\165.n  |:
; I      =   I.s    +++    I.n
;
; I\4.n  =   broom( ($ 4), tria_w, tria_h )           % for i021, i167, i235
; I\9.n  =   broom( ($ 9), tria_w, tria_h ) shi(( -tria_w, ($ 9) )/2 -+ OQ )
.                                                     % for i152
; I\6.n  =   broom( ($ 4),  ($ 6),  ($ 4) )           % for i199
);

		endgroup ; %% i165 - i166

Dd( i167 )( X_SYM  )( Y_NORM )( % s; k101
;
	iwe = !! $ 2.75;
;
; I  .a  =   ip\166.n
; I  .b  =   ip\166\4.n  ysh( +($ 4)/2  -+  0 )  scx idx
; I  .o  =   I.b  ysh( 0  -+  ($ 4) )
; I      =   I.a    +++    I.o
);

Dd( i168 )( X_SYM  )( Y_NORM )( % s106; k100
;
	iwe = !! $ 3;
;
	Numer  xbase = idx;
	Numer  ybase = xbase / 4;
;
; I  .a  =   tri_open( xbase, ybase )  |:
; I      =   |. idy         % +++
.            for  xwidth = idx  step (idx -+ ($ 2))/6  until  ($ 2)-eps :
.                +++  I.a  Scaled( xwidth/xbase )
.                .  ysh( +ybase * (xwidth/xbase) / 2
.                .      -+ ( in
.                .         - ((idx -+ xwidth)/(idx -+ ($ 2)))[$ 9.3, $ 1.3] )
.                .     )
.            endfor
);

Dd( i169 )( X_any  )( Y_NORM )( % s093.2; k086.127
;
	iwe = !! $ 4;
;
%	Nangle alf =  55;
	Nangle bet = -45;
;
	Pairp  SO  =  ( -$ 1,  is );
	Pairp  Sw  =  ( -$ 1, $ 2 );
	Pairp  NE  =  iEN;           % jet( Sw, alf )  where_x  ie;
;
	Path   pp  =  SO  --  Sw  --  NE;
;
	Pairp  Se  =  0.75[ Sw, NE ];
	Pairp  Nw  =  jet( Sw, bet )  where_x  iw;
	Pairp  Ne  =  jet( Se, bet )  where_y  in;
	Path   pa  =  Sw  --  Nw;
	Path   pd  =  Se  --  Ne;
	Path   pb  =  interpath( 2/3, pa, pd );
	Path   pc  =  interpath( 1/3, pa, pd );
;
; I      =   pp    +++    pa    +++    pb    +++    pc    +++    pd
);

Dd( i170 )( X_EQB  )( Y_NORM )( % s286; k282
;
	iwe = !! $ 3;
;
; I  .a  =   ip\192.h
; I  .b  =   ip\193.s  |:
; I  .x  =   I.a    +++    I.b
; I  .n  =   I.x  zsc( idy/2, idx )  |>90  ysh( in/2  -+  in )
; I  .w  =   |. idy  xsh iw
; I      =   I.w    +++    I.n
);

Dd( i171 )( X_SYM  )( Y_NORM )( % s099; k092
;
	iwe = !! $ 4;
;
; I  .b  =   ip\176  Yscaled( ($ 8) / idy\176 )  Xscaled( ($ 3) / idx\176 )
; I  .n  =   I.b  |<90  ysh( ($ 3)/2  -+  in )
; I      =   |. idy    +++    I.n
);

Dd( i172 )( X_SYM  )( Y_NORM )( % s100; k093
;
	iwe = !! $ 3;
;
	NUMER  sh, oh, nh;    sh + oh + nh = idy;
	oh  =  distance_y_mid;
	sh  =  nh;
;
; I  .b  =   ip\176  Scaled( idx / idy\176 )
; I  .c  =   |. sh
; I  .x  =   I.b  |< 90
; I  .s  =   I.c  ysh( -sh/2  -+ is )  +++  I.x  ysh( I.b.?.x_e -+ (is+sh) )
; I  .n  =   I.s  |:
; I      =   I.s    +++    I.n
);

Dd( i173 )( X_SYM  )( Y_NORM )( % s102; k095
;
	iwe = !! $ 3;
;
; I  .b  =   ip\172.x
; I  .n  =   I.b  ysh( ~.?.y_n  -+  in )
; I  .o  =   I.n  ysh( - ( rry ~  +  distance_y_mid ) )
; I  .h  =   I.o    +++    I.n
; I      =   |. idy    +++    I.h
);

Dd( i174 )( X_SYM  )( Y_NORM )( % s097.1; k091.044
;
	iwe = !! ( 3 stroke_distance_x );
;
	NUMER  sh, nh;    sh + nh = idy;
	sh  =  $ 8;
;
; I  .s  =   ip\087  xsc( 1/4 idx )
; I  .n  =   rect_open( 3/4 idx, nh )  |:  ysh( +nh/2  -+  in )
; I  .c  =   |. idx   |>90
; I  .o  =   I.c  ysh( 0  -+  (in - nh) )
; I      =   I.s    +++    I.o    +++    I.n
);

Dd( i175 )( X_SYM  )( Y_NORM )( % s; k
;
	iwe = !! ( 3 stroke_distance_x );
;
	NUMER  sh, nh;    sh + nh = idy;
	sh  =  $ 8;
;
; I  .s  =   oval_narrow. sh  ysh( -sh/2  -+  is )
; I  .n  =   ip\162.o  ysh -in  scy nh  ysh +in
; I  .c  =   ip\174.c
; I  .o  =   I.c  ysh( 0  -+  (in - nh) )
; I      =   I.s    +++    I.o    +++    I.n
);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% start of producing glyph variants too

Dd( i176, a107 )( X_EQB  )( Y_NORM )( % s104; k098 %%%%%%%%

%%%% 1)

% i176\4320 =( H- ?   )!= a107 .
% i176\6213 =( C-15   )=  a107 v
% i176\2289 =( M-1305 )=  a107 i
% i176\2674 =( M-732  )=  a107 q
% i176\1046 =( M-73   )=  a107 m
% i176\1227 =( M- ?   )!= a107 .
% i176\2121 =( M-879  )=  a107 h
% i176\2140 =( M-1135 )=  a107 e
% i176\1118 =( M- ?   )!= a107 .
% i176\8208 =( K-99   )=  a107 a

% a107 a K-99   pottery raw
% a107 b K-98   pottery raw
% a107 c M-488  tablet
% a107 d M-1133 seal raw
% a107 e M-1135 seal fine
% a107 f K-98   (?, not found there)
% a107 g M-472  tablet fine
% a107 h M-879  seal raw-fine
% a107 i M-1305 seal fine
% a107 j M-874  seal fine
% a107 k M-748  seal raw-fine - no real difference to j
% a107 l H-99   seal very raw
% a107 m M-73   seal fine
% a107 n M-1278 seal fine
% a107 o M-830  seal raw-fine
% a107 p H-315  tablet raw
% a107 q M-732  seal raw
% a107 r H-309  tablet raw
% a107 s C-14   seal, very raw, sign?
% a107 t M-1311 seal fine
% a107 u M-1312 seal raw-fine
% a107 v C-15   seal fine
% a107 w M-1651 ivory raw
% a107 x H-296  tablet very raw

%%%% 2)

%
% As for other signs, there are many glyph differentiating properties here
% - which of them could possibly indicate a difference in meaning,
% so glyphs differentiated by them should get a sign for its own?
%
% 1) There are  differences in absolute heights.
%    It seems better, to take this as non-differentiating.
%    Why?: a) The examples don't indicate the relevance on meaning.
%          b) It is difficult for men, to grasp such differences,
%             so they have little chance, to become sign differentiating.
%          c) It is difficult
%             to reproduce the same height on different writing material.
%          d) If we want to study the height, we do better
%             by associate the measured height to every sign occurrence.
%             So we can correctly represent the continuity of heights.
%             Otherwise we cannot avoid arbitrary decisions.
%
% 2) There are differences in relative heights (see a107 n and a107 q).
%    It seems better, to take this as non-differentiating too,
%    but with some exceptions:
%    - stroke rows
%    - oval forms of i373 and i374
%    Why?: a), b), c) as above
%                     (but the argument isn't so strong as it is there)
%          d) as above
%    (To be carefully,
%     we would need a cluster analysis of relative heights for each sign.)
%
% 3) Given the height, there are differences in breadth
%    It seems better, to take this as non-differentiating too.
%    Why?: as for 2)
%          e) The very fine worked seal M-1305 (a107 i) seems to indicate,
%             that it was a matter of style, to give the glyph this breadth.
%             Seal M-874 -coming from the same master (or school) obviously-
%             shows the same text.
%
% 4) There are differences in the angle of main stroke.
%    It seems better, to take this as non-differentiating too.
%    Why?: a) as above
%             Many signs show,
%             that mostly there was little attention on the glyph direction.
%          d) as above
%
% 5) There are differences in the angle of the parallel strokes.
%    It's not very clear here.
%    But if we take it as possibly differentiating,
%    then we should only take three directions into account:
%    - going to the right
%    - sloping down
%    - sloping up (one raw carved tablet only?: H-309)
%
% 6) The number of parallel strokes (3-10)
%    obviously is candidate to be differentiating.
%
% 7) A look on M-488, M-748, C-14, M-1651, H-296 doesn't indicate
%    the little remaining differences to be relevant ones.
%    Mainly they follow from raw work.
%
% The points 1-4 seems to be valid for other signs too.
%
% For the sign i176  = a107
% we end up nearly with the differentiation of I. Mahadevan ((1)).
%

%%%% 3)

% a        = length of the `main' stroke
% b        = breadth, orthogonal from the main stroke
% alpha    = angle of the main stroke
% beta     = angle of the parallel strokes
% main     = the main line has to be drawn?
% nstrokes = number of parallel strokes

Fi( expr a, b, alpha, beta, main, nstrokes )(

% more simple - but it takes more memory:
%   Figure  p  =  |. a  xsh( -1/2 b );
%   Figure  q  =  ++++ line( p  xsh b );
%   ( if main:  p  +++  fi ( p , q ) ''( nstrokes, beta - alpha ) ) |> alpha

	Numer  bb  =  ( b /2 ) *2; % avoid rounding problems

	Path  r  =  stroke_p( a/2 );
	Path  p  =  r  projection( beta - alpha + 180 ) line( ( -bb/2, 0 ), 0 );

	begingroup
		if      nstrokes = 0 :
			if  main:  p      else:  zero  fi

		elseif  nstrokes = 1 :
			if  main:  p  +++  fi    ( ++++ ( mid p -- mid p |||: ) )

		elseif  main :

			Path  pp = beg p  % --             % avoid rounding problems:
			. -- ( beg p + (nstrokes-1) * ((fin p - beg p)/(nstrokes-1)) );
			Path  qq = pp  |||:  `;

			Pairv  jag   =  1/(nstrokes-1) * ( fin pp - beg pp );
			Numer  jag_y =  abs ypart jag;
			Numer  half  =  floor 1/2 nstrokes;

			Figure  c  =
				if   beta - alpha <> 90 :
					++++(  beg qq   --   beg pp  --
					.    ( beg pp + half * jag ) -- ( beg qq + half * jag )
					.   )
				else : % branch for memory efficiency only
					rect_open( half * jag_y, bb )
					.   |< 90  shi( -( bb, half * jag_y )/2  -+  beg pp )
				fi;

			for  m = 0  upto  nstrokes - 1 - half :
				if  m > 0:  +++  fi
				.  c  shi( m * jag )
			endfor
		else:
			( ++++ p, ++++ line( p |||: ) )  ''( nstrokes, beta - alpha )
		fi
	endgroup    |> alpha
);

%%%% 4)

% FI(.0003      )(x        )( $$, $ 4, 0,  90, tT,  3 );

% FI(.4320      )(t        )( $$, $ 4, 0,  90, tT,  4 );
% FI(.6213      )(u,v,w    )( $$, $ 4, 0, 110, tT,  4 );

% FI(           )(r        )( $$, $ 4, 0,  70, tT,  5 );
  FI(.1046,.2298)(i,j,k,m,n)( $$, $ 4, 0,  90, tT,  5 );
% FI(.2674      )(l,o,p,q,s)( $$, $ 4, 0, 110, tT,  5 );

% FI(.1227      )(g        )( $$, $ 4, 0,  90, tT,  6 );
% FI(.2121      )(h        )( $$, $ 4, 0, 110, tT,  6 );

% FI(.2140      )(e        )( $$, $ 4, 0,  90, tT,  7 );
% FI(           )(f        )( $$, $ 4, 0, 110, tT,  7 );

% FI(.1118      )(c,d      )( $$, $ 4, 0, 110, tT,  8 );

% FI(           )(b        )( $$, $ 4, 0, 110, tT,  9 );
.                                               % a107b: 9 or 10 strokes?

% FI(.8208      )(a        )( $$, $ 4, 0, 110, tT, 10 );

; I      =   Ip .1046
; A      =   Ap[ variant m ]

% Variants unnecessary yet are commented out for capacity reasons.

%%%% 5) variants - as glyph parts

; I\3.3  =   IP( 176 )( $ 3, $ 1.5, 180, 180+90, tT, 3 ) shi $( -0.75, 1.5 )

%%%% 6) extended variants - as glyph parts

; % none

%%%% 7) bounds
;
	iwe = !! $ 2;
	awe = !! $ 2;
;
); % i176

Dd( i177, a108 )( X_SYM  )( Y_NORM )( % s105; k099 %%%%%%%%

%%%% 3)

% a      = length of the `main' stroke
% b      = breadth, orthogonal from the main stroke
% alpha  = angle of the main stroke
% beta   = angle of the parallel strokes
% n      = number of parallel strokes
% ta     = part not to fill with parallel strokes at the bottom
% to     = part not to fill with parallel strokes at the top

Fi( expr a, b, alpha, beta, n, ta, to )(
	Figure  p  =  |. a;
	Path   pp  =  Subpath( ta * Length p, ( 1 - to ) * Length p ) of p;
	Path    q  =    line( ppath p    xsh( +1/2 b ) )
	.            -- line( ppath p `  xsh( -1/2 b ) ) -- cycle;

	( p  +++ ( q ''( n, beta - alpha, ( beg pp, fin pp ) ) ) ) |> alpha
);

%%%% 4)

% FI(     )(f,g,h)( $$, $ 6,  0,  90, 3, 0.2, 0.2 );
  FI(.2577)(b,c  )( $$, $ 6,  0,  90, 4, 0.2, 0.2 );
% FI(.3151)(d,e  )( $$, $ 6,  0,  70, 4, 0.2, 0.2 );
% FI(.1219)(a    )( $$, $ 6,  0,  90, 5, 0.2, 0.2 );

; I      =   Ip .2577
; A      =   Ap[ variant c ]

%%%% 6) extended variants - as glyph parts

; I\3.5.x  =   IP( 177 )( $ 5 , $ 2 , 0, 90, 3, 1.8/5, 0.8/5 )  ysh $ 2.5

%%%% 7) bounds
;
	iwe = !! $ 3;
	awe = !! $ 3;
;
); % i177

Dd( i178, a202 )( X_any  )( Y_NORM )( % s192; k186.100 %%%%%%%%

%%%% 3)

% a      = height of the main `A' glyph
% b      = breadth, orthogonal to the `A' (both legs taken to the bottom)
% alpha  = angle of the main `A' glyph
% beta   = angle of the sloping line of the `A' glyph
% lleft  = tT, if the left `A'-stroke is the longest
% ymid   = ypart( sloping line intersects y-axis );
%          unknown, if there is no sloping line
% part   = part to insert at bottom right
% x      = connection kind of part to insert
% sloped_part = is the part sloping as the `A'-leg (or vertically)?

Fi( expr a, b, alpha, beta, lleft, ymid, part, x, sloped_part )(
	Boolean  slop = known ymid;  % is there a sloping line?

	Pairp  NN  =  ( 0, +a/2 );
	Path   pa  =  ( NN -     ( b/2, a ) )  --  NN;
	Path   pb  =  ( NN - 8/12( b/2, a ) )  --  NN;

	Path   vl  =  if  lleft:  pa      else:  pb     fi;
	Path   vr  =  if  lleft:  pb ||   else:  pa ||  fi;

	if slop:
		Pathl  sloping_line = line( ( 0, ymid ), beta );
		Path   sloping_path =     vl  Intersectionpoint_left  sloping_line
		.                     --  vr  Intersectionpoint_left  sloping_line;
	fi

	Nangle  gamma  = Angle vr;

	Figure  vro  = if  sloped_part: ( vr |< gamma   ++(x)+-   part ) |>gamma
	.              else           :   vr            ++(x)+-   part
	.              fi;

	( vl    +++    vro    if slop: +++  sloping_path fi ) |> alpha
);

;    pit:=   ip\176   % make sure, we can access IP(176)
;
%%%% 4)

.                              %IP(176)( a,b,alpha,beta,main,n )
% (for use by i179:)
;
	Numer  lll = $ 0.5 / sind Angle( 6/2, 12 );
;
  FI(.0001)
.   (     )
.   ( $$, $ 6, 0, 75, tT,  $ 1, IP(176)($ 1,lll  ,0,90,fF,1)|>90,
.                 "alpha=n"  , tT );

% FI(.3109)
%   (m    )
%   ( $$, $ 6, 0, 75, tT,  $ 1, IP(176)($ 1,$ 1  ,0,90,fF,1)|>90,
%                 "alpha=n"  , tT );

  FI(.1401)
.   (i    )
.   ( $$, $ 6, 0, 75, tT,  $ 1, IP(176)($ 3,$ 1.5,225,225+90,tT,3)|>(135 + 90),
.                 "alpha=n"  , tT );

% FI(.1051)
%   (k,l  )
%   ( $$, $ 6, 0, 75, tT,  $ 3, IP(176)($ 3,$ 1.5,0,90,fF,3)|>90,
%                 "alpha-(0,distance_y_mid/2)=n", tT );

% FI(     )
%   (j    )
%   ( $$, $ 6, 0, 75, tT,  $ 3, IP(176)($ 3,$ 1.5,0,90,fF,3)|>90,
%                 "alpha-(0,distance_y_mid/2)=n", fF );

% FI(.2039)
%   (     )
%   ( $$, $ 6, 0, 75, tT,  $ 1, IP(176)($ 4,$ 1.5,0,90,tT,4)|>90,
%                 "alpha=n"  , tT );

% FI(     )
%   (c,d  )
%   ( $$, $ 6, 0, 75, tT,  $ 1, IP(176)($ 4,$ 1.5,0,90,tT,4)|>90,
%                 "alpha=n"  , fF );

% FI(.2170)
%   (e,f  )
%   ( $$, $ 6, 0, 75, tT,  $ 1, IP(176)($ 4,$ 1.5,0,90,fF,4)|>90,
%                 "alpha-(0,distance_y_mid/2)=n", tT );

% FI(     )
%   (g    )
%   ( $$, $ 6, 0,105, tT,  $ 1, IP(176)($ 4,$ 1.5,0,90,fF,4)|>90,
%                 "alpha-(0,distance_y_mid/2)=n", tT );

% FI(     )
%   (h    )
%   ( $$, $ 6, 0,  0, tT, unk, IP(176)($ 4,$ 1.5,0,90,fF,4)|>90,
%                 "alpha-(0,distance_y_mid/2)=n", tT );

% FI(.4341)
%   (b    )
%   ( $$, $ 6, 0, 75, fF,  $ 0, IP(176)($ 3,$ 2.0,0,70,tT,4)    ,
%                 "alpha=s" , tT );

% FI(     )
%   (a    )
%   ( $$, $ 6, 0, 75, tT,  $ 1, IP(176)($ 5,$ 1.5,0,90,fF,5)|>90,
%                 "alpha-(0,distance_y_mid/2)=n", fF );

; I\0    =   Ip .1401
;
	iwe = !! rx I\0;
	awe =  iwe;
;
; I      =   I\0  xsh( I\0.?.x_w  -+  iw )
; A      =   I
; I\1    =   Ip .0001
		% i265 assumes: rry I\1 = idy;   I\1.?.x_w = iw .
;
%% Remarks
% 1) We have made more distinctions here than we should.
% 2) i178\4341 =(H-189)= a202b: IM reads 3 strokes instead of 4 - wrongly ?
); % i178

Dd( i179, a203 )( X_any  )( Y_NORM )( % s193; k187 %%%%%%%%
;
	iwe = !! ( $ 2.75 + split_distance_default + distance_x_low );
	awe = iwe;
;
; I  .a  =   ip\178\1
; I  .h  =   I.a  xsh( -$ 3  -+  -$ 2.75 )
; I      =   I.h    +++    iiii_iiii  splitted
; A      =   I
); % i179

		begingroup %% i180 - i181

Cc( i180, i181 )( %%
	Nangle  sloping  = 110;   % upper line sloping
);

Dd( i180, a217 )( X_any  )( Y_NORM )( % s210; k205 %%%%%%%%

%%%% 2)

% 1) The upper `base' can be:                a 1-, 2-, or 3-point    path
%                           or an `egg' with a 1-, 2-, or 3-point subpath.
%    We describe this by: egg    = with egg (or without)
%    So we ignore:
%    aa) path form     - take it as straight.
%    ab) path length (especially length 0) - compute it appropriately.
%    ac) path slope    - take it as 110.
%    ba) egg form      - take it as a circle.
%    bb) egg size      - take it as computable.
%    bc) egg direction - take it as vertical.

% 2) Stripes are hanging down from the upper base.
%    We describe this by: n_top  = number of stripes
%    So we ignore:
%    aa) stripe source point distribution on path or egg
%        - take them as different and equally distributed

% 3) Some of the stripes split on the way down.
%    We describe this by: n_bot  = number of stripes at the bottom end.
%    So we ignore:
%    aa) Which stripes are splitting
%        - we choose them in the order left, right, mid.
%    ab) Multiple splitting of a stripe, at one or at two points.
%    ac) Where the splitting points are on the stripe
%        - we take the bending point as splitting point too.

% 4) The stripes change their direction on the way down
%    We describe this by: nothing
%    So we ignore:
%    aa) stripe form: curving or straight
%        - we take it as straight with one sharp bend
%    ab) the position of the bending point

% 5) The stripes are ending on different levels over ground.
%    We describe this by: nothing
%    So we ignore:
%    aa) height of the stripe end

% 6) Two naturalistic glyphs show special details of stripes and upper base.
%    We describe this by: nothing new
%    We deduce this fact from n_bot=6.
%    So we ignore:
%    aa) some differences of the naturalistic glyphs from M-9 and H-390

%%%% 1)

% point `.' means:  one occurrence only

% a217a  ( M-745  )  = egg 3  4
% a217b  ( Blk-1  )  = egg 3  4
% a217c  ( M-314  )  = egg 3  4
% a217d  ( B-17   )  = egg 3  4
% a217e  (.B-28   )  = egg 2? 4 raw
% a217f  ( C-23   )  = egg 3  3
% a217g  ( Ns-9   )  = egg 3  3
% a217h  ( C-5    )  =     3  4
% a217i  ( M-921  )  =     3  4
% a217j  (.M-9    )  =     3  6 fine naturalistic
% a217k  (.H-390  )  =     3  6 fine naturalistic
% a217l  ( M-272  )  =     3  5
% a217m  ( Krs-1  )  =     3  5
% a217n  ( M-13   )  =     3  5
% a217o  ( H-10   )  =     3  5
% a217p  ( M-45   )  =     3  4
% a217q  ( M-683  )  =     3  4
% a217r  ( M-53   )  =     3  4
% a217s  ( M-4    )  =     3  4
% a217t  ( M-1095 )  =     3  3
% a217u  ( M-42   )  =     2  4
% a217v  ( M-1221 )  =     2  4
% a217w  ( M-623  )  =     2  4
% a217x  ( IM 1033)  =     2  4
% a217y  ( M-628  )  =     2  4
% a217z  ( M-1631 )  =     2  3
%(a218a )( M-66   )  =     3  4
%(a218b )( IM 2191)  =     3  4

%%%% 3)

% a      = height of the glyph
% b      = breadth of the glyph         % unused now
% alpha  = angle of the whole glyph
% beta   = undefined yet
% egg    = `egg' at the top?
% ntop   = top stroke number
% nbot   = bottom stroke  number

Fi( expr a, b, alpha, beta, egg, ntop, nbot )(
	% sloping     = 110;   % upper line sloping - global set value

	Nangle  alf =  20; % upper stripes slope angle, as seen from the mid-line
	Nangle  bet = 150; % lower stripes slope angle, as seen from the x-axis
	Nangle  gam = sloping; %  upper path   slope angle
	Nangle  del =  80;     % middle `line' slope angle

	Numer  lbase   =  $( 2 + (ntop - 2) if egg: / 4 fi )  +  $( nbot/6 );
	Path   pbase   =  ( -1/2 lbase, 0 )  --  ( +1/2 lbase, 0 );

	Path   pmid    =  pbase  |>( del - 90 );
	Pairp  pmid_a  =  beg  pmid;
	Pairp  pmid_m  =  mid  pmid;
	Pairp  pmid_o  =  fin  pmid;

	Path   pbot    =  pmid   projection( bet )   line( ( 0, -a/2 ), 90 );
	Pairp  pbot_a  =  beg  pbot  if nbot >     ntop:  +  ( $ 0.2, 0 ) fi;
	Pairp  pbot_m  =  mid  pbot;
	Pairp  pbot_o  =  fin  pbot  if nbot > 1 + ntop:  -  ( $ 0.2, 0 ) fi;

	Numer   diameter =  lbase * sind( del - alf );

	if egg:
		Pairp  ptop_c = jet( pmid_m, alf )  where_y  ( a/2 - diameter/2 );
		Path   ptop   = circle_p( 1/2 diameter )  shi ptop_c;
		Pairp  ptop_a = ptop Intersectionpoint_left jet( ptop_c, alf+270 );
		Pairp  ptop_m = ptop Intersectionpoint_left jet( ptop_c, alf+180 );
		Pairp  ptop_o = ptop Intersectionpoint_left jet( ptop_c, alf+ 90 );
	else  :
		Pairp  ptop_a = jet( pmid_a, alf )  where_y  ( a/2 );
		Path   ptop   = pmid  projection( alf )  line( ptop_a, gam );
		Pairp  ptop_m = mid  ptop;
		Pairp  ptop_o = fin  ptop;
	fi

	Figure ftop        =  ++++ ptop; % needs to be communicated to i181
	upper_line_figure :=       ftop;

	if nbot < 6 : % i.e. not naturalistic
		( ftop
		.   .                    +++ ( ptop_a  --  pmid_a  --  pbot_a )
		.   .                    +++ ( ptop_o  --  pmid_o  --  pbot_o )
		.   if ntop > 2       :  +++ ( ptop_m  --  pmid_m  --  pbot_m ) fi
		.   if nbot >     ntop:  +++ ( pmid_a -- ( pbot_a - $(1.5,0) ) ) fi
		.   if nbot > 1 + ntop:  +++ ( pmid_o -- ( pbot_o + $(1.5,0) ) ) fi
		) |>alpha
	else:
		Path   pslope =    ( -$ 0.5, -$ 6 ) .. ( $ 0.3, -$ 1 ) .. ( 0, 0 )
		.               .. ( -$ 0.3, -$ 1 ) .. ( $ 0.5, -$ 6 );
		Figure fslope = ++++ pslope;

		Path  prgt  = Subpath( 2/9, 6/9 ) of ( ptop_o -- pmid_o );
		Path  plft  = ptop_a -- pmid_a;

		( ftop
		.   .                 +++ ( ptop_a  --  pmid_a )
		.   .                 +++ ( ptop_m  --  pmid_m )
		.   .                 +++ ( ptop_o  --  pmid_o )
		.   +++  ( ++++ prgt, ++++ plft ) ''( 3, gam )
		.   +++  fslope  Scaled(( -a/2 -+ ypart pmid_a ) / $ 6 )  shi pmid_a
		.   +++  fslope  Scaled(( -a/2 -+ ypart pmid_m ) / $ 6 )  shi pmid_m
		.   +++  fslope  Scaled(( -a/2 -+ ypart pmid_o ) / $ 6 )  shi pmid_o
		)  |> alpha
	fi
);

%%%% 4)

FIGURE  upper_line_figure;

  FI(.1552,.2465,.1175,.2191,.1052)
.   (h,i,p,q,r,s)( $$, $ 6, 0, 90, fF, 3, 4 );

% FI(.1069      )
%   (l,m,n,o    )( $$, $ 6, 0, 90, fF, 3, 5 );

% FI(.2049      )
%   (t          )( $$, $ 6, 0, 90, fF, 3, 3 );

% FI(.1033      )
%   (u,v,w,x,y  )( $$, $ 6, 0, 90, fF, 2, 4 );

% FI(.2495      )
%   (z          )( $$, $ 6, 0, 90, fF, 2, 3 );

% FI(.2616      )                             % M-9, H-390
%   (j,k        )( $$, $ 6, 0, 90, fF, 3, 6 );

% FI(           )
%   (e          )( $$, $ 6, 0, 90, tT, 2, 4 );

% FI(.6402      )
%   (f,g        )( $$, $ 6, 0, 90, tT, 3, 3 );

% FI(           )
%   (a,b,c,d    )( $$, $ 6, 0, 90, tT, 3, 4 );


; I\0    =   Ip .1552
;
	iwe = !! rx I\0;
	awe = iwe;
;
; I      =   I\0  xsh( I\0.?.x_w  -+  iw )
; I  .n  =   upper_line_figure  xsh( I\0.?.x_w  -+  iw )
; A      =   I                % Ap[ variant r ] xsh ...
); % i180

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% end of producing glyph variants too

Dd( i181 )( X_any  )( Y_NORM )( % s211; k206.457
; I  .a  =   ip\180
; I  .c  =   ip\053.z
; I  .x  =   I.c  |>( sloping - 90 )
; I  .y  =   I.x  Scaled( ( ypart( ip\180.n.?.omega ) -+ in )/( I.x.?.y_n ))
; I  .nne=   I.y  shi( OQ  -+  ip\180.n.?.omega )
; I      =   I.a    +++    I.nne
;
	iwe = ( iw\180, max( ie\180, I.nne.?.x_e ) );
;
);

		endgroup ; %% i180 - i181

Dd( i182 )( X_SYM  )( Y_NORM )( % s307; k303
;
	iwe = !! $ 5;         % let idx\183 = $$
;
; I  .a  =   R_bend_very_thin
;
	NUMER  sh, oh, nh;    sh + oh + nh = idy;
	oh  =  $ 2;
	sh  =  nh;
;
	Numer  wid = idx - 2/3 * 2 rrx I.a;
;
; I  .w  =   I.a  xsh( xpart( I.a.?.alpha )  -+  iw )
; I  .e  =   I.w  ||
; I  .o  =   ( I.w , I.e ) ''( 2, 90, ( (0, -oh/2), (0, +oh/2) ) )
; I  .s  =   rect_open( wid/3, sh )  ysh( -sh/2  -+  is )
; I      =   I.w    +++    I.e    +++    I.o    +++    I.s
);

Dd( i183 )( X_any  )( Y_NORM )( % s308; k304
;
	iwe = iwe\182 + ( - bridge_width_default_wide, 0 );
;
; I  .w  =   |. idy  xsh( 0  -+  iw )
; I  .e  =   ip\182
;
	Pairp  XX  =  ( iw, -$ 0.7 );
	Pairp  YY  =  ip\182.w  where_y  +$ 0.7;
;
; I  .o  =   ++++( XX -- YY )
; I      =   I.w    +++    I.o    +++    I.e
);

		begingroup %% i184 - i185

Cc( i184, i185 )( %%
	Pair     iwe_base = !! $ 4.5;
;
	NUMER  sh, oh, nh;    sh + oh + nh = idy_base;
	oh  =  $ 2.5;
	sh  =  nh;
;
	NUMER  wb, ob, eb;    wb + ob + eb = $$;
	ob  =  idx_base;
	wb  =  eb;
);

Dd( i184 )( X_EQB  )( Y_NORM )( % s; k043.369
;
	iwe = !! ( $$/2 );
;
; I  .c  =   ip\176\3.3                      % width = wb = $ 1.5
; I  .d  =   ip\155   scx( 2 eb )
; I  .s  =   rect_open( ob, (sh+oh) )  ysh( -(sh+oh)/2  -+  is )
; I  .n  =   I.s  |:
; I  .sn =   rect_open( $ 4, (sh+oh) )  ysh( -(sh+oh)/2  -+  is )
; I  .o  =   |. oh
; I  .nw =   I.c  shi( ~.?.ne  -+  ( iw_base, in ) )
; I  .ne =   I.d  shi( ~.?.n   -+  ( ie_base, in ) )
; I  .h  =   I.s    +++    I.n
; I      =   I.h    +++    I.sn    +++    I.o    +++    I.nw    +++    I.ne
);

Dd( i185 )( X_SYM  )( Y_NORM )( % s; k299
;
	iwe = iwe_base;
;
; I  .h  =   ip\184.h
; I  .b  =   rectangle( 1/2 ob, oh )
; I  .c  =   |. idy
; I      =   I.h    +++    I.b    +++    I.c
);

		endgroup ; %% i184 - i185

		begingroup %% i186 - i187

Cc( i186, i187 )( %%
	Pair     iwe_base = !! $ 3;
;
	Numer  oh  =  $ 4;
);

Dd( i186 )( X_SYM  )( Y_NORM )( % s301; k296
;
	iwe = iwe_base;
;
; I  .w  =   |. idy  xsh( 0  -+  iw )
; I  .e  =   |. idy  xsh( 0  -+  ie )
; I\1.we =   rectangle( idx, oh )  ''( 1, 90 )
; I  .we =   rectangle( idx, oh )    +++    I\1.we
; I      =   I  .w    +++    I  .we    +++    I.e
; I\1    =   I  .w    +++    I\1.we    +++    I.e     % for 316
);

Dd( i187 )( X_any  )( Y_NORM )( % s304; k300
; I  .h  =   ip\186
; I  .b  =   R_bend_medium
; I  .e  =   I.b  xsh( I.b.?.x_w  -+  ie_base )
; I  .ne =   ip\006.ne  xsh ie_base
; I      =   I.h    +++    I.e    +++    I.ne
;
	iwe = iwe_base  +  ( 0, max( rrx I.b, ie\006 ) );
;
);

		endgroup ; %% i186 - i187

		begingroup %% i188 - i203

Cc( i188, i203 )( %%
	Pair     iwe_base = !! $ 4.5;
;
	NUMER  sh, oh, nh;    sh + oh + nh = idy_base;
	oh  =  $ 4;
	sh  =  nh;
;
	Numer  shoh  =  sh + oh;
	Numer  ohnh  =  oh + nh;
);

Dd( i188 )( X_SYM  )( Y_NORM )( % s299; k295
;
	iwe = iwe_base;
;
; I  .h  =   ip\202
; I  .s  =   rect_open( idx/3, shoh )  ysh( -shoh/2  -+  is )
; I      =   I.h    +++    I.s
);

Dd( i189 )( X_SYM  )( Y_NORM )( % s309; k305
;
	iwe = iwe_base;
;
; I  .a  =   ip\202.a  |:
; I  .b  =   I.a  Xscaled 1/3
; I      =   I.a    +++    I.b
);

Dd( i190 )( X_SYM  )( Y_NORM )( % s310; k306
; I  .b  =   ip\161\1
;
	iwe = iwe_base  +  I.b.?.we;
;
; I  .x  =   I.b  xsh -1/3 idx_base    +++    I.b  xsh +1/3 idx_base
; I  .n  =   I.x  xsh -1/6 idx_base    +++    I.x  xsh +1/6 idx_base
; I  .c  =   rectangle( idx_base, 2/3 sh )
; I  .s  =          I.c  ysh( -(2/3 sh)/2  -+    is )
.            +++    I.c  ysh( -(2/3 sh)/2  -+  ( is + 1/3 sh ) )
; I      =   I.s    +++    I.n
);

Dd( i191 )( X_any  )( Y_NORM )( % s311; k307
; I  .h  =   ip\202  |:
; I  .s  =   rectangle( 1/3 idx_base, sh )  ysh( -sh/2  -+  is )
; I  .ne =   ip\006.ne  xsh ie_base
; I      =   I.h    +++    I.s    +++    I.ne
;
	iwe = ( iw_base, I.ne.?.x_e );
;
);

Dd( i192 )( X_SYM  )( Y_NORM )( % s312; k308
;
	iwe = iwe_base;
;
; I  .n  =   ++++ ( iWN  --  OQ  --  iEN )
; I  .s  =   rect_open( idx, idy )  |:
; I  .o  =   |. idx  |>90
; I  .h  =   I.s    +++    I.o
; I      =   I.h    +++    I.n
);

Dd( i193 )( X_SYM  )( Y_NORM )( % s; k
;
	iwe = iwe_base;
;
	Path  p  =  iWN  --  OQ  --  iWO  --  cycle;
;
; I  .h  =   ip\192
; I  .nw =   p  ''( 2, 70, ( 0.37[ iWN, OQ ], 0.68[ iWN, OQ ] ) )
; I  .ne =   I.nw ||
; I  .s  =   rect_open( idx/3, idy/2 )  ysh( -(idy/2)/2  -+  is )
; I      =   I.h    +++    I.s    +++    I.nw    +++    I.ne
);

Dd( i194 )( X_SYM  )( Y_NORM )( % s292; k288
;
	iwe = !! ( $$/2 );
;
	Numer  ob   =  3/2 stroke_distance_x;
	Numer  nh   =  $ 2;
;
	Pairp  WSW  =  iWS  ysh $ 1.5;
	Pairp  SSW  =  iWS  xsh( $ 2 +-+ $ 1.5 );
	Pairp  NW   =  iON  - ( ob, nh );
;
	Path   west =  WSW  --  SSW  --  NW;
	Path   east =  west  ||;
	Path   pp   =  west  --  east `;
;
	Path    psw =  ( WSW -- SSW )
	.              shi( stroke_distance_y * unitvector( SSW -+ NW ) );
	Figure  fsw =  ++++ psw;
	Figure  fse =  fsw  ||;
;
; I  .h  =   pp    +++    fsw    +++    fse
; I  .s  =   tri_open( unk, ($ 4) )  ysh( -($ 4)/2  -+  is )  +++  ip\003.s
; I  .n  =   ip\087  ysc nh  ysh( +nh/2  -+  in )
; I      =   I.h    +++    I.n    +++    I.s
);

Dd( i195 )( X_SYM  )( Y_NORM )( % s290; k285
;
	iwe = iwe_base;
;
; I  .n  =   rect_open( idx, ohnh )  ysh( +ohnh/2  -+  in )
; I  .s  =   ip\155.n  ysh( 0 -+ is )
; I      =   I.s    +++    I.n
);

Dd( i196 )( X_SYM  )( Y_ROOF )( % s291; k286
; I  .n  =   ip\195\n  ysh( yn_normal  -+  yn_shrinked )
; I  .s  =   ip\195.s
; I\1    =   I.n    +++    I.s
; I      =   I\1  roofed( r_sloping )
;
	iwe = !! ( ( fig_right I ).?.x_e );
;
);

			begingroup %% i197 - i198

Cc( i197, i198 )( %%
	NUMER  sh, oh, nh;    sh + oh + nh = idy_base;
	nh  =  $ 3;
	sh  =  $ 6;
;
	Numer  shoh  =  sh + oh;
);


Dd( i197 )( X_SYM  )( Y_NORM )( % s293; k289
;
	iwe = iwe_base;
;
; I  .s  =   rect_open( idx, shoh )  ysh( -shoh/2  -+  is )
; I  .n  =   square.  ( nh )         ysh( +nh/2    -+  in )
; I      =   I  .s    +++    I.n
; I\3.s  =   rect_open( $ 4, shoh )  ysh( -shoh/2  -+  is )
; I\3    =   I\3.s    +++    I.n
);

Dd( i198 )( X_SYM  )( Y_NORM )( % s294; k290
;
	iwe = iwe_base;
;
; I  .h  =   ip\197
; I  .a  =   rectangle( 2/4 * idx, oh )
; I  .b  =   |. oh
; I  .x  = ( I.a    +++    I.b )  ysh( -oh/2 -+ ( is + sh ) )
; I  .c  =   |. idx  |>90  ysh( 0  -+  ( is + sh ) )
; I  .o  =   I.c    +++    I.x
; I      =   I.h    +++    I.o
);

			endgroup ; %% i197 - i198

Dd( i199 )( X_SYM  )( Y_NORM )( % s; k292.773
;
	iwe = iwe_base;
;
; I  .s  =   rect_open( idx, shoh )  ysh( -shoh/2  -+  is )
; I  .n  =   ip\166\6.n  ysh( +nh/2  -+  in )
; I      =   I.s    +++    I.n
);

Dd( i200 )( X_EQB  )( Y_NORM )( % s296; k292.371
;
	iwe = iwe_base;
;
; I  .b  =   ip\176  Scaled( nh / idy\176 )
; I  .n  =   I.b  ||  ysh( +nh/2  -+  in )
; I  .s  =   ip\199.s
; I      =   I.s    +++    I.n
);

Dd( i201 )( X_SYM  )( Y_NORM )( % s276; k272
;
	iwe = iwe_base;
;
; I  .h  =   rectangle( idx, idy )
; I  .s  =   ip\188.s
; I      =   I.h    +++    I.s
);

Dd( i202 )( X_SYM  )( Y_NORM )( % s297; k293.057
;
	iwe = iwe_base;
;
; I  .a  =   rect_open( idx, idy )
; I  .b  =   |. idx  |>90  ysh( 0  -+  ( in - nh ) )
; I      =   I.a    +++    I.b
);

Dd( i203 )( X_SYM  )( Y_ROOF )( % s298; k294
; I  .h  =   ip\202
; I\1    =   I.h  Transformed ysc_shrink
; I      =   I\1  roofed( r_sloping )
;
	iwe = !! ( ( fig_right I ).?.x_e );
;
);

		endgroup ; %% i188 - i203

		begingroup %% i204 - i210

Cc( i204, i210 )( %%
	Pair     iwe_base = !! $ 4.5;
);

Dd( i204 )( X_SYM  )( Y_NORM )( % s215; k210.104
;
	iwe = iwe_base;
;
; I\1    =   triangle( idx, idy )
; I\3    =   I\1  +++  I\1 ''( 2, 90,( 0.29[ iOS, iON ], 0.58[ iOS, iON ] ))
; I      =   I\1  +++  I\1 ''( 3, 90,( 0.23[ iOS, iON ], 0.68[ iOS, iON ] ))
);

Dd( i205 )( X_any  )( Y_NORM )( % s216; k210.223
;
		% There is some freedom to choose the width,
		% so we choose to make the dimensions equal to those of i416.
;
	iwe = iwe\416;
;
	Pairp  PP  = $( -2, -4.5 );
	Pairp  QQ  = $( -1,  6   );
	Pairp  RR  = $(  2, -6   );
;
	Path   pq  =   PP .. $( 0,1 ) .. QQ;
	Path   qr  =   QQ .. $( 3,0 ) .. RR;
	Path   rp  =   RR       --       PP;
;
	Path  pqr  =   pq  &  qr  &  rp;
;
	Pairp  XX  =   whatever[ RR, PP ];     ypart XX  =  $ 3;
	.        % ( jet( RR, PP )  where_y  $ 3 : more effort & inexact )
;
	Nangle  xp  =  Angle( XX  -+  PP );
	Nangle  xq  =  Angle( XX  -+  QQ );
;
; I  .h  =   ++++ pqr
; I\0    =   I.h    +++    pqr ''( 3, XX, ( 90 , 2/3[90, xp] ) )
; I\1    =   I\0  xsh( PP  -+   OQ )
; I\2    =   I\1  Xscaled( idx / ( xpart PP -+ qr.?.x_e ) )
; I      =   I\2  xsh( 0  -+  iw )
);

Dd( i206 )( X_SYM  )( Y_ROOF )( % s217; k211
; I  .a  =   ip\204  Transformed ysc_shrink
; I  .b  =   ++++ ( ( 0, yn_high )  --  ( 0, yn_shrinked ) )
; I  .h  =   I.a  roofed( r_straight )
; I  .x  =   fig_right I.h
; I  .n  =   I.b    +++    I.x
; I      =   I.a    +++    I.n
;
	iwe = !! max( ie_base, I.x.?.x_e );
;
);

Dd( i207 )( X_SYM  )( Y_ROOF )( % s218; k212
; I  .a  =   ip\206.a
; I  .b  =   ip\206.b
; I  .h  =   I.a    +++    I.b
; I\1    =   I.h  roofed( r_sloping )
;
	iwe = !! ( I\1.?.x_e  +  split_distance_default  +  0 );
;
; I      =   I\1    +++    ii_ii  splitted
);

Dd( i208 )( X_SYM  )( Y_ROOF )( % s219; k213
; I  .h  =   ip\206.h
; I  .b  =   ip\206.n  Scaled 0.5  ysh( 1/2 yn_shrinked  -+  yn_shrinked )
; I      =   I.h    +++    I.b
;
	iwe = iwe\206;
;
);

Dd( i209 )( X_SYM  )( Y_NORM )( % s213; k208
;
	iwe = iwe_base;
;
; I      =   ip\204\1    +++    |. idy
);

Dd( i210 )( X_SYM  )( Y_NORM )( % s214; k209
;
	iwe = iwe_base;
;
; I      =   ip\204      +++    |. idy
);

		endgroup ; %% i204 - i210

		begingroup %% i211 - i213

Cc( i211, i213 )( %%
	NUMER  sh, nh;    sh + nh = idy_base;
	nh  =  $ 4;
;
	Pair     iwe_base = !! ( teqla_s( nh ) / 2 );
);

Dd( i211 )( X_SYM  )( Y_NORM )( % s224; k217
;
	iwe = iwe_base;
;
; I  .s  =   |. sh  ysh( -sh/2  -+  is )
; I  .n  =   triangle( idx, nh )  ysh( +nh/2  -+  in )
; I      =   I.s    +++    I.n
);

Dd( i212 )( X_SYM  )( Y_NORM )( % s101; k094
;
	iwe = !! $ 4;
;
; I  .h  =   ip\211
; I  .n  =   rect_open( idx, nh )  |:  ysh( +nh/2  -+  in )
; I      =   I.h    +++    I.n
);

Dd( i213 )( X_SYM  )( Y_NORM )( % s; k
; I  .s  =   ip\211.s
; I  .n  =   ip\211.n  |:  ysh sh
; I  .o  =   ip\155.we  |:  ysh( ~.?.y_s  -+  0 )
; I      =   I.s    +++    I.n    +++    I.o
;
	iwe = !! max( ie_base, xpart( I.o.?.omega ) );
;
);

		endgroup ; %% i211 - i213

		begingroup %% i214 - i228

Cc( i214, i228 )( %%
 % parameter begin
	Numer  r_x  =  $ 4;        % half width
	Numer  r_y  =  $ 6;        % half height

	Pairv  jaw  =  1/3 ( r_x , r_y ); % or?: |.$ ( 2 ++ 2 ) `  |< 45

	Numer length_a = $ 1.5; % stroke length in stroke triples: i223,i224,i227
 % parameter end

	Pairp  NE  =  ( +r_x , +r_y );
	Pairp  SE  =  ( +r_x , -r_y );
	Pairp  SW  =  ( -r_x , -r_y );
	Pairp  NW  =  ( -r_x , +r_y );

	NUMER  cutted_length;
	cutted_length / length_a = r_x / r_y;

	Pairp  NE_short   =  NE  -  cutted_length * unitvector NE;
	Pairp  SE_short   =  SE  -  cutted_length * unitvector SE;

	Pairp  NE_x       =  NE       + jaw |:;
	Pairp  SE_x       =  SE       + jaw   ;
	Pairp  NE_short_x =  NE_short + jaw |:;
	Pairp  SE_short_x =  SE_short + jaw   ;

	Path  loop         =               SE       -- NW -- SW -- NE        ;
	Path  loop_x       =       SE_x -- SE       -- NW -- SW -- NE
	.                                                       -- NE_x      ;
	Path  loop_short   =               SE_short -- NW -- SW -- NE_short  ;
	Path  loop_short_x = SE_short_x -- SE_short -- NW -- SW -- NE_short
	.                                                       -- NE_short_x;

	Pair  iwe_base         = ( xpart SW, xpart NE         );
	Pair  iwe_base_x       = ( xpart SW, xpart NE_x       );
	Pair  iwe_base_short   = ( xpart SW, xpart NE_short   );
	Pair  iwe_base_short_x = ( xpart SW, xpart NE_short_x );

	Nangle  angle_se_nw  =  Angle( SE -- NW );

	Path    jaw_path     =  OQ -- ( OQ + jaw );
); %%

Dd( i214 )( X_SYM  )( Y_NORM )( % s229; k224
;
	iwe = iwe_base;
;
; I      =   ++++ (  loop -- cycle )
);

Dd( i215 )( X_any  )( Y_NORM )( % s231; k226
;
	save fac;  def  fac = 5/6  enddef;
;
	iwe = iwe_base  +  ( 0, fac ie_base );
;
; I  .h  =   ip\214
; I  .w  =   I.h  Scaled( ( ie_base - 0.7 stroke_distance_x ) / ie_base )
; I  .b  =   ++++ ( OQ  --  fac SE  --  fac NE  --  cycle )
; I  .x  =   I.b  Scaled( ( ie_base - 0.7 stroke_distance_x ) / ie_base )
; I  .e  = ( I.b    +++    I.x )  xsh( 0  -+  ie_base )
; I      =   I.h    +++    I.w    +++    I.e
);

Dd( i216 )( X_any  )( Y_NORM )( % s235.2; k230.241
;
	iwe = iwe_base_x;
;
; I      =   ++++ loop_x
);

Dd( i217 )( X_SYM  )( Y_NORM )( % s; k
; I  .w  =   ip\216  xsh( second iwe_base_x  -+  -1/2 distance_x_low )
; I  .e  =   I.w  ||
; I\0    =   I.w    +++    I.e
; I      =   I\0
;
	iwe = !! 1/2 distance_x_low  +  !!( first iwe_base_x -+ second iwe_base_x );
;
  if  idx > dx_high :
; I     :=   reduce_width( I.w, I.e )
;
	iwe := !! ( dx_high/2 );
	isn := I.?.sn;
;
  fi
);

Dd( i218 )( X_SYM  )( Y_NORM )( % s; k
;
	iwe = !! ( ie\328  +  split_distance_default
	.                  +  ( first iwe_base_x  -+  second iwe_base_x ) );
;
; I  .w  =   ip\217.w
; I  .e  =   ip\217.e
; I  .o  =   ip\328
; I  .we =   ip\217\0
; I      =   I.o    +++    I.we  splitted
;
  if  idx > dx_high :
; I     :=   reduce_width( I.w, I.o, I.e )
;
	iwe := !! ( dx_high/2 );
	isn := I.?.sn;
;
  fi
);

Dd( i219 )( X_any  )( Y_NORM )( % s237; k232
;
	iwe = iwe_base_x;
;
; I  .h  =   ip\216
;
	Path  p  =  ppath( oval_narrow. in )  ysh( +in/2  -+  in );
	Pair  tt =  p  intersectiontimes  loop_x;
;
	Path  north  =  subpath( first tt, -first tt - 1 ) of p;
	Path  south  =  north  |:;
;
; I      =   I.h    +++    south    +++    north
);

Dd( i220 )( X_any  )( Y_NORM )( % s238; k233
;
	iwe = iwe_base_x  +  !! split_distance_default  +  !! 0;
;
; I      =   ip\219    +++    ii_ii  splitted
);

Dd( i221 )( X_any  )( Y_NORM )( % s236; k231
;
	iwe = iwe_base_x;
;
; I      =   ip\216    +++    |. idy
);

Dd( i222 )( X_any  )( Y_NORM )( % s235.1; k230.033
;
	iwe = iwe_base_x;
;
; I  .c  =   ++++ jaw_path
; I  .s  =   I.c  shi( OQ  -+  ( SE  xsh( - 2 xpart jaw ) ) )
; I      =   ip\216   +++    I.s
);

Dd( i223 )( X_any  )( Y_NORM )( % s242; k237
;
	iwe = iwe_base_short_x;
;
; I  .h  =   ++++ loop_short_x
; I  .b  =   ip\176\3.3                      % $ 3 = 2 length_a
; I  .sse=   I.b  |> angle_se_nw  shi( OQ  -+ SE_short )
; I  .nne=   I.sse  |:
; I  .e  =   I.sse    +++    I.nne
; I      =   I.h      +++    I.e
);

Dd( i224 )( X_any  )( Y_NORM )( % s243; k238
; I  .h  =   ++++ loop_short
; I  .e  =   ip\223.e
; I  .c  = ( |. ($ 3)  ysh( -($ 3)/2  -+  0 )
.            +++  ip\176\3.3  ysh( 0  -+  ($ 3) ) ) |<135  % $ 3 = 2 length_a
; I  .wsw=   I.c  xsh( 0  -+  iw_base )
; I      =   I.h    +++    I.e    +++    I.wsw
;
	iwe = iwe_base_short  +  ( I.c.?.x_w, 0 );
;
);

Dd( i225 )( X_any  )( Y_NORM )( % s232; k227
;
	iwe = iwe_base;
;
; I      =   ++++ loop
);

Dd( i226 )( X_any  )( Y_NORM )( % s234; k229
;
	iwe = iwe_base  +  ( 0, 2 xpart jaw );
;
; I  .h  =   ip\225
; I  .c  =   ++++ ( jaw_path || `   &   jaw_path )
; I  .nne=   I.c  shi( jaw  -+  iEN )
; I      =   I.h    +++    I.nne
);

Dd( i227 )( X_any  )( Y_NORM )( % s; k
; I  .h  =   ip\225
; I  .wsw=   ip\224.wsw
; I      =   I.h    +++    I.wsw
;
	iwe = ( iw\224, ie_base );
;
);

Dd( i228 )( X_any  )( Y_NORM )( % s; k
;
	iwe = iwe_base;
;
	NUMER  sh, oh, nh;    sh + oh + nh = idy;
	oh  =  distance_y_mid;
	sh  =  nh;
;
; I  .a  =   ip\225  ysc nh
; I  .n  =   I.a  ysh( +nh/2  -+  in )
; I  .s  =   I.a  ysh( -sh/2  -+  is )
; I  .o  =   ++++ ( ( 0, is + sh/2 )   --   ( 0, in - nh/2 ) )
; I      =   I.n    +++    I.s    +++    I.o
);

		endgroup ; %% i214 - i228

Dd( i229 )( X_any  )( Y_any  )( % s225; k220
;
	iwe = !! $ 6;
;
		% compute the sides of the little triangle at ne, above the figure:
	Numer  ne_diagon =  stroke_distance_x / sind 60;
	Numer  ne_x_side =  ne_diagon * sind 60 / sind 90;
	Numer  ne_y_side =  ne_diagon  +-+  ne_x_side;
;
		% ne_x_side is the excess, we get by lengthening the main `X', so
	Numer  tria_h    =  ( idx + ne_x_side ) / 2;
	Numer  tria_side =  teqla_s( tria_h );
;
	isn = !! ( tria_side/2 );
;
	Pairp  NNE =  ( ie - ne_x_side, in );
	Pairp  ENE =  ( ie, in - ne_y_side );
	Pairp  ONW =   NNE  projection( -120 )  ( iWN  --  ENE |: );
;
	Path  p = ONW -- NNE -- ENE -- iWS -- iWN -- ENE |: -- NNE |: -- ONW |:;
;
; I      =   ++++ p
);

Dd( i230 )( X_SYM  )( Y_NORM )( % s222; k215.105
;
	iwe = !! $ 6;
;
; I  .a  =   triangle( idx/3, idy )
; I  .w  =   I.a  xsh( -(idx/3)/2  -+  iw )
; I  .e  =   I.a  xsh( +(idx/3)/2  -+  ie )
; I      =   I.w    +++    I.a    +++    I.e
);

Dd( i231 )( X_SYM  )( Y_NORM )( % s223; k216
;
	iwe = !! $ 6;
;
	NUMER  sh, oh, nh;    sh + oh + nh = idy;
	oh  =  distance_y_mid;
	sh  =  nh;
;
; I  .a  =   ip\230  ysc nh  ysh( -nh/2  -+  0 )
; I  .n  =   I.a  ysh( nh  -+  in )
; I  .s  =   I.n  |:
; I      =   I.n    +++    I.s
);

Dd( i232 )( X_SYM  )( Y_NORM )( % s; k113
;
	iwe = !! $ 6;
;
	NUMER  sh, nh;    sh + nh = idy;
	nh  =  sh + distance_y_mid;
;
; I  .s  =   ip\231.n  ysh -nh
; I  .n  =   ip\326\1  Scaled( nh / idy\326 )  ysh( +nh/2  -+  in )
; I      =   I.s    +++    I.n
);

		begingroup %% i233 - i235

Cc( i233, i235 )( %%
	Numer  c  =  $ 3;        % half triangle side
	Numer  b  =  2c  +-+  c;

	Pair   iwe_base = !! good.x b;

	Pairp  ESE  =  ( ie_base, is_base/2 );
);

Dd( i233 )( X_EQB  )( Y_NORM )( % s226; k221
;
	iwe = iwe_base;
;
	Path  p  =  iOS -- iON -- ESE |: -- ESE || -- ESE |||: -- ESE -- cycle;
;
; I      =   ++++ p
);

Dd( i234 )( X_EQB  )( Y_ROOF )( % s227; k222
;
	iwe = !! $ 6;
;
; I  .a  =   ip\233  Transformed ysc_shrink
; I      =   I.a  roofed( r_straight, idx )
);

Dd( i235 )( X_any  )( Y_NORM )( % s228; k223
; I  .h  =   ip\233
; I  .ene=   ip\166\4.n  ysh( +($ 4)/2  -+  in )
; I      = ( I.h  ++("")+-  I.ene )  connected( ESE, 90, "s", 0 )
;
	iwe = ( iw_base, ( fig_right I ).?.x_e );
;
);

		endgroup ; %% i233 - i235

Dd( i236 )( X_any  )( Y_NORM )( % s; k396
;
	iwe = !! $ 6;
;
	Numer  q = $ 4; % ? ( 3++3 )
;
; I  .a  =   square. idy
; I  .b  =   square( q )
; I  .nw =   I.b  shi( ( -q/2, q/2 )  -+  iWN )
; I\1    =   I.a    +++    I.nw
; I  .o  =   ip\120  Scaled 9/12  xsh 1/2 q
; I      =   I\1    +++    I.o
);

		begingroup %% i237 - i243

Cc( i237, i243 )( %%
	Pair     iwe_base = !! $ 2;
);

Dd( i237 )( X_SYM  )( Y_NORM )( % s266; k262
;
	iwe = iwe_base;
;
; I      =   rectangle( idx, idy )
);

Dd( i238 )( X_SYM  )( Y_NORM )( % s268; k264
;
	iwe = iwe_base;
;
; I      =   ip\237    +++    rectangle( idx, idy/6 )
);

Dd( i239 )( X_EQB  )( Y_NORM )( % s271; k267
;
	iwe = iwe_base;
;
; I  .w  =   ip\241  scx( idx/2 )  xsh( -(idx/2)/2  -+  iw )
; I      =   ip\237    +++    I.w
);

Dd( i240 )( X_SYM  )( Y_any  )( % s265; k355.415
;
	isn = !! $ 3;
	iwe = iwe_base;
;
; I      =   rectangle( idx, idy )
);

Dd( i241 )( X_SYM  )( Y_any  )( % s267; k
;
	isn = !! $ 4;
	iwe = iwe_base;
;
; I  .h  =   rectangle( idx, idy )
; I  .o  =   |. idx  |>90
; I      =   I.h    +++    I.o
);

Dd( i242 )( X_EQB  )( Y_NORM )( % s269; k265
;
	iwe = 2 iwe_base;
;
	NUMER  wb, eb;    wb + eb = idx;
	wb  =  eb;
;
; I  .a  =   ip\241  ysc idy
; I  .b  =   ip\237
; I  .w  =   I.a  xsh( -wb/2  -+  iw )
; I  .e  =   I.b  xsh( +eb/2  -+  ie )
; I      =   I.w    +++    I.e
);

Dd( i243 )( X_EQB  )( Y_NORM )( % s270; k266
;
	iwe = 2 iwe_base;
;
; I  .h  =   ip\242
; I  .c  =   ip\328  scx 1/2 ie
; I  .o  =   I.c  xsh( 0  -+  ie/2 )
; I      =   I.h    +++    I.o
);

		endgroup ; %% i237 - i243

		begingroup %% i244 - i246

Cc( i244, i246 )( %%
	Pair     iwe_base = !! $ 4.5;
);

Dd( i244 )( X_SYM  )( Y_NORM )( % s274.2; k270.066
;
	iwe = iwe_base;
;
; I  .h  =   rectangle( idx, idy )
; I  .b  =   ip\176  Scaled( idx / idy\176 )
; I  .n  =   I.b  |>90  ysh( +(idx/3)/2  -+  in )      % i176: idx/idy=1/3
; I  .s  =   I.n  |:
; I      =   I.h    +++    I.s    +++    I.n
);

Dd( i245 )( X_SYM  )( Y_NORM )( % s273.2; k268.069
;
	iwe = iwe_base;
;
; I  .h  =   rectangle(     idx,     idy )
; I  .sn =   rectangle( 1/3 idx,     idy )
; I  .we =   rectangle(     idx, 1/3 idy )
; I      =   I.h    +++    I.sn    +++    I.we
);

Dd( i246 )( X_any  )( Y_NORM )( % s; k269
;
	iwe = iwe_base  +  ( -bridge_width_default_wide, 0 );
;
; I      = ( |. idy    +-("")++    ip\245 )  connected( $ 3, $ 1 )
);

		endgroup ; %% i244 - i246

		begingroup %% i247 - i248

Cc( i247, i248 )( %%
	Pair     iwe_base = !! $ 5;
);

Dd( i247 )( X_SYM  )( Y_any  )( % s272; k380
;
	isn = iwe_base;
	iwe = iwe_base;
;
; I  .a  =   square. 1/2 idx    +++    |. $ 2
; I  .b  =   I.a  xsh( iw/2  -+  iw )    +++    I.a  xsh( ie/2  -+  ie )
; I      =   I.b  ysh( is/2  -+  is )    +++    I.b  ysh( in/2  -+  in )
);

Dd( i248 )( X_any  )( Y_NORM )( % s; k
;
	iwe = iwe_base  +  ( -bridge_width_default_wide, 0 );
;
; I      = ( |. idy    +-("")++    ip\247 )  connected( $ 3, $ 1 )
);

		endgroup ; %% i247 - i248

		begingroup %% i249 - i256

Cc( i249, i256 )( %%
	Pair     iwe_base = !! $ 3;
);

Dd( i249 )( X_SYM  )( Y_NORM )( % s279; k276
;
	iwe = iwe_base;
;
	NUMER  sh, nh;    sh + nh = idy;
	sh  =  nh;
;
; I  .a  =   rectangle( idx, sh )
; I  .b  =   |. nh
; I  .s  =   I.a  ysh( -sh/2  -+  is )
; I  .n  =   I.b  ysh( +nh/2  -+  in )
; I      =   I.s    +++    I.n
);

Dd( i250 )( X_SYM  )( Y_NORM )( % s280; k277
;
	iwe = !! ( ie_base  +  split_distance_default  +  0 );
;
; I      =   ip\249    +++    ii_ii  splitted
);

Dd( i251 )( X_EQB  )( Y_NORM )( % s282; k278
;
	iwe = iwe_base;
;
; I  .h  =   ip\249
; I  .b  =   ip\219  xsh( 1/2[ iw\219, ie\219 ] -+ 0 ) zsc 3/4( idx, idy/2 )
; I  .o  =   I.b  ysh( 0  -+  1/2 is )
; I      =   I.h    +++    I.o
);

Dd( i252 )( X_SYM  )( Y_NORM )( % s284; k280
;
	iwe = iwe_base;
;
; I  .h  =   ip\249
; I  .b  =   rectangle( idx, 1/3 idy/2 )
; I  .o  =   I.b  ysh( 0  -+  1/2 is )
; I      =   I.h    +++    I.o
);

Dd( i253 )( X_SYM  )( Y_NORM )( % s278.1; k275.072
;
	iwe = iwe_base;
;
	NUMER  sh, oh, nh;    sh + oh + nh = idy;
	sh  =  nh;
	oh  =  idy/2;
;
; I  .a  =   ip\249.a
; I  .b  =   |. nh
; I  .s  =   I.b  ysh( -sh/2  -+  is )
; I  .n  =   I.b  ysh( +nh/2  -+  in )
; I      =   I.a    +++    I.s    +++    I.n
);

Dd( i254 )( Z_SYM  )( Y_NORM )( % s305; k301
;
	iwe = iwe_base;
;
; I  .a  =   ip\253.a
; I  .s  =   ip\253.s  xsh( 0  -+  ie )
; I  .n  =   ip\253.n  xsh( 0  -+  iw )
; I  .o  =   |. idx  |>90
; I      =   I.a    +++    I.s    +++    I.n    +++    I.o
);

Dd( i255 )( X_any  )( Y_NORM )( % s306; k302
;
	iwe = iwe_base;
;
	NUMER  sh, oh, nh;    sh + oh + nh = idy;
	sh  =  oh;
	nh  =  sh + oh;
;
	Numer  shoh = sh + oh;
	Numer  ohnh = oh + nh;
;
; I  .a  =   rect_open( shoh, idx )  |>90
; I  .b  =   rect_open( idx, ohnh )  |:
; I  .s  =   I.a  ysh( -shoh/2  -+  is )
; I  .n  =   I.b  ysh( +ohnh/2  -+  in )
; I      =   I.s    +++    I.n
);

Dd( i256 )( X_SYM  )( Y_NORM )( % s285; k281
;
	iwe = iwe_base;
;
	Numer  nh = idx/2;
;
; I  .b  =   rectangle( idx, nh )
; I  .n  =   I.b  ysh( +nh/2  -+  in )
; I      =   |. idy    +++    I.n
);

		endgroup ; %% i249 - i256

Dd( i257 )( X_SYM  )( Y_NORM )( % s277; k274
; I  .a  =   ip\237
;
	iwe = iwe\237  +  !! $ 3;
;
	NUMER  wb, ob, eb;    wb + ob + eb = idx;
	wb  =  eb;
	ob  =  idx\237;
;
; I  .b  =   square. wb
; I  .sw =   I.b  shi( ( -wb/2, -wb/2 )  -+  iWS )
; I  .se =   I.b  shi( ( +eb/2, -eb/2 )  -+  iES )
; I      =   I.a    +++    I.sw    +++    I.se
);

Dd( i258 )( X_any  )( Y_NORM )( % s205; k200
; I  .a  =   ip\237
;
	iwe = !! idx\237;
;
	NUMER  wb, eb;    wb + eb = idx;
	wb  =  eb;
;
; I  .b  =   rectangle( wb, 2/5 idy )
; I  .x  =   I.a    +++    I.b  ysh -1/10 idy    +++    I.b  ysh +1/10 idy
; I  .w  =   I.x  xsh( -wb/2  -+  iw )
; I  .e  =   ++++ ( ( 0, -$ 1 ) -- ( eb, -$ 2 ) -- ( eb, +$ 2 ) -- ( 0, +$ 1 ) )
; I      =   I.w    +++    I.e
);

Dd( i259 )( X_any  )( Y_NORM )( % s203; k198
;
	NUMER  sh, nh;
	NUMER  wb, ob, eb;
	Numer  shnh = sh  +  nh;
	Numer  obeb = ob  +  eb;
	shnh  =  obeb;
	obeb  =  teqre_s idy;    % shnh ++ obeb = idy
	wb    =  nh;
	wb    =  $ 3;
	ob    =  $ 4;
;
	width = teqre_s wb  +  teqre_s obeb  +  max( teqre_s nh, teqre_s ob );
;
	iwe = !! ( width/2 );
;
	Pairp  CC = ( iw + teqre_s wb + teqre_s nh, ( nh/shnh ) * is );
;
; I  .a  =   rectangle(   wb, nh )
; I  .b  =   rectangle( obeb, nh )
; I  .c  =   rectangle(   ob, sh )
; I  .nw =   I.a  shi( ( +  wb/2, -nh/2 )  -+  OQ )
; I  .ne =   I.b  shi( ( -obeb/2, -nh/2 )  -+  OQ )
; I  .se =   I.c  shi( ( -  ob/2, +sh/2 )  -+  OQ )
; I\0    =   I.nw    +++    I.ne    +++    I.se
; I      =   I\0  |<45  shi( OQ  -+  CC )
);

Dd( i260 )( X_any  )( Y_NORM )( % s; k
;
	iwe = !! 1/3 idy;
;
; I  .w  =   |. idy  xsh iw
; I  .sn =   |. idy
; I  .e  =   rect_open( 1/3 idy, idx )  |>90
; I  .o  =   |. ie  |>90  xsh( +ie/2  -+  ie )
; I      =   I.w    +++    I.sn    +++    I.e    +++    I.o
);

		begingroup %% i261 - i286

Cc( i261, i286 )( %%
 % parameter begin
	Numer  rh_ry =        1/2 idy_base;
	Numer  rh_rx = good.x 1/3 idy_base;

	Numer  rh_little_fac = 1/3;
 % parameter end

	Pair     iwe_base = !! rh_rx;

	Pairp  rh_N = ( 0, in_base );
	Pairp  rh_E = ( ie_base, 0 );
	Pairp  rh_S = ( 0, is_base );
	Pairp  rh_W = ( iw_base, 0 );
	Pairp  rh_O = 1/2[ rh_N, rh_S ];

	Numer  rh_side  =    0.5 length( rh_N - rh_S )
	.                 ++ 0.5 length( rh_E - rh_W );

	Pairp  rh_little_N = rh_N;
	Pairp  rh_little_S = rh_N + rh_little_fac * ( rh_S - rh_N );
	Pairp  rh_little_E = rh_N + rh_little_fac * ( rh_E - rh_N );
	Pairp  rh_little_W = rh_N + rh_little_fac * ( rh_W - rh_N );

	Numer  rh_little_side  =  rh_little_fac * rh_side;

	Pairp  rh_shrink_S = rh_S;
	Pairp  rh_shrink_N = min( ( 0, yn_shrinked ),
	.                          rh_shrink_S  +  ( 0, 2 rh_ry ) );

	Numer  rh_fac_shrink_y  =  length( rh_shrink_N - rh_shrink_S )
	.                        / length( rh_N        - rh_S        );

	Numer  rh_rx_shrink     =  good.x( rh_rx * rh_fac_shrink_y );
	Numer  rh_fac_shrink_x  =  rh_rx_shrink / rh_rx;

	Pairp  rh_shrink_E = rh_shrink_S
	.                  + ( rh_fac_shrink_x * xpart( rh_E - rh_S ),
	.                      rh_fac_shrink_y * ypart( rh_E - rh_S ) );

	Pairp  rh_shrink_W = rh_shrink_S
	.                  + ( rh_fac_shrink_x * xpart( rh_W - rh_S ),
	.                      rh_fac_shrink_y * ypart( rh_W - rh_S ) );

	Pairp  rh_shrink_little_N = rh_shrink_N;
	Pairp  rh_shrink_little_S = rh_shrink_N
	.                   + rh_little_fac * ( rh_shrink_S - rh_shrink_N );
	Pairp  rh_shrink_little_E = rh_shrink_N
	.                   + rh_little_fac * ( rh_shrink_E - rh_shrink_N );
	Pairp  rh_shrink_little_W = rh_shrink_N
	.                   + rh_little_fac * ( rh_shrink_W - rh_shrink_N );

	Path   rh_p               =    rh_S -- rh_W
	.                           -- rh_N -- rh_E -- cycle;

	Path   rh_little_p        =    rh_little_S -- rh_little_W
	.                           -- rh_little_N -- rh_little_E -- cycle;

	Path   rh_shrink_p        =    rh_shrink_S -- rh_shrink_W
	.                           -- rh_shrink_N -- rh_shrink_E -- cycle;

	Path   rh_shrink_little_p =    rh_shrink_little_S -- rh_shrink_little_W
	.                           -- rh_shrink_little_N -- rh_shrink_little_E
	.                           -- cycle;

	Nangle  rh_angle_s_e = Angle( rh_S -+ rh_E );
	Nangle  rh_angle_n_e = Angle( rh_N -+ rh_E );
	Nangle  rh_angle_e_n = Angle( rh_E -+ rh_N );

	Nangle  rh_alpha  =  rh_angle_s_e;
	Nangle  rh_omega  =  90 - 2 rh_alpha;
		% angle( perpendicular from (S/W)-point onto parallel side, side )

	Numer   rh_slanted_fac =  tand rh_omega;
); %%

Dd( i261 )( X_SYM  )( Y_NORM )( % s357.1; k355.111
;
	iwe = !! rh_rx;
;
; I      =   ++++ rh_p
);

Dd( i262 )( X_any  )( Y_NORM )( % s359 (but oval); k356 (...)
; I  .a  =   ip\261
; I  .c  =   ip\162\1
; I  .x  =   I.c  ysh( is\162  -+  0 )
.                 Transformed( identity  slanted -rh_slanted_fac )
.                 |>( 90 - rh_alpha )
; I  .e  =   I.x  scy( ypart rh_E  -+  in )
.                 shi( OQ  -+  rh_E )
; I      =   I.a    +++    I.e
;
	iwe = ( -rh_rx, I.e.?.x_e );
;
);

Dd( i263 )( X_any  )( Y_NORM )( % s363; k361
;
	iwe = !! rh_rx;
;
; I  .a  =   ip\261
; I  .b  =   ++++ ( rh_W -- rh_S )
; I  .se =   I.b  shi( rh_W  -+  OQ )
; I      =   I.a    +++    I.se
);

Dd( i264 )( X_SYM  )( Y_NORM )( % s361; k359
;
	iwe = !! rh_rx;
;
; I  .a  =   ip\261
;
	Numer   d  =  stroke_distance_x;

	Pairv  Av  =  1/2 d * ( ( Dir rh_alpha ) |<90 );
	Pairp  CC  =  ( OQ + Av ) projection( rh_alpha ) ( rh_E -- rh_N );
	Pairp  DD  =  ( OQ - Av ) projection( rh_alpha ) ( rh_E -- rh_N );
;
	Pairp  AN = jet( CC, rh_alpha )  where_y  ypart rh_N;
;
	Path    p  =  AN -- CC;
	Path    q  =  p  shifted( CC  -+  DD );
	Path   pq  =  p -- ( q ` );
;
; I  .b  =   ++++ pq
; I  .ne =   I.b
; I  .nw =   I.ne  ||
; I  .n  =   I.ne    +++    I.nw
; I  .s  =   I.n   |:
; I      =   I.a     +++    I.s    +++    I.n
);

Dd( i265 )( X_EQB  )( Y_NORM )( % s; k
;
	iwe = !! rh_rx;
;
; I  .a  =   ip\261
; I  .b  =   ip\178\1
;
	% assumptions: rry ip\178\1 = idy\178;   ip\178\1.?.x_w = iw\178 .
;
	Numer  hh   = $ 7;
	Numer  yscf = hh / idy\178;
;
; I  .c  =   I.b  Yscaled yscf  Xscaled min( yscf, 1.2 rh_rx /( -2 iw\178 ))
; I  .o  =   I.c  shi( OQ -+ rh_O   +   $(0.2, 1) )
; I      =   I.a    +++    I.o
);

Dd( i266 )( X_SYM  )( Y_NORM )( % s393; k363
;
	iwe = !! rh_rx;
;
; I  .a  =   ip\261
; I  .b  =   ip\256
;
	Numer  yscf = $ 6 / ( idy\256 - 0.25 idx\256 );
;
; I  .c  =   I.b  ysh( is\256  -+  0 )
; I  .d  =   I.c  Yscaled yscf  Xscaled min( yscf, 1.4 rh_rx / idy\256 )
; I  .s  =   I.d  ysh( 0  -+  is )
; I      =   I.a    +++    I.s
);

Dd( i267 )( X_SYM  )( Y_NORM )( % s380.1; k385.162
;
	iwe = !! rh_rx;
;
; I  .a  =   ip\261
; I  .b  =   ++++ rh_little_p
; I      =   I.a    +++    I.b
);

Dd( i268 )( X_SYM  )( Y_NORM )( % s381; k386
;
	iwe = iwe\410;
;
; I  .h  =   ip\410
; I  .d  =   ip\410.n
;
	Pairp  NN  =  $( 0, 2 );
	Pairp  EE  =  jet( NN, 135 )  Intersectionpoint_right  I.d;
	Path   p   =  ( EE || ) -- NN -- EE;
;
; I  .n  =   ++++ p
; I  .s  =   I.n  |:
; I      =   I.h    +++    I.s    +++    I.n
);

Dd( i269 )( X_any  )( Y_NORM )( % s; k
;
	iwe = ( iw\373 - bridge_width_default_wide, ie\373 );
;
; I  .a  =   ip\373
; I  .w  =   |. idy  xsh( 0  -+  iw )
;
	Pairp  WW  =  Point 9/12 of  I.w;
	Pairp  QQ  =  OQ;
	Pairp  EE  =  ( QQ -- WW || )  Intersectionpoint_right  I.a;
	Path    p  =  WW -- QQ -- EE;
;
; I  .c  =   ++++ p
; I      =   I.a    +++    I.w    +++    I.c
);

Dd( i270 )( X_any  )( Y_HIGH )( % s; k392
; I  .a  =   ++++ rh_shrink_p
; I  .b  =   ++++ rh_shrink_little_p
; I\1    =   I.a    +++    I.b
;
; I  .x  =   ip\262.x  ||
; I  .w  =   I.x  scy( ypart rh_shrink_little_W  -+  in )
.                 shi( OQ  -+  rh_shrink_little_W )
;
; I      =   I\1    +++    I.w
;
	iwe = ( min( -rh_rx_shrink, I.w.?.x_w ), rh_rx_shrink );
;
);

Dd( i271 )( X_any  )( Y_HIGH )( % s388; k393
; I  .h  =   ip\270\1
;
	Pairp  XX = rh_shrink_little_E;
	Pairp  ZZ = rh_shrink_E;
	Pairp  YY = 1/2[ XX, ZZ ];
;
	Numer  hh = $ 5;
	Numer  ww = max( $ 0.75, min( $ 1.5, length( XX -+ YY ) - $ 1 ) );
;
;    pit:=   ip\177   % make sure, we can access IP(177)
; I  .c  =   IP( 177 )( hh, ww, rh_alpha, rh_angle_e_n, 3, 1.8/5, 0.8/5 )
; I  .x  =   I.c  shi( hh/2 * unitvector( rh_S -+ rh_E ) )
; I  .y  =   I.x  Scaled( ( yn_high - ypart XX ) / ( I.x.?.y_n ) )
; I  .nne=   I.y  shi( OQ  -+  XX )
; I  .ne =   I.y  shi( OQ  -+  YY )
; I  .ene=   I.y  shi( OQ  -+  ZZ )
; I      =   I.h    +++    I.nne    +++    I.ne    +++    I.ene
;
	iwe = ( -rh_rx_shrink, I.ene.?.x_e );
;
);

Dd( i272 )( X_SYM  )( Y_HIGH )( % s384; k389
; I  .h  =   ip\270\1
;
	Pairp  NNW  =  jet( rh_shrink_little_S, rh_shrink_little_W ) where_y in;

	Path  pnnw  =  rh_shrink_little_W  --  NNW;
	Path  north =  rh_shrink_little_N  --  iON;
	Path  pnw   =  interpath( 1/2, pnnw, north );
;
; I  .nw =   pnnw    +++    pnw;
; I  .ne =   I.nw  ||
; I  .n  =   ++++ north
; I      =   I.h    +++    I.nw    +++    I.n    +++    I.ne
;
	iwe = !! max( rh_rx_shrink, -xpart NNW );
;
);

		begingroup %% i273 - i274

Cc( i273, i274 )( %%
	Numer  flag_dx = $ 1;     % width, orthogonal to the stick
	Numer  flag_dy = $ 2;
	Numer  stick_l = $ 2;     % stick without flag
	Numer  full_dy = stick_l + flag_dy;
); %%

Dd( i273 )( X_SYM  )( Y_HIGH )( % s390; k395
; I  .h  =   ip\270\1
;    pit:=   ip\176   % make sure, we can access IP(176)
; I  .b  =   IP( 176 )( flag_dy, flag_dx, rh_angle_e_n, rh_alpha, tT, 3 )
; I  .c  =   |. stick_l  ysh( -1/2 stick_l -+ 0 )  |>rh_angle_e_n
; I  .x  =   I.c    ++("omega=s")+-    I.b
;
	Numer  scalefactor  =   ( ypart rh_shrink_little_W  -+  yn_high )
	.                     / ( I.x.?.y_n );
;
; I  .y  =   I.x  Scaled( scalefactor )
; I  .nw =   I.y  shi( OQ -+ rh_shrink_little_W )
; I  .ne =   I.nw  ||
; I      =   I.h    +++    I.nw    +++    I.ne
;
	Numer  flag_width = ( full_dy * scalefactor ) * sind rh_alpha;
;
	iwe = !! max( rh_rx_shrink, xpart rh_shrink_little_E + flag_width );
;
);

Dd( i274 )( X_SYM  )( Y_HIGH )( % s389; k394
; I  .h  =   ip\273.h
; I  .b  =   ip\273.b  |||:
; I  .c  =   ip\273.c
; I  .x  =   I.c    ++("omega=e")+-    I.b
;
	Numer  full_height  =  full_dy * cosd rh_alpha;
	Numer  scalefactor  =  ( yn_high - ypart rh_shrink_little_W )
	.                     /  full_height;
;
; I  .y  =   I.x  Scaled( scalefactor )
; I  .nw =   I.y  shi( OQ -+ rh_shrink_little_W )
; I  .ne =   I.nw  ||
; I      =   I.h    +++    I.nw    +++    I.ne
;
	iwe = !! max( rh_rx_shrink, xpart rh_shrink_little_E - I.y.?.x_w );
;
);

		endgroup ; %% i273 - i274

Dd( i275 )( X_EQB  )( Y_NORM )( % s383 (but mirrowed); k388
;
	iwe = !! rh_rx;
;
; I  .a  =   ip\267
; I  .c  =   ++++ ( ( rh_S -- rh_W )
.            shifted( stroke_distance_y * unitvector ( rh_W  -+  rh_N ) ) )
; I      =   I.a    +++    I.c
);

Dd( i276 )( X_any  )( Y_NORM )( % s382; k387
;
	iwe = !! rh_rx;
;
; I  .a  =   ip\267
; I  .c  =   ip\087  ysc 1.5 rh_little_side
.                    Transformed( identity  slanted -rh_slanted_fac )
.                    |>( 90 - rh_alpha )
; I  .x  =   I.c  shi( OQ  -+  1/2[ rh_S, rh_W ] )
; I      =   I.a    +++    I.x
);

Dd( i277 )( X_SYM  )( Y_NORM )( % s; k
;
	iwe = !! rh_rx;
;
; I  .a  =   ip\267
;
	Pairp  PP  =  rh_little_S + rh_little_side * down;
	Path   p   =  rh_little_S -- PP;
;
; I  .b  =   ++++ p
; I      =   I.a    +++    I.b
);

Dd( i278 )( X_SYM  )( Y_NORM )( % s; k
;
	iwe = !! ( rh_rx  +  split_distance_default  +  0 );
;
; I  .a  =   ip\261
;
	Pairp  PP  =  ( rh_little_W -- rh_little_S )  where_x
	.                                             -0.38 stroke_distance_x;
	Pairp  QQ  =  PP + rh_little_side * down;
	Path   p   =  rh_little_W  --  PP  --  QQ;
;
; I  .nw =   ++++ p
; I  .ne =   I.nw  ||
; I\1    =   I.a    +++    I.nw    +++    I.ne
; I      =   I\1    +++    ii_ii  splitted
);

Dd( i279 )( X_EQB  )( Y_NORM )( % s; k
;
	iwe = !! rh_rx;
;
; I  .a  =   ip\278\1
; I  .ne =   ip\284.b
; I      =   I.a    +++    I.ne
);

Dd( i280 )( X_SYM  )( Y_NORM )( % s; k390.730
;
	iwe = !! rh_rx;
;
; I  .a  =   ip\277
;
	Pairp  WW =  rh_little_S + ( rh_little_E -+ rh_little_S );
	Pairp  EE =  WW  ||;
	Path   p  =  WW -- rh_little_S -- EE;
;
; I  .b  =   ++++ p
; I      =   I.a    +++    I.b
);

Dd( i281 )( X_SYM  )( Y_NORM )( % s; k
;
	iwe = !! ( rh_rx  +  split_distance_default  +  0 );
;
; I      =   ip\280    +++    ii_ii  splitted
);

Dd( i282 )( X_EQB  )( Y_NORM )( % s385; k390.166
;
	iwe = !! rh_rx;
;
	Numer  haft_length  =  0.15 ( rh_side - rh_little_side );
	Numer  flag_h       =  0.60 ( rh_side - rh_little_side );
;
; I  .a  =   ip\267
;    pit:=   ip\176   % make sure, we can access IP(176)
; I  .b  =   IP( 176 )( flag_h, $ 1.2, rh_alpha, rh_angle_n_e, tT, 3 )
; I  .c  =   |. haft_length  ysh( +1/2 haft_length -+ 0 )  |> rh_alpha
; I  .x  =   I.c  shi( OQ  -+  rh_little_S )
; I  .y  =   I.b  shi(             ~.?.n  -+  rh_little_S
.                        + ( I.c.?.omega  -+  I.c.?.alpha )   )
; I  .o  =   I.x    +++    I.y
; I      =   I.a    +++    I.o
);

Dd( i283 )( X_EQB  )( Y_NORM )( % s; k
;
	iwe = !! rh_rx;
;
; I  .a  =   ip\282
; I  .b  =   ip\284.b
; I      =   I.a    +++    I.b
);

Dd( i284 )( X_SYM  )( Y_NORM )( % s377; k382
;
	iwe = !! rh_rx;
;
; I  .a  =   ip\267
; I  .b  =   ip\267.b  shi( rh_little_E  -+  rh_E )
; I  .ne =   I.a    +++    I.b
; I  .sw =   I.ne  |||:
; I      =   I.ne   +++    I.sw
);

Dd( i285 )( X_SYM  )( Y_NORM )( % s378; k383
;
	iwe = !! ( rh_rx  +  split_distance_default  +  0 );
;
; I      =   ip\284    +++    ii_ii  splitted
);

Dd( i286 )( X_SYM  )( Y_NORM )( % s379; k384
;
	iwe = !! rh_rx;
;
; I  .a  =   ip\261
;
	save fac;    def  fac = 2/3  enddef;
	Pairp  NN =  fac [ rh_little_N, rh_little_S ];
	Pairp  NE =  fac [ rh_little_N, rh_little_E ];
	Pairp  EE =  rh_E  +  fac * ( rh_little_E -+ rh_little_W );
	Path   p  =  NN -- NE;
	Path   q  =  p  shifted( NN  -+  EE );
	Path   pq =  p -- ( q ` );
	Path   r  =  pq  &  pq |: `  &  pq |||:  &  pq || `;
;
; I  .b  =   ++++ r
; I  .h  =   I.a    +++    I.b
; I  .d  =   ip\391  scx( 2 ( xpart rh_E - 2 * fac * xpart rh_little_E )
.                         - 1.0 stroke_distance_x )
; I      =   I.h    +++    I.d
);

		endgroup ; %% i261 - i286

Dd( i287 )( X_any  )( Y_NORM )( % s161; k154.153
; I      =   R_bend_medium
;
	iwe = !! -xpart beg I;
;
);

Dd( i288 )( X_any  )( Y_NORM )( % s162; k156
; I  .a  =   ip\287
; I  .b  =   ++++ ( ( xpart beg( I.a ), $ 1 ) -- Point 0.5 of I.a )
; I      =   I.a    +++    I.b
;
	iwe = iwe\287;
;
);

Dd( i289 )( X_any  )( Y_NORM )( % s160 (but different form); k155 (...)
;
	iwe = !! good.x ( ie\287 + split_distance_default + distance_x_low );
;
; I      =   ip\287    +++    iiii_iii  splitted
);

Dd( i290 )( X_any  )( Y_any  )( % s168; k162
; I  .a  =   ip\287
;
	Nangle  alf  =  75;
;
	Path   p   =  Subpath( 0, 0.7 )  of  I.a;
	Pairp  NN  =  beg p  +  $ 2 * Dir alf;
	Pairp  EE  =  fin p  +  $ 2 * Dir alf;
	Path   r   =  line( EE, NN );
;
	Numer   dy_old =  ypart( fin I.a  -+  NN );
;
	isn = ( ys_normal, unk );
;
	Transform  tt  =  identity
	.                 yscaled(    min( 1,       dy_high/dy_old        ) )
	.                 shifted( 0, min( 0, is * (dy_high/dy_old) -+ is ) );
;
; I\0    =   I.a    +++    ( ++++ p, ++++ r ) ''( 5, alf )
; I      =   I\0  Transformed tt
;
	isn = ( ys_normal, ypart( NN Transformed tt ) );
	iwe = (    iw\287, xpart( EE Transformed tt ) );
;
);

Dd( i291 )( X_any  )( Y_NORM )( % s107; k102
;
	iwe = iwe\376;
;
; I  .a  =   ip\287
;
	Nangle alf =   28;
	Nangle bet = -100;
;
	Pairp  AA  =  Point  0.2  of  I.a;
	Pairp  CC  =  Point  0.7  of  I.a;
	Pairp  NE  =  AA  projection( alf )  N_line;
	Pairp  EN  =  jet( CC, alf )  where_x  ( ie - split_distance_default );
;
	Pathl   l  =  ( beg I.a -- fin I.a )
	.             xsh( xpart beg I.a  -+  ( iw + split_distance_default ) );
;
	Path   pa  =  ( AA projection( bet ) l ) --  AA  --  NE;
	Path   pc  =  ( CC projection( bet ) l ) --  CC  --  EN;
;
	Pairp  BL  =  1/2[ beg pa, beg pc ];
	Pairp  BR  =  1/2[ fin pa, fin pc ];
;
	Pairp  BB  =  jet( BL, bet + 180 ) intersectionpoint jet( BR, alf + 180 );
;
	Path   pb  =  BL  --  BB  --  BR;
;
; I\0    =   I.a    +++    pa    +++    pb    +++    pc
; I      =   I\0    +++    ip\087  splitted
);

Dd( i292 )( X_any  )( Y_NORM )( % s175 (but mirrowed); k171 (...)
; I  .a  =   ip\287
;
	Pairp PP = Point 0.5  of  I.a;
	Pairp QQ = Point 0.3  of  I.a;
	Path  p = PP -- ( PP + $ 1.5 *( unitvector Direction .4 of I.a |< 90 ) );
	Path  q  = p  shifted( PP  -+  QQ );
;
	iwe = ( iw\287, xpart fin p )  +  !! split_distance_default  +  !! 0;
;
; I  .b  =   p     +++    q
; I\0    =   I.a   +++    I.b    +++    I.b |:
; I      =   I\0   +++    ii_ii  splitted
);

Dd( i293 )( X_any  )( Y_NORM )( % s166; k160
; I  .a  =   ip\287
;
	Pairp  PP = Point  0.32 Length I.a  of  I.a;
	Pairp  QQ = PP  |:;
	Path    p = PP { Dir -110 } .. { Dir +110 } QQ;
;
; I      =   I.a    +++    p
;
	iwe = ( min( iw\287, xpart( directionpoint down of p ) ), ie\287 );
;
);

Dd( i294 )( X_any  )( Y_NORM )( % s176.2; k172.242
; I  .a  =   ip\287
; I  .b  =   ip\287
; I  .x  =   I.a  xsh( rx I.a )  Xscaled 1.10  xsh( -rx I.a )
; I  .w  =   I.x  xsh( -1/2 stroke_distance_x )
; I  .e  =   I.b  xsh( +1/2 stroke_distance_x )
; I      =   I.w    +++    I.e
;
	iwe = iwe\287  +  !! 1/2 stroke_distance_x;
;
);

Dd( i295 )( X_any  )( Y_NORM )( % s177.2; k173.455
; I  .a  =   ip\294.w
; I  .b  =   ip\294.e
;
	save  thorn;
	vardef  thorn  primary fig =
		Pairp  PP = Point  0.3  of  fig;
		Pairp  RR = Point  0.6  of  fig;
		Pairp  NN = ( xpart RR + $ 0.6 , in );
		;
		PP { (PP -+ NN) |> 10 } .. NN  &  NN { Dir 175 } .. { Dir 210 } RR
	enddef;
;
	Path  p  =  thorn( I.b );
;
; I  .ne =   ++++ p
; I  .w  =   I.a
; I  .e  =   I.b    +++    I.ne
; I      =   I.w    +++    I.e
;
	iwe = ( iw\294, max( ie\294, xpart( directionpoint down of p ) ) );
;
; I\1.b  =   R_parenthesis
; I\1.e  =   I\1.b    +++    thorn( I\1.b )
);

		begingroup %% i296 - i297

Cc( i296, i297 )( %%
	Pairp  CC    = ( -$ 7, 0 );
); %%

Dd( i296 )( X_any  )( Y_NORM )( % s180; k175
; I  .b  =   ip\294.e
;
	Pairp  NW  =  beg I.b + stroke_distance_x * unitvector( beg I.b -+ CC );
	Pairp  SW  =  NW  |:;
	Pairp  OW  =  mid I.b + stroke_distance_x * unitvector( mid I.b -+ CC );
;
	Path    p  =  SW  ..  OW  ..  NW;
	Path    r  = p   --  ppath I.b  --  cycle;
;
; I      =   ++++ r
;
	iwe = ( xpart beg p, ie\294 );
;
);

Dd( i297 )( X_any  )( Y_NORM )( % s181; k176
; I  .h  =   ip\296
;
	iwe = iwe\296;
;
	Nangle  alpha = 90  -+  Angle( CC -- fin ip\294.e );
	.                  % half of angle range, figure is seen at from CC
;
; I  .b  =   I.h  ''( 3, CC, ( 90 - 2/3 alpha, 90 ) )
; I  .c  =   I.b  |:
; I      =   I.h    +++    I.b    +++    I.c
);

		endgroup ; %% i296 - i297

Dd( i298 )( X_any  )( Y_NORM )( % s182; k177
;
	iwe = !! 1/2( 4 stroke_distance_x + idx\287 );
;
; I  .a  =   ip\294.w
; I  .b  =   ip\294.e
;
	Path  pww  =  ppath( I.a )  xsh( Point 0 of I.a  -+  iWN );
	Path  pee  =  ppath( I.b )  xsh( Point 1 of I.b  -+  iEO );
	Path  poo  =  interpath( 1/2, pww, pee );
	Path  pwo  =  interpath( 1/2, pww, poo );
	Path  peo  =  interpath( 1/2, pee, poo );
;
; I      =   pww    +++    pwo    +++    poo    +++    peo    +++    pee
);

Dd( i299 )( X_any  )( Y_NORM )( % s169; k163
; I      =   ip\287  ||
;
	iwe = !!! iwe\287;
;
);

Dd( i300 )( X_any  )( Y_NORM )( % s170; k164
; I  .a  =   ip\299
;
	Pairp  PP = Point 0   of  I.a;
	Pairp  QQ = Point 0.5 of  I.a;
	Pairp  EE = ( $ 3, ypart( QQ + .1( PP - QQ ) ) );
;
; I  .b  =   ++++ ( PP -- EE -- QQ )
; I      =   I.a    +++    I.b
;
	iwe = ( iw\299, $ 3 );
;
);

Dd( i301 )( X_any  )( Y_NORM )( % s171; k165
; I      =   ip\293 ||
;
	iwe = !!! iwe\293;
;
);

Dd( i302 )( X_any  )( Y_NORM )( % s174; k170
; I  .a  =   R_bow_narrow  ||
;
	Numer  u  =  first( I.a Intersectiontimes I.a || );
	Numer  v  =  Length I.a - u;
;
	Path   p  =     ( ( beg I.a ) || - ( 0, $ 2 ) )
	.           --  ( Subpath( 0, v )  of  I.a || );
;
; I      =   I.a    +++    p
;
	iwe = !! - xpart Point 1 of I.a;
;
);

Dd( i303 )( X_SYM  )( Y_NORM )( % s178; k174
; I  .a  =   ip\287
;
	iwe = !! idx\287  +  !! 1/2 stroke_distance_x;
;
; I  .w  =   I.a  xsh( iw\287  -+  iw )
; I  .e  =   I.w  ||
; I      =   I.w    +++    I.e
);

Dd( i304 )( X_any  )( Y_NORM )( % s184; k178
; I  .e  =   R_bow_thick
;
	iwe = !! -xpart beg I.e;
;
; I  .w  =   |. idy  xsh( 0  -+  iw )
; I      =   I.w    +++   I.e
);

Dd( i305 )( X_any  )( Y_any  )( % s185; k179
; I  .a  =   ip\304
; I  .e  =   ip\304.e
;
	Nangle  alf =  45;
;
	save  hair;
	vardef  hair  primary n =
		Path   p = Subpath( (5-n)/5 * 0.5, 0.5 )  of  I.e;
		Pairp  NN  =  beg p  +  $ 2 * Dir alf;
		Pairp  EE  =  fin p  +  $ 2 * Dir alf;
		Path   r   =  line( EE, NN );

		( ++++ p, ++++ r ) ''( n, alf )
	enddef;
;
; I  .b  =   hair( 5 )
; I\0    =   I.a    +++    I.b
;
	Pairp  NX  =  Point 0.0 of I.e  +  $ 2 * Dir alf;
	Pairp  EX  =  Point 0.5 of I.e  +  $ 2 * Dir alf;
;
	Numer   dy_old =  ypart( fin I.e  -+  NX );
;
	isn = ( ys_normal, unk );
;
	Transform  tt  =  identity
	.                 yscaled(    min( 1,       dy_high/dy_old        ) )
	.                 shifted( 0, min( 0, is * (dy_high/dy_old) -+ is ) );
;
; I      =   I\0  Transformed tt
;
	isn = ( ys_normal, ypart( NX Transformed tt ) );
	iwe = (    iw\304, xpart( EX Transformed tt ) );
;
; I  .c  =   hair( 3 )
; I\2    =   I.a    +++    I.c
;
	Pairp  MX  =  Point 0.2 of I.e  +  $ 2 * Dir alf;
;
	Numer   dy_olt =  ypart( fin I.e  -+  MX );
;
	Transform  tx  =  identity
	.              yscaled(    min( 1,      13/14 dy_high/dy_olt        ) )
	.              shifted( 0, min( 0, is * 13/14(dy_high/dy_olt) -+ is ) );
;
; I\3    =   I\2  Transformed tx
);

Dd( i306 )( X_any  )( Y_ROOF )( % s186; k180
; I  .a  =   ip\305\3
;
	iwe = !! $ 4.5;
;
	Path  p  =  iWS  --  iWN  --  iEN  -- ( iEN  ysh -roof_height_default );
;
; I      =   I.a    +++    p
);

Dd( i307 )( X_any  )( Y_NORM )( % s188; k182
; I  .a  =   ip\304
;
	iwe = iwe\304;
;
	Path    p   =  iWO -- iEN;
;
; I      =   I.a    +++    p
);

Dd( i308 )( X_any  )( Y_NORM )( % s; k183
;
	iwe = iwe\307  +  !! split_distance_default  +  !! distance_x_low;
;
; I      =   ip\307   +++   iiii_iiii  splitted
);

Dd( i309 )( X_any  )( Y_NORM )( % s233; k228
;
	iwe = !! good.x 1/2( idy  +-+  idy/2 );
;
; I  .a  =   ++++ ( iWN  --  iEO  --  iWS  --  cycle )
; I  .b  =   ++++ ( iEN  --  iWO  --  iES )
; I      =   I.a    +++   I.b   +++   |. 1/2 idy
);

Dd( i310 )( X_any  )( Y_NORM )( % s087; k078
;
	iwe = !! $ 3;
;
; I  .a  =   ip\304  Yscaled 1/2  Xscaled 2/3
; I  .n  =   I.a  ysh( 1/2 in\304  -+  in )  xsh( 2/3 iw\304  -+  iw  )
; I  .s  =   I.a  ysh( 1/2 is\304  -+  is )  xsh( 2/3 iw\304  -+  iw  )
; I  .e  =   ++++ ( iWO { right }  .. tension 0.8 ..  { up } iEN )
; I      =   I.s    +++    I.n    +++    I.e
);

Dd( i311 )( X_any  )( Y_NORM )( % s187 (but mirrowed); k181 (...)
;
	iwe = !! $ 3;
;
; I  .h  =   ++++ ( iWS --- ( 0, -$ 4.5 ) .. iEO .. ( 0, +$ 4.5 ) --- iWN )
;
	Pairp  PP = iWO  xsh 0.12( iw -+ ie );
	Pairp  QQ = iWO  xsh 0.57( iw -+ ie );
;
; I  .o  =   I.h  ''( 3, 0, ( PP, QQ ) )
; I      =   I.h    +++    I.o
);

		begingroup %% i312 - i315

Cc( i312, i315 )( %%
	Numer  h_bend = 1/3 dy_normal;
); %%

Dd( i312 )( X_SYM  )( Y_any  )( % s136; k131
;
	isn = !! 1/2 h_bend;
	iwe = !! $ 4;
;
; I      =   ++++ ( iWS { Dir 10 }  ..  iON  ..  { Dir 170 } iES )
);

Dd( i313 )( X_SYM  )( Y_any  )( % s137; k132
; I  .a  =   ip\312
;
	isn = 2 isn\312;
	iwe = iwe\312;
;
; I  .s  =   I.a  ysh( -1/2 h_bend  -+  is )
; I  .n  =   I.a  ysh( +1/2 h_bend  -+  in )
; I      =   I.s    +++    I.n
);

Dd( i314 )( X_SYM  )( Y_NORM )( % s138; k133
; I  .a  =   ip\313
;
	iwe = iwe\312;
;
; I  .s  =   I.a  ysh( -2/2 h_bend  -+  is )
; I  .n  =   I.a  ysh( +2/2 h_bend  -+  in )
; I      =   I.s    +++    I.n
);

Dd( i315 )( X_SYM  )( Y_NORM )( % s140; k135
;
	iwe = !! $ 3;
;
	Numer  h = 1/7 dy_normal;
;
; I  .a  =   ++++ ( ( iw, -h/2 )  ..  ( 0, +h/2 )  ..  ( ie, -h/2 ) )
; I  .x  =   I.a  ysh( +1/2 h  -+   0 )   +++   I.a  ysh( -1/2 h  -+   0 )
; I  .y  =   I.x  ysh( +2/2 h  -+   0 )   +++   I.x  ysh( -2/2 h  -+   0 )
; I      =   I.y  ysh( -4/2 h  -+  is )   +++   I.y  ysh( +4/2 h  -+  in )
);

		endgroup ; %% i312 - i315

		begingroup %% i316 - i318

Cc( i316, i318 )( %%
	Pair     iwe_base = !! $ 3;
;
	Path  p_wn = ( iw_base, 0 ) { up }  ..  { Dir 40 } ( 0, in_base );
); %%

Dd( i316 )( X_SYM  )( Y_NORM )( % s341; k340
;
	iwe = iwe_base;
;
	Path  p_west  =  iWS  ---  p_wn;
	Path  p_east  =  p_west  ||;
	Path  p       =  p_west   &   p_east `;
;
; I  .h  =   ++++ p
; I      =   I.h   +++    ip\186\1  scy $ 4
);

Dd( i317 )( X_SYM  )( Y_NORM )( % s338.1; k338
;
	iwe = iwe_base;
;
; I  .h  =   ip\316.h
; I  .a  =   iii_mini  ysh( -1/2 mini  -+   0 )
; I  .b  =   ii_mini   ysh( +1/2 mini  -+  -distance_y_mid )
; I      =   I.h    +++    I.a    +++    I.b
);

Dd( i318 )( X_EQB  )( Y_ROOF )( % s342; k341
; I  .h  =   ip\316.h
;
	Pairp  PP = I.h   where_x  -1/2 stroke_distance_x ;
	Numer   h = -is  +  ypart PP;
;
; I  .s  =   ip\087  ysc h  ysh( -1/2 h  -+  is )
; I  .o  =   ip\087  |<60         %  scx $ 11.5
; I\0    =   I.h    +++    I.s    +++    I.o
; I\1    =   I\0  Transformed ysc_shrink
; I      =   I\1  roofed( r_acute )
;
	iwe = !! max( I.o.?.x_e, ( fig_right I ).?.x_e );
;
);

		endgroup ; %% i316 - i318

		begingroup %% i319 - i322

Cc( i319, i322 )( %%
	Pair     iwe_base = !! good.x $ 3.5;
;
	Pairp  WOS = 1/2[ ( iw_base, is_base ), ( 0, is_base ) ];
	Pairp  EOS = 1/2[ ( ie_base, is_base ), ( 0, is_base ) ];
;
	Path  p_sw =       WOS { Dir -30 }  ..  { up }     ( iw_base, 0 );
	Path  p_wn = ( iw_base, 0 ) { up }  ..  { Dir 60 } ( 0, in_base );
;
	Path  p_w  = p_sw  &  p_wn;
	Path  p_e  = p_w   ||;
	Path  p_we = p_w  &  p_e `;
); %%

Dd( i319 )( X_EQB  )( Y_NORM )( % s343; k342
;
	iwe = iwe_base;
;
	Path  pos  = p_sw  ||  `  xsh( EOS -+ WOS );
	Path  p    = pos  &  p_we;
;
; I      =   ++++ p
);

Dd( i320 )( X_EQB  )( Y_NORM )( % s344; k343
;
	iwe = iwe_base;
;
; I  .h  =   ip\319
;
	Pairp  PP = point 1.67 of p_e;   % nearly perpendicular to NE
	Pairp  NE = iEN;
;
; I      =   I.h   +++   ( PP -- NE )
);

Dd( i321 )( X_SYM  )( Y_NORM )( % s345; k344
;
	iwe = iwe_base;
;
	Pairp   WSW  =  p_sw  where_y  -$ 1;
	Numer  twsw  =  second( WSW  intersectiontimes  p_sw );
;
	Paird  dwos  =  direction   0  of p_sw;
	Paird  dwsw  =  direction twsw of p_sw;
	Nangle corr  =  5;                    % fight optical illusion
	Paird  d     =  dwsw |||:  rotated( - 2 Angle dwos  +  corr );
;
	Path   pssw  =  WSW { d }  .. tension 0.85 ..  { dwos |: } WOS;
	Path   west  =  pssw     &    p_w;
	Path   east  =  west  ||;
	Path   pp    =  west     &    east `;
;
; I  .e  =   ++++ east
; I      =   ++++ pp
);

Dd( i322 )( X_SYM  )( Y_NORM )( % s346; k345.286
;
	iwe = iwe_base;
;
; I  .h  =   ip\321
; I  .b  =   ip\161
;
	Numer  corr = 0;   % fight peeking of Y out of the bow %% not used now
	save   fit;
	vardef fit( expr scf ) =        % tried scale factor of the `Y'
		scf * idy\161 + corr < is -+ ypart( p_wn where_x ( scf * iw\161 ) )
	enddef;

	NUMER  scf;
	begingroup
		interim  tolerance := 0.0001;
		scf = solve fit( 1/2, 1 );
	endgroup;
;
; I  .o  =   I.b  Scaled scf  ysh( scf * is\161  -+  is )
; I      =   I.h    +++    I.o
);

		endgroup ; %% i319 - i322

Dd( i323 )( X_SYM  )( Y_NORM )( % s116; k196
;
	iwe = !! $ 4.5;
;
	Pairp  SO  =  (  0    , -$ 4.2 );
	Pairp  SSW =  ( -$ 2.1,    is  );
	Pairp  WSW =  (    iw , -$ 3.2 );
	Pairp  WNW =  0.20[ WSW, iON ]  xsh -$ 0.34;
;
	Path   p   =       SO  { Dir -160 }
	.              ..  SSW {   left   }
	.              ..  WSW {   up     }
	.              ..  WNW
	.              .. { (WSW -+ iON ) |> 8 } iON;
	Path   pq  =  p    &    p  ||  `;
;
; I      =   ++++ pq
);

Dd( i324 )( X_SYM  )( Y_NORM )( % s; k374 (?)
;
	iwe = !! $ 4;
;
; I  .a  =   oval_thin( 2 abs iEN )
; I  .c  =   I.a  |>( Angle iEN )  xsc idx
; I  .d  =   I.c  ||
; I      =   I.c    +++    I.d
);

Dd( i325 )( X_SYM  )( Y_NORM )( % s117; k111
;
	iwe = !! $ 4;
;
; I  .a  =   ip\323
;
	Numer  scf  =  idx / idx\323;
;
; I  .h  =   I.a  Scaled( scf )  ysh( scf * in\323  -+  in )
; I  .s  =   ++++ ( iOS -- beg I.h )
; I      =   I.s    +++    I.h
);

Dd( i326 )( X_SYM  )( Y_NORM )( % s118; k112
; I  .a  =   ip\323
;
	Numer  midd = 1/2 Length I.a;
;
	NUMER  sh, oh, nh;    sh + oh + nh = idy;
	oh  =  $ 9.5;
	nh  =  $ 1.0;
	Numer  scf  =  oh / idy\323;
;
	iwe = scf * iwe\323;
;
; I  .h  =   I.a  Scaled( scf )  ysh( +oh/2  -+  ( in - nh ) )
;
	Path   qa  =  Subpath( 0, midd ) of I.h  --  cycle;
;
	Pairp  PP  =  0.14[ Point 1 of I.h, Point midd of I.h ];
	Pairp  QQ  =  0.47[ Point 1 of I.h, Point midd of I.h ];
;
; I  .w  =   qa  ''( 2, -20, ( PP, QQ ) )
; I  .e  =   I.w  ||
; I  .sn =   |. idy
; I      =   I.h    +++    I.sn    +++    I.w      +++    I.e
;
; I\1.h  =   ip\325.h
;
	Numer  mitt = 1/2 Length I\1.h;
;
	Path  qb  =  Subpath( 0, mitt ) of I\1.h  --  cycle;
;
	Pairp  CC  =  0.28[ Point 1 of I\1.h, Point mitt of I\1.h ];
	Pairp  DD  =  0.58[ Point 1 of I\1.h, Point mitt of I\1.h ];
;
; I\1.w  =   qb  ''( 2, +70, ( CC, DD ) )
; I\1.e  =   I\1.w  ||
; I\1    =   I\1.h    +++    I.sn    +++    I\1.w    +++   I\1.e % for i232
);

Dd( i327 )( X_any  )( Y_NORM )( % s115; k110
; I  .h  =   ip\326.h
;
	iwe = iwe\326;
;
	Numer  midd = 1/2 Length I.h;
;
	Path  p  =  Subpath( 0, midd ) of I.h;
	Path  q  =  p -- cycle;
;
	Nangle alp =  -60;
	Pairp  BB  =  0.24[ point 1 of p, fin p ];
	Pairp  CC  =  0.45[ point 1 of p, fin p ];
	Pairp  DD  =  0.66[ point 1 of p, fin p ];
;
; I  .w  =   q  ''( 3, alp, ( BB, CC, DD ) )
; I  .e  =   I.w  ||
; I  .s  =   ++++ ( iOS -- fin p )
;
	Path  pnnw  =  Subpath( midd - 0.52, midd - 0.1 ) of I.h;
	Nangle   a  =  Angle direction 0.5 of pnnw  -  90 + 20;
	Pairp  NNW  =  ( fin pnnw )  projection( a )  N_line;
	Pairp  WNW  =  ( beg pnnw )  shi( fin pnnw -+ NNW );
	if  xpart WNW < iw:
		WNW := ( iw, ypart WNW );
	fi
	Path  qnnw = pnnw  --  pnnw  shi( beg pnnw -+ WNW ) `  --  cycle;
;
; I  .nw =   qnnw    +++    qnnw ''( 1, a )
;
	Pairp  XX   =  Point( midd + 0.10 )  of  I.h;
	Pairp  YY   =  Point( midd + 0.52 )  of  I.h;
	Pairp  NNE  =  ( $ 2, in );
	Path  pnne  =  XX -- NNE{ Dir 170 } .. { Dir 210 } YY;
;
; I      =   I.h   +++   I.s   +++   I.w   +++   I.e  +++  I.nw   +++  pnne
);

		begingroup %% i328 - i372

Cc( i328, i372 )( %%
;
	save  vessel;
	vardef  vessel( expr _iw, _in, _is ) =
		Path  west =   ( _iw, _in )
		.          --- ( _iw, 1/2_is ) .. { Dir 110 }( 0, _is );
		++++ ( west   &   west || ` )
	enddef;
			% i355 relies on the `1/2' in `Path  west = ...'
;
	Pair  vessel_small_iwe   = !! $ 3  ;
	Pair  vessel_broad_iwe   = !! $ 4.0;       % i353, i367 - i372
;
	Pair  vessel_difference  =  vessel_broad_iwe  -  vessel_small_iwe;
;
	Pair  iwe_base = vessel_small_iwe;
;
	Pairp  wN  =  (  first vessel_small_iwe, in_base );
	Pairp  eN  =  ( second vessel_small_iwe, in_base );
); %%

Dd( i328 )( X_SYM  )( Y_NORM )( % s314; k310
;
	iwe = iwe_base;
;
; I      =   vessel( iw, in, is )
;
	Path   p = ppath I;
;
; I  .wnw=   ++++ ( subpath( 0, 1       ) of p )     % for i355
; I  .sw =   ++++ ( subpath(    1, 2    ) of p )     % for i355
; I  .w  =   ++++ ( subpath( 0,    2    ) of p )
; I  .e  =   ++++ ( subpath(       2, 4 ) of p )
);

Dd( i329 )( X_SYM  )( Y_NORM )( % s315; k311
;
	iwe = iwe_base;
;
; I  .h  =   ip\328
; I  .n  =   ii_mini  ysh( +mini/2  -+  in )
; I      =   I.h    +++    I.n
);

Dd( i330 )( X_SYM  )( Y_NORM )( % s316; k312
;
	iwe = iwe_base;
;
; I  .h  =   ip\328
; I  .n  =   iii_mini  ysh( +mini/2  -+  in )
; I      =   I.h    +++    I.n
);

Dd( i331 )( X_any  )( Y_HIGH )( % s324; k323
; I  .h  =   vessel( iw_base, yn_shrinked, is )
; I  .n  =   ip\389.o  ysh( ~.?.y_n  -+  in )
; I      =   I.h    +++    I.n
;
	iwe = ( iw_base, max( ie_base, I.n.?.x_e ) );
;
);

			begingroup %% i332 - i335

Cc( i332, i335 )( %%
	Numer  sh  =  $ 3;
;
	Pairp  CC  =  OQ  ysh $ 1;
	Nangle  a  =  Angle( CC  -+  ( 3/2 iw_base, is_base ) );
); %%

Dd( i332 )( X_SYM  )( Y_NORM )( % s317.1; k313.359
;
	iwe = 3/2 iwe_base;
;
	Pairp  NW   =  ( iw_base,  in   );
	Pairp  WO   =  ( iw_base,  -$ 1 );
	Pairp  SO   =  (    0 , is + sh );
	Path   west =  NW  ---  WO  ..  { right } SO;
	Path   pp   =  west  &  west || `;
;
; I  .n  =   ++++ pp
; I  .s  =   |. sh  ysh( -sh/2  -+  is )
; I  .sn =   I.n    +++    I.s
; I  .d  =   S_line
; I  .sw =   ( I.n, I.d ) ''( 2, CC, ( a, 1/2[180, a] ) )
; I  .se =   I.sw  ||
; I      =   I.sn   +++    I.sw   +++    I.se
);

Dd( i333 )( X_SYM  )( Y_NORM )( % s317.2; k313.375
; I  .n  =   ip\332.n
; I  .sn =   ip\332.sn
; I  .d  =   S_line  ysh 2/3 sh
; I  .sw =   ( I.n, I.d ) ''( 1, OQ, ( a ) )
; I  .se =   I.sw  ||
; I      =   I.sn   +++    I.sw   +++    I.se
;
	iwe = !! max( ie_base, I.se.?.x_e );
;
);

Dd( i334 )( X_SYM  )( Y_ROOF )( % s318; k314
; I  .h  =   ip\333
; I\1    =   I.h  Transformed ysc_shrink
; I      =   I\1  roofed( r_acute )
;
	iwe = !! max( ie\333, ( fig_right I ).?.x_e );
;
);

Dd( i335 )( X_SYM  )( Y_NORM )( % s320.2; k317.407
; I  .h  =   ip\333
;
	iwe = iwe\333;
;
; I  .n  =   |. (1/2 idy)  ysh( +(1/2 idy)/2  -+  in )
; I      =   I.h    +++    I.n
);

			endgroup ; %% i332 - i335

Dd( i336 )( X_SYM  )( Y_NORM )( % s319.1; k316.197
;
	iwe = iwe_base;
;
	NUMER  nh, oh;
	nh  =  $ 6;
	oh  =  $ 2;
;
; I  .h  =   ip\328
; I  .n  =   |.         nh  ysh( +nh/2  -+    in        )
; I  .o  =   oval_norm. oh  ysh( +oh/2  -+  ( in - nh ) )
; I  .sn =   I.n    +++    I.o
; I      =   I.h    +++    I.sn
);

Dd( i337 )( X_SYM  )( Y_NORM )( % s320.1; k317.322
; I  .h  =   ip\332
;
	iwe = iwe\332;
;
	NUMER  nh, oh;
	nh  =  $ 4;
	oh  =  $ 2;
;
; I  .n  =   |.         nh  ysh( +nh/2  -+    in        )
; I  .o  =   oval_norm. oh  ysh( +oh/2  -+  ( in - nh ) )
; I  .sn =   I.n    +++    I.o
; I      =   I.h    +++    I.sn
);

			begingroup %% i338 - i341

Cc( i338, i341 )( %%
	Pairp  SW  =  ( iw_base, is_base );
	Pairp  SE  =  ( ie_base, -$ 1    );
;
	Path   p   =  wN  --  SW { Dir 80 }  ..  { Dir 30 } SE  ---  eN;
	Numer  nh  =  $ 2;
); %%

Dd( i338 )( X_any  )( Y_NORM )( % s323; k322
;
	iwe = iwe_base;
;
; I  .h  =   ++++ p
; I  .b  =   rectangle( idx_base, nh )   +++   rectangle( 2/4 idx_base, nh )
.                                        +++   |. nh
; I  .n  =   I.b  ysh( +nh/2  -+  in )
; I      =   I.h    +++    I.n
);

Dd( i339 )( X_any  )( Y_ROOF )( % s; k321
; I  .h  =   ip\338.h
; I  .b  =   rect_open( idx_base, nh )  |:    +++    |. nh
; I  .n  =   I.b  ysh( +nh/2  -+  in_base )
; I\0    =   I.h    +++    I.n
; I\1    =   I\0  Transformed ysc_shrink
; I      =   I\1  roofed( r_straight )
;
	iwe = iwe_base  +  !! roof_distance[ r_straight ];
;
);

Dd( i340 )( X_SYM  )( Y_NORM )( % s321; k318
;
	iwe = iwe_base;
;
; I  .h  =   ip\328
;
	Pairp  CC  =  OQ;
	Pairp  WW  =  CC  projection( -120 ) I.h;
;
; I  .o  =   ++++ ( WW  --  CC  --  WW || )
; I      =   I.h    +++    I.o
);

Dd( i341 )( X_any  )( Y_NORM )( % s322; k320
;
	iwe = iwe_base;
;
; I  .h  =   ip\338.h
; I  .c  =   ++++ ( ( iw, -$ 1 ) -- ( ie, +$ 1 ) )
; I  .o  =   I.c    +++    ( I.c, I.h ) ''( 2, 0, ( iWO/3, iEO/3 ) )
; I      =   I.h    +++    I.o
);

			endgroup ; %% i338 - i341

			begingroup %% i342 - i346

% Cc( i342, i346 )( %%
% ;
% ); %%

Dd( i342 )( X_SYM  )( Y_NORM )( % s325; k324
; I  .h  =   ip\328
;
	save  pot;
	vardef  pot  primary hh =
		Figure  fsq  =  square_open. hh  |>90;
		Figure  fnw  =  fsq  shi( ( +hh, +hh )/2  -+  wN );
		Figure  fne  =  fnw  ||;
		Figure  fnn  =  fnw    +++    fne;

		I.h    +++    fnn
	enddef;
;
	Numer  dd = $ 2;
;
; I  .b  =   square_open. dd  |>90
; I  .nw =   I.b  shi( ( +dd, +dd )/2  -+  wN )
; I  .w  =   ip\328.w    +++    I.nw              % for i352
;
; I      =   pot( dd )
;
	iwe = iwe_base  +  !! dd;
;
; I\2    =   pot( 1/2 idy )   % variant for i015
; I\4    =   pot( 1/4 idy )   % variant for i353
);

Dd( i343 )( X_SYM  )( Y_NORM )( % s326; k325
; I  .h  =   ip\342
; I  .n  =   i_mini  ysh( +mini/2  -+  in )
; I      =   I.h    +++    I.n
;
	iwe = iwe\342;
;
);

Dd( i344 )( X_SYM  )( Y_NORM )( % s327; k326
; I  .h  =   ip\342
; I  .n  =   ip\329.n
; I      =   I.h    +++    I.n
;
	iwe = iwe\342;
;
);

Dd( i345 )( X_SYM  )( Y_NORM )( % s328.2; k327.208
; I  .h  =   ip\342
; I  .n  =   ip\330.n
; I      =   I.h    +++    I.n
;
	iwe = iwe\342;
;
);

Dd( i346 )( X_SYM  )( Y_NORM )( % s329; k329
;
	iwe = !! $ 6;
;
	Numer  dd = $ 3;
;
; I  .h  =   ip\345
; I  .o  =   iii_mini  ysh( 0  -+  5/12 is )
; I  .c  =   |. idy
; I  .d  =   square_open. dd  |<90
; I  .x  =   I.c    +++    I.d  shi( ( -dd, +dd )/2  -+  iON )
; I  .sw =   I.x  ysh( is  -+  0 )  |<120  scx (idx/2)  ysh( 0  -+  $ 1 )
; I  .se =   I.sw  ||
; I      =   I.h    +++    I.o    +++    I.sw    +++    I.se
);

			endgroup ; %% i342 - i346

			begingroup %% i347 - i361

Cc( i347, i361 )( %%
	Numer  ee_halfwidth = 5/12 idx_base;
); %%

Dd( i347 )( X_SYM  )( Y_NORM )( % s332.3; k332.248
;
	.                       % tune it with i348
%	Numer  dx =  idx_base - ee_halfwidth - stroke_distance_x;
	Numer  dx = 2 idx_base/3;
	Numer  dy = $ 3;
;
; I  .h  =   ip\328
; I  .d  =   tri_open( dx, dy )  |:
; I  .nw =   I.d   shi( (0, dy/2)  -+  wN )
; I  .w  =   ip\328.w    +++    I.nw
; I  .e  =   I.w  ||
; I      =   I.w    +++    I.e
;
	iwe = iwe_base  +  !! ( dx/2 );
;
);

Dd( i348 )( X_any  )( Y_NORM )( % s103; k096
;
	Numer  dx = 2 ee_halfwidth;     % tune it with i347 and i358
;
; I  .d  =   ip\173.h  xsc dx
; I  .ne =   I.d   shi( iON  -+  eN )
; I  .w  =   ip\347.w
; I  .e  =   ip\328.e    +++    I.ne
; I      =   I.w    +++    I.e
;
	iwe = ( iw\347, ie_base + dx/2 );
;
);

Dd( i349 )( X_any  )( Y_NORM )( % s334; k335
;
	iwe = iwe\347 + ( - bridge_width_default_wide, 0 );
;
; I  .w  =   |. idy  xsh( 0  -+  iw )
; I  .e  =   ip\347
;
	Pairp  XX  =  ( iw, $ 1 );
	Pairp  YY  =  ip\328.w  where_y  $ 1;
;
; I   .o =   ++++( XX -- YY )
; I      =   I.w    +++    I.o    +++    I.e
);

Dd( i350 )( X_any  )( Y_NORM )( % s335; k336
; I  .h  =   ip\347
; I  .e  =   |. (1/3 idy)  ysh ($ 0.5)
; I      = ( I.h    ++("")+-    I.e )  connected( $ 0, "alpha" )
;
	iwe = iwe\347  +  ( 0, +distance_x_low );
;
);

Dd( i351 )( X_any  )( Y_NORM )( % s111; k106
; I  .w  =   ip\347.w
; I  .e  =   ip\321.e |:
;
	iwe = iwe\347;
;
	Pairp  CC   =  I.e  where_y  -$ 1;
;
; I  .c  =   oval_medium. $$  |>100  scx 2( xpart CC -+ ie )
; I  .ene=   I.c  shi( OQ  -+  CC )
; I  .x  =   I.e    +++    I.ene
; I      =   I.w    +++    I.x
);

Dd( i352 )( X_any  )( Y_NORM )( % s331; k331
; I  .w  =   ip\342.w
; I  .e  =   ip\347.e
; I      =   I.w    +++    I.e
;
	iwe = ( iw\342, ie\347 );
;
);

Dd( i353 )( X_SYM  )( Y_HIGH )( % s336; k
;
	iwe = vessel_broad_iwe;
;
; I  .a  =   vessel( iw, yn_shrinked, is )
;
	Numer  pot_fac  =  ( yn_high - yn_shrinked ) / yn_normal;
;
	Numer  bo  =  min( 2 idx/6, idx\328 * pot_fac );
	Numer  bb  =  ( idx - bo ) / 4;
;
	Numer  ha  =  min( max( $ 2, yn_high - yn_shrinked ), $ 3 );
;
; I  .c  =   ip\328.w  zsc( bb, ha )
; I  .ne =   I.c  shi( ( 0, ha/2 )  -+  ( ie, yn_shrinked ) )
; I  .nw =   I.ne  ||
; I  .h  =   I.a    +++    I.nw    +++    I.ne
; I  .d  =   ip\342\4  Xscaled( bo / idx\328 )  Yscaled pot_fac
; I  .n  =   I.d  ysh( +( yn_high - yn_shrinked )  -+  in )
; I      =   I.h    +++    I.n
);

Dd( i354 )( X_SYM  )( Y_NORM )( % s319.2; k316.398
;
	iwe = iwe_base;
;
; I  .a  =   ip\328
;
	Numer  ha = $ 3;
;
; I  .c  =   ip\328.w  zsc( idx/4, ha )
; I  .ne =   I.c  shi( ( 0, +ha/2 )  -+  iEN )
; I  .nw =   I.ne  ||
; I  .h  =   I.a    +++    I.nw    +++    I.ne
; I  .n  =   ip\336.sn
; I      =   I.h    +++    I.n
);

Dd( i355 )( X_SYM  )( Y_NORM )( % s337; k337
;
	Numer  r   =  idx_base/2;
	Pairp  CC  =  ( 0, is + r );
;
	Path   pa   =  ppath ip\328.sw; % but quartercircle has 3 points ...
	Pair   tt   =  pa  intersectiontimes  jet( CC, -135 );
	Path   pb   =     Subpath( 0, first tt ) of pa
	.              &  Subpath( first tt, 1 ) of pa;
;
	Path   pc   =  quartercircle  |||:  scaled( 2 r )  ysh( OQ  -+  CC );
	Path   psw  =  interpath( 1/2, pb, pc );
	Path   pwnw =  ppath ip\328.wnw;
	Path   west =  pwnw  &  psw;
;
; I  .w  =   west    +++    ip\347.nw
; I  .e  =   I.w  ||
; I  .h  =   I.w    +++    I.e
;
	Path   phc =  halfcircle  scaled( 2 r )  ysh( OQ  -+  CC );
	Pairp  NE  =  phc  Intersectionpoint_left  jet( CC, 60     );
	Pairp  SW  =  psw  Intersectionpoint_left  jet( CC, 60+180 );
	Path   q   =  NE  --  SW;
;
; I  .o  =   phc    +++    q   +++  |. (2 r)  ysh( OQ  -+  CC )  +++   q ||
; I      =   I.h    +++    I.o
;
	iwe = iwe\347;
;
);

Dd( i356 )( X_SYM  )( Y_NORM )( % s; k334
; I  .h  =   ip\347
;
	Pairp  NN   =               OQ  ;    % `balks' upper point
	Numer  b    =  stroke_distance_x;    % breadth of the `balks'
	Nangle alf  =                 70;    % angle at NN
;
	Pairp  ENE  =  NN   shi( ( b/sind alf )  *  Dir( 180-alf/2 ) );
	Pairp  WSW  =  NN   projection( 180 + alf/2 )  ip\328.w;
	Pairp  SSW  =  ENE  projection( 180 + alf/2 )  ip\328.w;
;
; I  .sw =   ++++ ( WSW  --  NN  --  ENE  --  SSW )
; I  .se =   I.sw  ||
; I  .o  =   I.sw    +++    I.se
; I      =   I.h     +++    I.o
;
	iwe = iwe\347;
;
);

Dd( i357 )( X_SYM  )( Y_NORM )( % s333; k333
; I  .h  =   ip\347
;
	Pairp  CC  =  ( 0, 2/3 is );
	Nangle alf =  120;
;
	Pairp  SW  =  CC projection( 180 + 1/2 alf ) ip\328.w;
	Pairp  NE  =  CC projection(       1/2 alf ) ip\328.e;
;
; I  .sw =   ++++ ( SW -- NE )
; I  .se =   I.sw  ||
; I  .o  =   I.sw    +++    I.se
; I      =   I.h     +++    I.o
;
	iwe = iwe\347;
;
);

Dd( i358 )( X_any  )( Y_NORM )( % s332.4; k332.276
;
	.                       % tune it with i347
	Numer  dx =  idx_base - ee_halfwidth - distance_x_low;
	Numer  dy =  $ 3;
	Path p = ( dx, 0 ) -- OQ -- ( 0, -dy ){ Dir 65 } .. { Dir 10 }( dx, 0 );
	Path q = (0, -0.45 dy) -- ( subpath(2, 3) of p  where_y  -0.45 dy );
;
; I  .d  =   p    +++    q
; I  .nw =   I.d   shi( OQ  -+  wN )
; I  .ne =   I.nw  xsh( wN  -+  eN )
; I  .w  =   ip\328.w    +++    I.nw
; I  .e  =   ip\328.e    +++    I.ne
; I  .h  =   I.w    +++    I.e
; I      =   I.h
;
	iwe = ( iw_base, ie_base  +  dx );
;
);

Dd( i359 )( X_any  )( Y_NORM )( % s; k
; I  .w  =   ip\358.w
; I  .e  =   ip\348.e
; I  .h  =   I.w    +++    I.e
; I      =   I.h
;
	iwe = ( iw\358, ie\348 );
;
);

Dd( i360 )( X_any  )( Y_NORM )( % s; k
; I  .h  =   ip\358
; I  .w  =   |. idy
; I      = ( I.w    +-("")++   I.h )  connected( $ 1, $ 1 )
;
	iwe = iwe\358  +  ( -bridge_width_default_wide, 0 );
;
);

Dd( i361 )( X_any  )( Y_NORM )( % s; k
; I  .h  =   ip\358
; I  .o  =   ip\340.o
; I      =   I.h    +++    I.o
;
	iwe = iwe\358;
;
);

			endgroup ; %% i347 - i361

			begingroup %% i362 - i372

Cc( i362, i372 )( %%
	Numer  rx_triangle  = $ 1.5; % i362f, i368f % little triangle - width/2
	Numer  ry_triangle  = $ 0.5; % i362f, i368f % little triangle - height/2
;
	Numer  rx_umbrella  = ( idx_base - distance_x_low )/2;    % i364
	Numer  ry_umbrella  = $ 1.0;                              % i364
;
	Numer  rx_petal     = $ 2.0;  % * 2 = ( $$ - idx_broad )  % i370
	Numer  ry_petal     = $ 1.0;                              % i370
;
	Numer  rx_comb      = $ 1.0;  % * 4 = ( $$ - idx_broad )  % i371
	Numer  ry_comb      = $ 2.0;                              % i371
;
	Numer  ry_oval      = $ 1.0;  % i368 - i370   % little oval - height/2
;
	Pairv  shift_a  = ( 0, -$ 1   ); % i362ff, i368ff
	Pairv  shift_b  = ( 0, -$ 1.5 ); % i363  , i369    % (added on shift_oa)
	Pairv  shift_oa = ( 0, -2 ry_oval ) + 0.80 shift_a;
); %%

Dd( i362 )( X_EQB  )( Y_NORM )( % s; k
; I  .a  =   ip\328
; I  .d  =   tri_open( 2 rx_triangle, 2 ry_triangle )
;
	Pairp  NN  =  ( 0, +ry_triangle );
;
; I  .nw =   I.d  shi( NN  -+  ( wN + shift_a ) )
; I  .ne =   I.d  shi( NN  -+  ( eN + shift_a ) )
; I  .n  =   I.nw    +++    I.ne
;
; I  .o  =   ip\053  Scaled 1/3  ysh( 0  -+  (-$ 1) )
; I  .z  =   I.a     +++    I.o
; I      =   I.z     +++    I.n
;
	iwe = iwe_base  +  !! rx_triangle;
;
);

Dd( i363 )( X_EQB  )( Y_NORM )( % s; k
; I  .a  =   ip\362
; I  .n  =   ip\362.n  ysh shift_b
; I      =   I.a     +++    I.n
;
	iwe = iwe\362;
;
);

Dd( i364 )( X_EQB  )( Y_NORM )( % s; k
; I  .a  =   ip\362.z
;
	Pairp  NE =  (            0 , 2 ry_umbrella );
	Pairp  SW =  ( -rx_umbrella ,             0 );
	Pairp  SE =  (            0 ,             0 );
;
	Path p =  NE {    left     }  ..  { Dir   -150  } % SW
	.         SW { Dir (90-15) }  ..  { Dir (90+15) }   SE;
;
	Pairp  CC  =  ( 0  , -$ 6 );
	Pairp  XX  =  1/3[ SE, SW ];
;
; I  .b  =   ++++ p
; I  .x  =   I.b   +++   I.b ''( 1, CC, ( XX ) ) % one stripe may be enough
; I  .y  =   I.x   +++   I.x  ||
;
	Pairp  NN  =  NE;
;
; I  .nw =   I.y  shi( NN  -+  ( wN + shift_a ) )
; I  .ne =   I.y  shi( NN  -+  ( eN + shift_a ) )
; I  .n  =   I.nw    +++    I.ne
; I      =   I.a     +++    I.n
;
	iwe = iwe_base  +  !! rx_umbrella;
;
);

Dd( i365 )( X_SYM  )( Y_NORM )( % s; k315
; I      =   ip\134  |:    +++    |. idy
;
	iwe = iwe\134;
;
);

Dd( i366 )( X_any  )( Y_NORM )( % s; k
;
	iwe = !! $ 4;
;
; I  .n  =   ip\332.n  xsh( ~.?.x_e  -+  ie )
;
	Pairp  NN    =  I.n.?.s;                   % = $( 1, -3 )
	Path   north =  NN  --  ( xpart NN, in );
;
	Pairp  NNN   =  NN  xsh $ 0.1;   % fight optical illusion
	Pairp  WSW   =  ( iw      , -$ 5 );
	Pairp  SSW   =  ( iw + $ 1,   is );
	Pairv  delta =  $ 0.3  *  down;
;
	Path   south =  flex( NNN, 1/2[ WSW, NNN ] + delta, WSW )
	.            -- flex( SSW, 1/2[ SSW, NNN ] + delta, NNN );
;
; I      =   I.n    +++    south    +++    north
);

				begingroup %% i367 - i372

Cc( i367, i372 )( %%
	Numer  rry_main  =  idy_base - 2 ry_oval;
	Numer   in_main  =   in_base - 2 ry_oval;
;
	Pairp  wN  =  (  first vessel_broad_iwe, in_base );
	Pairp  eN  =  ( second vessel_broad_iwe, in_base );
); %%

Dd( i367 )( X_SYM  )( Y_NORM )( % s; k
;
	iwe = vessel_broad_iwe;
;
	NUMER  sh, nh;    sh + nh = idy;
	sh  =  $ 8;
;
	Pairp  OS   =  (    0  ,      is ); % = iOS
	Pairp  WW   =  (     iw,  1/6 in );
	Pairp  NW   =  ( 3/4 iw,      in );
	Path   swn  =  OS  ..  { up } WW  ..  NW;
;
	Pairp  WNW  =  swn  where_y  ( in - nh );
	Path   pwo  =  NW { Dir 150 }  .. tension 0.80 ..  WNW;
	Path   west =  swn      &   pwo;
	Path   p    =  west `   &   west ||;
;
; I  .h  =   ++++ p
;
; I  .c  =   |.           sh  ysh( -sh/2  -+  is )
; I  .d  =   oval_narrow. nh  ysh( +nh/2  -+  in )
; I  .o  =   I.c    +++    I.d
;
; I      =   I.h    +++    I.o
);

Dd( i368 )( X_SYM  )( Y_NORM )( % s122.1; k117.215
; I  .a  =   vessel( first vessel_broad_iwe, in_main, is ) % for i368-i370
; I  .b  =   |. rry_main  ysh( -rry_main/2  -+  is )
; I  .h  =   I.a    +++    I.b
;
; I  .c  =   oval_norm( 2 ry_oval )
; I  .nw =   I.c  shi( ( 0, +ry_oval )  -+   wN )
; I  .ne =   I.c  shi( ( 0, +ry_oval )  -+   eN )
; I  .no =   I.c  shi( ( 0, +ry_oval )  -+  iON )
; I  .n  =   I.nw    +++    I.no    +++    I.ne
;
; I  .z  =   I.h    +++    I.n
;
; I  .d  =   ip\362.d
; I  .wnw=   I.d  shi( ( 0, +ry_triangle )  -+  (  wN + shift_oa ) )
; I  .ene=   I.d  shi( ( 0, +ry_triangle )  -+  (  eN + shift_oa ) )
; I  .so =   I.d  shi( ( 0, +ry_triangle )  -+  ( iON + shift_oa ) )
; I  .o  =   I.wnw   +++    I.so    +++    I.ene
;
; I      =   I.z    +++    I.o
;
	iwe = vessel_broad_iwe  +  !! rx_triangle;
;
);

Dd( i369 )( X_SYM  )( Y_NORM )( % s; k
; I  .a  =   ip\368
; I  .o  =   ip\368.o  ysh shift_b
; I      =   I.a    +++    I.o
;
	iwe = iwe\368;
;
);

Dd( i370 )( X_SYM  )( Y_NORM )( % s; k
; I  .a  =   ip\368.z
;
	Pairp  NE =  (         0, 2 ry_petal );
	Pairp  SW =  ( -rx_petal, 0          );
	Pairp  SE =          1/3 NE           ;
;
	Path  petal_w  =  NE { Dir -90 }  ..  { Dir  -170 } % SW
	.                 SW { Dir  60 }  ..  { Dir    90 }   SE;
;
; I  .d  =   ++++ petal_w
; I  .wnw=   I.d  shi( NE  -+  (  wN + shift_oa ) )
; I  .nnw=   I.d  shi( NE  -+  ( iON + shift_oa ) )
; I  .wo =   I.wnw   +++    I.nnw
; I  .eo =   I.wo  ||
; I  .o  =   I.wo    +++    I.eo
; I      =   I.a     +++    I.o
;
	iwe = vessel_broad_iwe  +  !! rx_petal;
;
);

Dd( i371 )( X_SYM  )( Y_NORM )( % s122.2; k117.214
; I  .a  =   vessel( first vessel_broad_iwe, in, is )
; I  .b  =   |. idy
; I  .h  =   I.a    +++    I.b
;
;    pit:=   ip\176   % make sure, we can access IP(176)
;
; I  .d  =   IP( 176 )( 2 ry_comb, 2 rx_comb, 180, 180 + 90, tT, 3 )
; I  .nnw=   I.d  shi( ( +rx_comb,  +ry_comb )  -+  iON )
; I  .wnw=   I.nnw  xsh first vessel_broad_iwe
; I  .wo =   I.wnw   +++    I.nnw
; I  .eo =   I.wo  ||
; I  .o  =   I.wo    +++    I.eo
; I      =   I.h     +++    I.o
;
	iwe = vessel_broad_iwe  +  !! 2 rx_comb;
;
);

Dd( i372 )( X_any  )( Y_NORM )( % s112; k107
;
	iwe = !! $ 6;
;
; I  .h  =   ip\371.a
;
	Pairp  NW   =  wN;
	Pairp  SW   =  NW  ysh -($ 3);
	Pairp  ENE  =  1/2[ NW, SW ]  xsh ($ 1.5);
;
	Path   pnw  =  NW  ..  ENE  ..  SW;
;
; I  .nw =   ++++ pnw
;
	Pairp  CC   =  I.h  first_where_y  -$ 1;
;
; I  .c  =   oval_medium. $$  |<100  scx 2( iw -+ xpart CC )
; I  .wnw=   I.c  shi( OQ  -+  CC )
;
; I  .d  =   ip\347.nw
; I  .ne =   I.d  xsh( first vessel_small_iwe  -+  second vessel_broad_iwe )
;
; I  .o  =   ip\397\2
; I      =   I.h    +++    I.nw    +++    I.wnw    +++    I.o    +++    I.ne
);

				endgroup ; %% i367 - i372

			endgroup ; %% i362 - i372

		endgroup ; %% i328 - i372

Dd( i373 )( X_SYM  )( Y_NORM )( % s357.2; k355.157
; I      =   oval_egg. idy
;
	iwe = !! ( I.?.x_e );
;
);

Dd( i374 )( X_SYM  )( Y_any  )( % s356; k355.381
;
	iwe = !! $ 2.5;
	isn = iwe / golden_ratio;
;
; I      =   oval_egg. idy
);

Dd( i375 )( X_SYM  )( Y_NORM )( % s364; k366
; I      =   ip\373    +++    |. $ 5
;
	iwe = iwe\373;
;
);

Dd( i376 )( X_any  )( Y_NORM )( % s365; k367
; I  .h  =   ip\375
; I  .a  =   ip\373
;
	Pairp  PP  =  Point 0.3 of I.a;
	Pairp  QQ  =  Point 0.6 of I.a;
	Pairp  NN  =  ( xpart QQ + $ 0.8 , in );
	Path   pne =      PP { ( PP -+ NN ) |> 10 }  ..  NN
	.            &    NN { ( NN -+ QQ ) |< 30 }  ..  QQ;
;
; I  .ne =   ++++ pne
; I      =   I.h    +++    I.ne
;
	iwe = ( iw\373, max( ie\373, pne.?.x_e ) );
;
);

Dd( i377 )( X_any  )( Y_NORM )( % s114; k109
; I  .a  =   ip\397\5
; I  .b  =   ip\375
;
	Numer  raxus  =  rx I.a  +  rx I.b  +  distance_x_low/2;
;
	iwe = !! ( raxus  +  split_distance_default  +  0 );
;
; I  .w  =   I.a  xsh( -rx I.a  -+  -raxus )
; I  .e  =   I.b  xsh( +rx I.b  -+  +raxus )
; I\1    =   I.w    +++    I.e
; I      =   I\1    +++    ii_ii  splitted
);

Dd( i378 )( X_SYM  )( Y_NORM )( % s; k
; I      =   ip\373    +++    |. idy
;
	iwe = iwe\373;
;
);

Dd( i379 )( X_EQB  )( Y_NORM )( % s369; k372
; I      =   ip\373    +++    iii_mini  sla -1.5/6  |>90
;
	iwe = iwe\373;
;
);

Dd( i380 )( X_SYM  )( Y_NORM )( % s372; k376
; I  .a  =   ip\373
;
	Pairp  WW  =  ( iw\373, 0 );
	Pairp  EE  =  ( ie\373, 0 );
;
; I  .b  =   I.a  ''( 3, +40, ( WW, OQ, EE ) )
; I  .c  =   I.b  ||
; I      =   I.a    +++    I.b    +++    I.c
;
	iwe = iwe\373;
;
);

Dd( i381 )( X_EQB  )( Y_NORM )( % s366; k369
; I  .h  =   ip\373
; I  .o  =   ip\241  sla -1.5/6  Scaled( ($ 4)/idy\241 )  |>90
; I      =   I.h    +++    I.o
;
	iwe = iwe\373;
;
);

Dd( i382 )( X_EQB  )( Y_NORM )( % s; k
;
	iwe = iwe\373;
;
; I  .h  =   ip\373
;
;    pit:=   ip\176   % make sure, we can access IP(176)
;
; I  .b  =   IP( 176 )( $ 4 , $ 4/3, 70, 170, tT, 4 )
; I  .x  =   I.b  shi( ( $ 2/3 + 1/2 stroke_distance_y ) * Dir 170 )
; I  .c  =   I.x  |||:
; I  .o  =   I.x    +++    I.c
; I      =   I.h    +++    I.o
);

Dd( i383 )( X_EQB  )( Y_NORM )( % s; k
; I  .h  =   ip\373
;
	NUMER  wh, eh;    wh + oval_corr = eh;
	wh  =  $ 4;
;
; I  .b  =   ip\176  Scaled( wh / idy\176 )
; I  .c  =   oval_medium. eh
;
	Numer  scf_b  =  wh / idy\176;
	Numer  scf_c  =  1/2;   % for oval_medium holds: idx/idy = 1/2
;
; I  .w  =   I.b  xsh(  scf_b * ie\176  -+  -1/2 distance_x_mid )
; I  .e  =   I.c  xsh( -scf_c * eh/2    -+  +1/2 distance_x_mid )
; I  .o  = ( I.w    +++    I.e )  xsh -$ 0.2
; I      =   I.h    +++    I.o
;
	iwe = iwe\373;
;
);

Dd( i384 )( X_SYM  )( Y_NORM )( % s371; k375
; I  .h  =   ip\373
;
	Numer  oh = $ 6;
	Numer  nh = ( idy - oh ) / 2;
;
	Numer  scf  =  oh / idy\261;
;
; I  .o  =   ip\261  Scaled scf
;
	Pairp  NN  =  (            0, oh/2 );
	Pairp  WW  =  ( iw\261 * scf, 0    );
	Pairp  EE  =  WW  ||;
;
	Pairp  CC  = 1/3[ WW, NN ];
	Pairp  DD  = 2/3[ WW, NN ];
	Pairp  CX  = jet( CC, CC + ( EE -+ NN ) )  Intersectionpoint_right  I.h;
	Pairp  DX  = jet( DD, DD + ( EE -+ NN ) )  Intersectionpoint_right  I.h;
;
; I  .nw =   ++++ ( DX -- DD -- CC -- CX )
; I  .ne =   I.nw  ||
; I  .no =   |. nh  ysh( +nh/2  -+  in )
; I  .n  =   I.nw     +++    I.no     +++    I.ne
; I  .s  =   I.n   |:
; I      =   I.h    +++    I.o    +++    I.s    +++    I.n
;
	iwe = iwe\373;
;
);

Dd( i385 )( X_SYM  )( Y_NORM )( % s; k
; I  .h  =   ip\373
;
	Numer  oh  =  $ 8;
;
; I  .o  =   ip\155  Scaled( oh / idy\155 )
; I      =   I.h    +++    I.o
;
	iwe = iwe\373;
;
);

Dd( i386 )( X_SYM  )( Y_NORM )( % s; k
; I  .h  =   ip\373
;
	Numer  oh  =  -ys_normal;
;
; I  .o  =   |. oh  ysh( -oh/2  -+  is )
; I      =   I.h    +++    I.o
;
	iwe = iwe\373;
;
);

Dd( i387 )( X_SYM  )( Y_NORM )( % s; k
; I  .h  =   ip\373
; I  .b  =   ip\162
;
	Numer  oh  =  $ 8;
	Numer  scf =  oh / idy\162;
;
; I  .o  =   I.b  Scaled scf  ysh( -oh/2  -+  is )
; I      =   I.h    +++    I.o
;
	iwe = iwe\373;
;
);

Dd( i388 )( X_SYM  )( Y_NORM )( % s; k
;
	iwe = !! ( ie\373  +  split_distance_default  +  0 );
;
; I      =   ip\387    +++    ii_ii  splitted
);

Dd( i389 )( X_EQB  )( Y_NORM )( % s394; k364
;
	iwe = iwe\373;
;
; I  .h  =   ip\373
;
	NUMER  oh, ohs, ohn;    ohs + ohn = oh;
	oh  =  $ 9;
	ohn =  $ 4;
;
; I  .b  =   ip\176\3.3
; I  .x  =   I.b  |>( Angle( ~.?.nw )  -+  0 )
; I  .y  =   I.x  scy ohn  ysh( 0  -+  ( is + ohs ) )
; I  .c  =   |. ohs  ysh( -ohs/2  -+  is )
; I  .o  =   I.y    +++    I.c
; I      =   I.h    +++    I.o
);

Dd( i390 )( X_EQB  )( Y_NORM )( % s395; k365
;
	iwe = !! ( ie\373  +  split_distance_default  +  0 );
;
; I      =   ip\389    +++    ii_ii  splitted
);

Dd( i391 )( X_SYM  )( Y_NORM )( % s373; k378
; I  .h  =   ip\378
; I  .z  =   ip\373
;
	Nangle  alf =  Angle( ( ie\261, 0 )  -+  ( 0, in\261 ) );
	Pairp   PP  =  jet( OQ, alf )  Intersectionpoint_right  I.z;
;
; I  .x  =   ++++ ( -PP  --  PP )
; I  .y  =   I.x  ||
; I      =   I.h    +++    I.x    +++    I.y
;
	iwe = iwe\373;
;
);

Dd( i392 )( X_any  )( Y_NORM )( % s374; k379
; I  .a  =   ip\087
; I  .b  =   ip\391
;
	Numer  raxus  =  rx I.a  +  rx I.b  +  distance_x_low/2;
;
	iwe = !! raxus  +  !! split_distance_default  +  !! 0;
;
; I  .w  =   I.a  xsh( -rx I.a  -+  -raxus )
; I  .e  =   I.b  xsh( +rx I.b  -+  +raxus )
; I\1    =   I.w    +++    I.e
; I      =   I\1    +++    ii_ii  splitted
);

Dd( i393 )( X_SYM  )( Y_NORM )( % s339; k339
;
	iwe = !! $ 6;
;
	Path  ov =  ( 0, in ) .. { down }( ie, is );   % ~ oval_medium. $ 24
	Path  p  =  subpath( 0, 0.9 )  of  ov;
	Path  q  =  p  xscaled( ie/(xpart fin p) );
	Path  pp =  q || `   &  q;
;
; I  .n  =   ++++ pp
; I  .o  =   ip\391  Scaled( ($ 9) / idy\391 )
; I  .s  =   ii_mini  ysh( -mini/2  -+  is )
; I  .h  =   I.o    +++    I.s  splitted_by !! split_distance_default
; I      =   I.h    +++    I.n
);

Dd( i394 )( X_SYM  )( Y_NORM )( % s; k
;
	NUMER  sh, nh;    sh + nh = idy;
	sh  =  $ 6  +  oval_corr;
;
; I  .a  =   oval_norm. sh
; I  .b  =   ip\342\4
;
	Numer  scf_n  =  nh / idy\342;
;
; I  .s  =   I.a                ysh( -sh/2  -+  is )
; I  .n  =   I.b  Scaled scf_n  ysh( +nh/2  -+  in )
; I      =   I.s    +++    I.n
;
	iwe = !! ( I.?.x_e );
;
);

Dd( i395 )( X_any  )( Y_NORM )( % s; k
;
	iwe = !! good.x $ 3.5;
;
	NUMER  sh, oh, nh;    sh + oh + nh = idy;
	sh  =  $ 3;
	nh  =  $ 5;
;
	Numer  nb  =  $ 1.5;
;
	NUMER  xh, sxh, nxh;    xh = sxh + nxh = nh  +-+  nb;
	nxh =  2 nb;
;
; I  .a  =   ip\176\3.3  ysh(  nxh    -+   xh )      % $ 3 = nxh
; I  .b  =   |. sxh      ysh( +sxh/2  -+  sxh )
; I  .n  = ( I.a  +++  I.b )  |>( Angle( -nb, xh ) -+ 0 )  ysh( nh  -+  in )
; I  .s  =   IP( 176 )( idx, sh, 90, 180, tT, 4 )  ysh( -sh/2  -+  is )
; I  .o  =   ++++ (                ( iw, is + sh ) { Dir  20 }
.                   .. { Dir  60 } (  0, in - nh ) { Dir 120 }
.                   .. { Dir 160 } ( ie, is + sh )             )
; I      =   I.s    +++    I.o    +++    I.n
);

Dd( i396 )( X_SYM  )( Y_NORM )( % s; k
;
	NUMER  sh, nh;    sh + nh = idy;
%	nh  =  $ 6  +  oval_corr;  % $ 6.2, but to reduce the number of x-widths:
	nh  =  $ 4 / golden_ratio; % $ 6.47205
;
; I  .a  =   oval_golden. nh
; I  .b  =   oval_golden. 1/2 nh
; I  .n  = ( I.a    +++    I.b )  ysh( +nh/2  -+  in )
; I  .s  =   |. sh  ysh( -sh/2  -+  is )
; I      =   I.s    +++    I.n
;
	iwe = !! rx I.a;
;
);

Dd( i397 )( X_SYM  )( Y_NORM )( % s113; k108
;
	save    iooi;
	vardef  iooi( expr sh, oh, nh )( text summand ) =
		FIGURE  za, zb, zc, oz, sz, nz;
		za  =  oval_norm. oh;
		zb  =  summand;

		zc  =  if  zb <> zero:   za    +++    zb
		.      else          :   za
		.      fi;

		oz  =  zc  ysh( +oh/2 -+ ( in - nh ) );
		sz  =  |. sh  ysh( -sh/2  -+  is );
		nz  =  |. nh  ysh( +nh/2  -+  in );

		sz    +++    oz    +++    nz
	enddef;
;
; I      =   iooi( $ 4  , $ 4, $ 4   )( oval_norm. $ 1    );
; I\2    =   iooi( $ 4.5, $ 3, $ 4.5 )( zero              ); % for i372
; I\5    =   iooi( $ 3.5, $ 5, $ 3.5 )( oval_norm. $ 1.25 ); % for i377
; I\7    =   iooi( $ 5  , $ 5, $ 2   )( zero              ); % for i399
; I\8    =   iooi( $ 4  , $ 4, $ 4   )
.           ( za ''( 3, 45, ( OQ, (0, +$ 1.1), (0, -$ 1.1) ) ) ); % for i398
;
	iwe = !! ( I.?.x_e );
;
);

Dd( i398 )( X_EQB  )( Y_NORM )( % s052; k047
;
	Numer  nb  =  $ 2;
	Numer  nh  =  $ 1;
;
; I  .h  =   ip\397\8
; I  .n  =   tri_open( nb, nh )  ysh( +nh/2  -+  in )
; I      =   I.h    +++    I.n
;
	iwe = !! max( ie\397, nb/2 );
;
);

Dd( i399 )( X_SYM  )( Y_NORM )( % s362; k360
;
	iwe = !! good.x $ 3.5;
;
	Pairp  AA  =  jet( OQ, 1/2 Angle iEN )  Intersectionpoint_right  N_line;
;
; I  .h  =   ip\397\7
; I  .ne =   ( I.h, N_line )  ''( 2, OQ, ( AA, iEN ) )
; I  .nw =   I.ne  ||
; I  .n  =   I.nw    +++    I.ne
; I      =   I.h     +++    I.n
);

Dd( i400 )( X_any  )( Y_NORM )( % s108; k103
;
	iwe = !! $ 2.75;
;
	NUMER  sh, nh;    sh + nh = idy;
	sh  =  $ 8;
;
; I  .a  =   oval_narrow. nh
; I  .n  =   I.a  xsh( rx I.a  -+  ie )  ysh( +nh/2  -+  in )
;
	Pairp  XX  =  ( 0, -nh/2 )  xsh( rx I.a  -+  ie )  ysh( +nh/2  -+  in );
;
; I  .s  =   ++++ ( iWS  --  XX )
;
	Nangle  alf = Angle( iWS -+ XX );
	Pairp   MM  = I.s  where_y  0;
;
; I  .x  =   I.a  |< ( 90 - alf )
; I  .y  =   I.x  Scaled min( 1, (xpart MM -+ ie) / ( I.x.?.x_e ) )
; I  .o  =   I.y  xsh( OQ -+ MM )
; I      =   I.s    +++    I.o    +++    I.n
);

Dd( i401 )( X_any  )( Y_NORM )( % s109; k104
;
	iwe = iwe\400  +  !! split_distance_default  +  !! 0;
;
; I      =   ip\400    +++    ip\087  splitted
);

Dd( i402 )( X_any  )( Y_NORM )( % s207; k202
;
		% There is some freedom to choose the width,
		% so we choose to make the dimensions equal to those of i416.
;
	iwe = iwe\416;
;
; I  .a  =   |. idy  sla 1.5/6  xsh( -$ 1.5  -+  iw )
;
	Pairp  PP  =  Point 0.65 of I.a;
	Pairp  QQ  =  Point 0.35 of I.a;
	Pairp  EE  =  ( ie, ypart QQ  - $ 0.8 );
	Pairp  PQ  =  0.5[ PP, QQ ];
	Path    p  =            QQ { ( QQ -+ EE )  |< 10 }  ..  EE
	.            softjoin   EE { Dir -10 }  ..  { Dir -45 } PP;
;
; I  .b  =   p     +++   p  ''( 2, Angle I.a, ( 0.31[PQ,EE], 0.62[PQ,EE] ) )
; I      =   I.a   +++   I.b
);

		begingroup %% i403 - i407

Cc( i403, i407 )( %%
	Pair     iwe_base = !! $ 6;
); %%

Dd( i403 )( X_SYM  )( Y_NORM )( % s350; k349
;
	iwe = iwe_base;
;
; I  .a  =   ip\373
; I  .w  =   I.a  xsh( iw\373  -+  iw )
; I  .e  =   I.a  xsh( ie\373  -+  ie )
; I      =   I.w    +++    I.e
);

Dd( i404 )( X_SYM  )( Y_NORM )( % s351; k350
;
	iwe = iwe_base  +  !! ( split_distance_default  +  0 );
;
; I      =   ip\403    +++    ii_ii  splitted
);

Dd( i405 )( X_any  )( Y_NORM )( % s352; k351
; I  .h  =   ip\403
; I  .b  =   ip\091.y
; I  .e  =   I.b  xsh( 0  -+  ie\403 )
; I      =   I.h    +++    I.e
;
	iwe = iwe_base  +  ( 0, I.b.?.x_e );
;
);

Dd( i406 )( X_SYM  )( Y_NORM )( % s; k
;
	iwe = iwe_base;
;
; I      =   ip\403    +++    iii_mini  xsc $ 6
);

Dd( i407 )( X_EQB  )( Y_NORM )( % s353; k352
;
	iwe = iwe_base;
;
; I  .h  =   ip\403
; I  .a  =   ip\403.w
;
	Numer  ring_ring_delta = idx - idx\373;

	Path  w_w = Subpath( 1/2 Length I.a, Length I.a ) of I.a;
	Path  e_w = w_w  xsh ring_ring_delta;

	Pairp  CC =  OQ  xsh -1/2 ring_ring_delta;

	Path    p = jet( CC, -65 );
	Path    q = jet( CC, 115 );
	Pairp  PP = p  Intersectionpoint_right  w_w;
	Pairp  QQ = q  Intersectionpoint_right  e_w;
;
	Path   r = jet( OQ, -65 );
	Pairp  RR = r  Intersectionpoint_right  e_w;
;
; I  .o  =   ( PP  --  QQ )   +++   ( RR  --  -RR )   +++   ( -PP  --  -QQ )
; I      =   I.h    +++    I.o
);

		endgroup ; %% i403 - i407

Dd( i408 )( X_SYM  )( Y_any  )( % s349; k347
; I  .a  =   ip\374
;
	isn = isn\374;
	iwe = 2 iwe\374  +  !! 1/2 bridge_width_default_wide;
;
; I  .w  =   I.a  xsh( iw\374  -+  iw )
; I  .e  =   I.a  xsh( ie\374  -+  ie )
; I  .o  =   |. bridge_width_default_wide  |>90
; I      =   I.w    +++    I.o    +++    I.e
);

Dd( i409 )( X_SYM  )( Y_NORM )( % s348; k346
; I  .a  =   ip\408
;
	NUMER  sh, nh;    sh + nh/2 = idy;
	nh  =  idy\408;
;
; I  .n  =   I.a  ysh( +nh/2  -+  in )
; I  .s  =   |. sh  ysh( -sh/2  -+  is )
; I      =   I.s    +++    I.n
;
	iwe = iwe\408;
;
);

Dd( i410 )( X_SYM  )( Y_NORM )( % s; k079
; I  .a  =   oval_golden. 1/2 idy
; I  .s  =   I.a  ysh( -1/4 idy  -+  is )
; I  .n  =   I.a  ysh( +1/4 idy  -+  in )
; I      =   I.s    +++    I.n
;
	iwe = !! ( I.a.?.x_e );
;
);

Dd( i411 )( X_SYM  )( Y_ROOF )( % s; k
;
	iwe = !! $ 4;
;
; I  .h  =   ip\410
; I\1    =   I.h  Transformed ysc_shrink
; I      =   I\1  roofed( r_sloping, idx ) 
);

Dd( i412 )( X_any  )( Y_NORM )( % s086; k077
; I  .h  =   ip\410
; I  .b  =   ip\186.we
; I  .c  =   ip\186.e
;
	Numer  sloping  = 60   ;    % ladder sloping
	Numer  breadth  = $ 2.5;    % ladder breadth
	Numer  vertical = breadth/sind sloping; % sloped ladder vertical breadth
;
	Numer  lll  =  idy\186 - idx\186 * cotd sloping;    % ladder length left
	Pairp  PP   =  I.h  last_where_y  -( vertical / 2 );
;
; I  .d  =   |. lll  shi( ( 0, lll/2 )  -+  ( iw\186, in\186 ) )
; I  .x  =   I.b  Yscaled 1.5  ysh( ~.?.y_s  -+  ( in\186 - lll ) + $ 0.6 )
; I  .y  =   I.d    +++    I.x    +++    I.c
; I  .z  =   I.y  shi( ( ie\186, is\186 )  -+  OQ )
; I  .e  =   I.z  scy 2 breadth  |>sloping  shi( OQ  -+  PP )
; I      =   I.h    +++    I.e
;
	iwe = ( iw\410, I.e.?.x_e );
;
);

Dd( i413 )( X_any  )( Y_NORM )( % s088; k080
;
	iwe = iwe\410  +  ( -bridge_width_default_wide, 0 );
;
; I  .h  =   ip\410
; I  .b  =   |. idy
;
	Pairp  AA  =  ( iw\410, 1/2 in );
	Pairp  BB  =  ( iw    , 1/2 in );
;
; I  .w  =   I.b  xsh( 0  -+  iw )
; I  .o  =   ++++ ( AA -- BB )
; I      =   I.h    +++    I.w    +++    I.o
);

Dd( i414 )( X_SYM  )( Y_NORM )( % s; k
; I      =   ip\410    +++    |. idy
;
	iwe = iwe\410;
;
);

Dd( i415 )( X_SYM  )( Y_NORM )( % s354; k353.196
;
	Numer  hh  =  idy/3;
;
; I  .a  =   oval_norm. hh;
; I  .o  =   I.a
; I  .s  =   I.a  ysh( -hh/2  -+  is )
; I  .n  =   I.a  ysh( +hh/2  -+  in )
; I      =   I.s    +++    I.o    +++    I.n
;
	iwe = !! ( I.a.?.x_e );
;
);

Dd( i416 )( X_SYM  )( Y_NORM )( % s; k354
;
	iwe = !! ( ie\415  +  split_distance_default  +  0 );
;
; I      =   ip\415    +++    ip\087  splitted
);

Dd( i417 )( X_SYM  )( Y_NORM )( % s355.1; k353.296
; I      =   ip\415    +++    |. idy
;
	iwe = iwe\415;
;
);

% i418 moved after i015

Dd( i419 )( X_SYM  )( Y_NORM )( % s; k328
; I  .h  =   ip\342
;
	iwe = iwe\342;
;
	Numer  r = floor( 1/10 rrx ip\328 );
;
; I  .c  =   i_mini  shi( ( 0, mini/2 ) -+ ( -3r, in ) )
; I  .d  =   i_mini  shi( ( 0, mini/2 ) -+ ( - r, in ) )
; I  .nnw=   I.c      +++    I.d
; I  .nne=   I.nnw ||
; I  .n  =   I.nnw    +++    I.nne
; I      =   I.h      +++    I.n
);

	endgroup ; %% i000 - i419

endfor   ;         %%%%%%%%
=======================================================================
% ============== |  production: reclaim storage of context functions  |
=======================================================================
for  sigl = sign_lists_implemented_stage_d:
	for  ix = 0  upto context[ sigl ] .hix:
		Pair ga  =  context[ sigl ][ ix ][ 0 ];
		Pair go  =  context[ sigl ][ ix ][ 1 ];

		scantokens( "numeric "  &  context_function_name( ga, go ) );
	endfor
endfor
=======================================================================

% #####################################################################
endgroup ;     % ########### |  END PART 2.1: Indus glyph production  |
endgroup ;     % ########### |  END PART 2  : Indus glyph             |

if  resource_report >= 2 :
	showstats;
	if  resource_report >= 3 :
		show "fig_mem .path_hix= " & decimal fig_mem .path_hix;
		show "fig_mem .plus_lox= " & decimal fig_mem .plus_lox;
	fi
fi

fi % Indus glyph

=======================================================================
% =========|  parameter evaluation (for ASCII and preliminary signs)  |
=======================================================================
if  known ascii_signs_wanted  <>  known preliminary_signs_wanted :
	ascii_signs_wanted  =  not preliminary_signs_wanted;
fi
=========
if unknown       ascii_signs_wanted :
	ascii_signs_wanted        =  not indus_signs_needed;
fi

Boolean  ascii_signs_needed =
		ascii_signs_wanted
	cand (
		.  ( ascii_letters_lowercase_wanted > 0 )
		or ( ascii_letters_uppercase_wanted > 0 )
		or ( ascii_digits_wanted            > 0 )
		or ( ascii_special_signs_wanted     > 0 )
	);
=================
if unknown preliminary_signs_wanted :
	preliminary_signs_wanted  =  not indus_signs_needed;
fi

Boolean  preliminary_signs_needed =
		preliminary_signs_wanted
	cand (
		not empty( list_of_preliminary_glyph_strings )
	);
=======================================================================

if  ascii_signs_needed
or  preliminary_signs_needed:

STRING  wanted_ascii_chars;

begingroup     % ########### |  BEG PART 3  : ASCII glyph             |
% #####################################################################

if  progress_report >= 1 :
	show "ASCII glyph generation starts ...";
fi

=======================================================================
% ========================================================= |  ASCII  |
=======================================================================
% The following part describes the ASCII glyphs.
% We prefer simple generation over beautiful glyph here,
% because these signs are included for vague reasons hitherto.
=======================================================================

=======================================================================
% Evaluate parameters.
=======================================================================
.                                % south/north portion of height:
NUMER  s_portion, n_portion;     s_portion + n_portion = 1;
.      s_portion = asc_s_portion;

Pair   iwe_base = !! 0.5 asc_dx;

Pair   OO_real  =
	( 0, - 0.5 $$ + asc_baseline_y + s_portion * asc_dy_normal );
=========
Numer  super    =  asc_super  ;
Numer  super_O  =  asc_super_O;
=======================================================================
% Define base levels and points.
%
% (The glyphs are produced in a position first,
%  where origin = OQ = OO = (0,0) parts south from north portion.
%  They will be positioned right later on.)
=======================================================================
Numer  w_level  =  iw_base;
Numer  e_level  =  ie_base;

Numer  o_level  =  0;
Numer  s_level  =  - s_portion * asc_dy_normal;
Numer  n_level  =  s_level + asc_dy_normal;

Numer  z_level  =  s_level  -  asc_dz;
Numer  solevel  =  s_portion[ s_level, o_level ];
Numer  onlevel  =  s_portion[ o_level, n_level ];
=========
Numer irreality =  ( - 0.5 $$ + asc_baseline_y )  -+  s_level;
=========
NUMER  sh, nh;     sh + nh = asc_dy_normal;
nh = n_level;
=========
PAIR   WN  , ON  , EN
.    , WNNW, ONNO, ENNE
.    , WNW , ONO , ENE
.    , WO  , OO  , EO
.    , WSW , OSO , ESE
.    , WSSW, OSSO, ESSE
.    , WS  , OS  , ES
.    , WZ  , OZ  , EZ  ;

WZ   =  ( w_level, z_level );
OZ   =  (  0     , z_level );
EZ   =  ( e_level, z_level );

WS   =  ( w_level, s_level );
OS   =  (  0     , s_level );
ES   =  ( e_level, s_level );

WO   =  ( w_level, o_level );
OO   =  (  0     , o_level );
EO   =  ( e_level, o_level );

WN   =  ( w_level, n_level );
ON   =  (  0     , n_level );
EN   =  ( e_level, n_level );

WSW  =  ( w_level, solevel );
OSO  =  (  0     , solevel );
ESE  =  ( e_level, solevel );

WNW  =  ( w_level, onlevel );
ONO  =  (  0     , onlevel );
ENE  =  ( e_level, onlevel );

WSSW =  ( w_level, 0.6 [ o_level, s_level ] );
OSSO =  (  0     , 0.6 [ o_level, s_level ] );
ESSE =  ( e_level, 0.6 [ o_level, s_level ] );

WNNW =  ( w_level, 0.6 [ o_level, n_level ] );
ONNO =  (  0     , 0.6 [ o_level, n_level ] );
ENNE =  ( e_level, 0.6 [ o_level, n_level ] );
=======================================================================
% Building stones 1: strokes
=======================================================================
Numer  xshort = 0.8;
Pairp  OOW  = xshort * WO;
Pairp  OOE  = xshort * EO;

Numer  xdis = 0.5 stroke_distance_x;
Numer  ydis = 0.5 stroke_distance_y;
=================
Path  stroke_y  = OS  --  ON;
Path  stroke_z  = OZ  --  OS;
Path  stroke_s  = OS  --  OO;
Path  stroke_n  = OO  --  ON ;
Path  stroke_zs = OZ  --  OO;
=========
Numer eye_factor = 1.1;           % fight optical illusion
Path  stroke_x  = WO  --  EO;
Path  strok_x   = stroke_x  scaled xshort;
Path  strok_y   = strok_x   rotated -90  scaled eye_factor;
=========
Path  diagon_u  =  WS  --  EN;
Path  diagon_d  =  WN  --  ES;
Path  diag_s_u  =  WS  --  EO;
Path  diag_s_d  =  WO  --  ES;
Path  diag_n_u  =  WO  --  EN;
Path  diag_four =  WO  --  ON;
=================
Pair  less_ne   =  ( xshort * e_level, 2 ydis );
Path  less      =  less_ne  --  -0.5[ less_ne, less_ne |: ]  --  less_ne |:;
=========
Path  vau_s     =  WO  --  OS   --  EO;
Path  vau_n     =  WN  --  OO   --  EN;
Path  Vau       =  WN  --  OS   --  EN;
Path  vau_kaa   =  EO  --  WSW  --  ES;
=========
Numer comma_s_level  =  0.7 [ s_level, z_level ];
Numer comma_height   =  comma_s_level  -+  s_level;
Numer comma_width    =  0.5 comma_height;

Numer accent_height  =  comma_height;
Numer accent_width   =  comma_width ;

Path  comma     =  OS  --  ( OS + ( - comma_width, - comma_height ) );
Path  apo_y     =  ON  --  ( ON + (             0, -accent_height ) );
Path  apo_d     =  ON  --  ( ON + ( +accent_width, -accent_height ) );
=======================================================================
% Building stones 2: superellipse and subpaths, circles
=======================================================================
Path  elli_Ooo  =  superellipse( EO , ON , WO , OS , super_O );
Path  elli_zero =  superellipse( EO , ON , WO , OS , super );
Path  elli_s    =  superellipse( ESE, OO , WSW, OS , super );
Path  elli_n    =  superellipse( ENE, ON , WNW, OO , super );
Path  elli_jot  =  superellipse( ES , WS + ( WZ -+ WS ),
.                                     WS + ( ES -+ WS ), WZ, super );
Path  elli_Jot  =  superellipse( EO , WO + ( WS -+ WO ),
.                                     WO + ( EO -+ WO ), WS, super );

Path  Gee_w     =  subpath( 1, 8 ) of elli_zero;
Path  eee       =  subpath( 0, 7 ) of elli_s   ;
Path  enn_n     =  subpath( 0, 4 ) of elli_s   ;
Path  at_elli   =  subpath( 0, 6 ) of elli_s   ;
Path  jot_s     =  subpath( 6, 8 ) of elli_jot ;
Path  Jot_s     =  subpath( 6, 8 ) of elli_Jot ;
=================
Path  six       =  EN  ..  {down} WSW   &   subpath( 4, 12 ) of elli_s;
Path  nine      =  WS  ..  { up } ENE   &   subpath( 0,  8 ) of elli_n;
=========
Path  enn       =  WS  --  WSW   &   enn_n `   &   ESE  --  ES;
=================
Numer circ_rad  =  $ 0.7;                            % for percent sign
Path  circ      =  fullcircle  scaled 2 circ_rad;
=======================================================================
% Building stones 3: serpents, baskets, sloping paths
=======================================================================
Vardef  serpent( expr P, Q, alf ) =
	Pairp  M = 0.5[ P, Q ];
	P { (P-+Q) |> alf } .. M { (P-+Q) |< alf } .. { (P-+Q) |> alf } Q
enddef;
=========
Path  serpent_x = serpent( OOW, OOE, -60 );
Path  serpent_n = serpent(  EN,  OO, +40 );
Path  serpent_s = serpent(  ES,  OO, -40 );
=================
Path  bask_s    =  WO  ..  ESE {down}  ..  WS;
Path  bask_n    =  WO  ..  ENE { up }  ..  WN;

Path  basket_s  =  bask_s  ysh( ~.?.y_n -+ 0 )  ysc sh;
Path  basket_n  =  bask_n  ysh( ~.?.y_s -+ 0 )  ysc nh;

Numer t_s       =  max( 0, directiontime right of  basket_s );
Numer t_n       =  max( 0, directiontime right of  basket_n );

Path  busket_s  =  subpath( t_s, infinity ) of basket_s;
Path  busket_n  =  subpath( t_n, infinity ) of basket_n;

Path  three     =  busket_s `  --          busket_n;
Path  B_e       =  busket_s `  --  WO  --  busket_n;
Path  R_ne      =                  WO  --  busket_n;

Path  five_s    =                  WO  --  basket_s;
=================
Path  eight     =    ESSE {down} .. OS {left} .. WSSW { up } .. OO
.                 .. ENNE { up } .. ON {left} .. WNNW {down} .. OO .. cycle;
Path  ampersand =    ESE  {down} .. OS {left} .. WSSW { up }
.                 .. ENNE { up } .. ON {left} .. WNW  {down} .. {Dir 145} ES;

Path  two_slope =  ( ENE  { up } .. ON {left} .. WNW  {down} .. {Dir 125} ES ) ||;
=======================================================================
% Building stones 4: specials
=======================================================================
Path  eff       =  EN  ..  ONO  ---  OO   --  OS;
Path  tee       =  ON  --  OO   ---  OSO  ..  ES;
=========
Path  ell       =  WN {right} ..  ONNO ---  OSSO .. {right} ES;
=================
Path  lpar      =  ES  ..  OO  ..  EN;
Path  rpar      =  WS  ..  OO  ..  WN;
=========
Path  Cee       =  ES  ..  WO  ..  EN;
=================
Numer doll_fac  =  xshort;
Path  Ess       =  subpath( 4, 10 ) of eight;
Path  Ess_doll  =  Ess  yscaled doll_fac;
Path  ess       =  Ess  ysh( ON -+ OQ )  yscaled( sh/asc_dy_normal );
=======================================================================
% ================================ |  ASCII: lists, variables, tools  |
=======================================================================
String  ascii_letters_lowercase  =  "abcdefghijklmnopqrstuvwxyz";
String  ascii_letters_uppercase  =  "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
String  ascii_digits             =  "0123456789";
String  ascii_special_signs      =  " !"
.                                 & ditto
.                                 & "#$%&'()*+,-./:;<=>?@[\]^_`{|}~";
=========
wanted_ascii_chars =  ""
	if ascii_letters_lowercase_wanted = 1: & ascii_letters_lowercase fi
	if ascii_letters_uppercase_wanted = 1: & ascii_letters_uppercase fi
	if ascii_digits_wanted            = 1: & ascii_digits            fi
	if ascii_special_signs_wanted     = 1: & ascii_special_signs     fi;

String needed_ascii_chars = wanted_ascii_chars
	if preliminary_signs_needed:
		for   cc = list_of_preliminary_glyph_strings :  & cc   endfor
	fi;
=================
save  asc;     path    asc[][];
.              numer   asc[] .hix;
=================
Def  AS( expr c ) text t  =
	if   c  is_in  needed_ascii_chars:
		asc[ ASCII c ] .hix := -1;         % necessary for blank sign
		for x = t:
			new asc[ ASCII c ] = x;
		endfor
	fi
enddef;
=========
Def ! primary c = AS( c )  enddef;
=======================================================================
% ====================================== |  ASCII: sign descriptions  |
=======================================================================
;! "0"
	, elli_zero
;! "1"
	, diag_n_u
	, stroke_y     xsh e_level
;! "2"
	, two_slope
	, stroke_x     ysh s_level
;! "3"
	, three
;! "4"
	, stroke_x
	, stroke_y
	, diag_four
;! "5"
	, stroke_x     ysh n_level
	, stroke_n     xsh w_level
	, five_s
;! "6"
	, six
;! "7"
	, stroke_x     ysh n_level
	, diagon_u
	, stroke_x                             Scaled 0.5
;! "8"
	, eight
;! "9"
	, nine
;
=================
;! "a"
	, elli_s
	, stroke_s     xsh e_level
;! "b"
	, elli_s
	, stroke_y     xsh w_level
;! "c"
	, basket_s ||
;! "d"
	, elli_s
	, stroke_y     xsh e_level
;! "e"
	, eee
	, stroke_x     ysh solevel
;! "f"
	, eff
	, stroke_x
;! "g"
	, elli_s
	, stroke_s     xsh e_level
	, jot_s
;! "h"
	, stroke_y     xsh w_level
	, enn
;! "i"
	, stroke_s
	, stroke_x     ysh s_level
	, stroke_x
	, ON
;! "j"
	, jot_s
	, stroke_x
	, stroke_s     xsh e_level
	, ON
;! "k"
	, stroke_y     xsh w_level
	, vau_kaa
;! "l"
	, ell
;! "m"
	, enn          xsh w_level             Xscaled 0.5
	, enn          xsh e_level             Xscaled 0.5
	, stroke_s     xsh w_level
;! "n"
	, enn
	, stroke_s     xsh w_level
;! "o"
	, elli_s
;! "p"
	, elli_s
	, stroke_zs    xsh w_level
;! "q"
	, elli_s
	, stroke_zs    xsh e_level
;! "r"
	, enn_n
	, stroke_s     xsh w_level
;! "s"
	, ess
;! "t"
	, tee
	, stroke_x
;! "u"
	, enn      |:  ysh s_level
;! "v"
	, vau_s
;! "w"
	, vau_s        xsh w_level             Xscaled 0.5
	, vau_s        xsh e_level             Xscaled 0.5
;! "x"
	, diag_s_d
	, diag_s_u
;! "y"
	, vau_s
	, stroke_z
;! "z"
	, diag_s_u
	, stroke_x     ysh s_level
	, stroke_x
;
=================
;! "A"
	, Vau      |:  ysh( s_level + n_level )
	, stroke_x                             Scaled n_portion
;! "B"
	, stroke_y     xsh w_level
	, B_e
;! "C"
	, Cee
;! "D"
	, stroke_y     xsh w_level
	, Cee      ||
;! "E"
	, stroke_y     xsh w_level
	, stroke_x     ysh s_level
	, stroke_x
	, stroke_x     ysh n_level
;! "F"
	, stroke_y     xsh w_level
	, stroke_x
	, stroke_x     ysh n_level
;! "G"
	, Gee_w
	, stroke_x     xsh e_level             Scaled 0.5
;! "H"
	, stroke_y     xsh w_level
	, stroke_y     xsh e_level
	, stroke_x
;! "I"
	, stroke_y
	, stroke_x     ysh s_level
	, stroke_x     ysh n_level
;! "J"
	, stroke_x     ysh n_level
	, stroke_n     xsh e_level
	, Jot_s
;! "K"
	, stroke_y     xsh w_level
	, diag_s_d
	, diag_n_u
;! "L"
	, stroke_y     xsh w_level
	, stroke_x     ysh s_level
;! "M"
	, stroke_y     xsh w_level
	, stroke_y     xsh e_level
	, vau_n
;! "N"
	, stroke_y     xsh w_level
	, stroke_y     xsh e_level
	, diagon_d
;! "O"
	, elli_Ooo
;! "P"
	, stroke_y     xsh w_level
	, basket_n
;! "Q"
	, elli_Ooo
	, diag_s_d     shi( e_level, s_level )   Scaled 0.5
;! "R"
	, stroke_y     xsh w_level
	, R_ne
	, diag_s_d
;! "S"
	, Ess
;! "T"
	, stroke_y
	, stroke_x     ysh n_level
;! "U"
	, stroke_n     xsh w_level
	, stroke_n     xsh e_level
	, enn      |:  ysh s_level
;! "V"
	, Vau
;! "W"
	, stroke_y     xsh w_level
	, stroke_y     xsh e_level
	, vau_s    |:  ysh s_level
;! "X"
	, diagon_d
	, diagon_u
;! "Y"
	, stroke_s
	, vau_n
;! "Z"
	, stroke_x     ysh s_level
	, stroke_x     ysh n_level
	, diagon_u
;
=================
;! " "
	,                          % "This sign intentionally left blank."
;! "!"
	, stroke_y     ysh -n_level    Scaled doll_fac   ysh +n_level
	, OS
;! ditto
	, apo_y        xsh -xdis
	, apo_y        xsh +xdis
;! "#"
	, strok_x      ysh +ydis
	, strok_x      ysh -ydis
	, strok_y      xsh +xdis
	, strok_y      xsh -xdis
;! "$"
	, Ess_doll
	, stroke_y
;! "%"
	, diagon_u
	, circ         shi( + !! circ_rad  -+  WN )
	, circ         shi( - !! circ_rad  -+  ES )
;! "&"
	, ampersand
;! "'"
	, apo_y
;! "("
	, lpar
;! ")"
	, rpar
;! "*"
	, strok_y
	, strok_x      |> 34                      % fight optical illusion
	, strok_x      |< 34
;! "+"
	, strok_x
	, strok_y
;! ","
	, comma
;! "-"
	, strok_x
;! "."
	, OS
;! "/"
	, diagon_u
;! ":"
	, OO           ysh +ydis
	, OO           ysh -ydis
;! ";"
	, OS           ysh 2 ydis
	, comma
;! "<"
	, less
;! "="
	, strok_x      ysh +ydis
	, strok_x      ysh -ydis
;! ">"
	, less     ||
;! "?"
	, Ess_doll ||  ysh( ~.?.y_n  -+  n_level )
	, OS
;! "@"
	, elli_s       ysh( 0.55/0.45 s_level/2 )  Scaled 0.45 % 0.55+0.45=1
	, stroke_s `   xsh e_level
	.              ysh( 0.55/0.45 s_level/2 )  Scaled 0.45  ..  {up} ESE
	, at_elli
;! "["
	, stroke_y
	, stroke_x     xsh e_level          Scaled 0.5     ysh n_level
	, stroke_x     xsh e_level          Scaled 0.5     ysh s_level
;! "\"
	, diagon_d
;! "]"
	, stroke_y
	, stroke_x     xsh w_level          Scaled 0.5     ysh n_level
	, stroke_x     xsh w_level          Scaled 0.5     ysh s_level
;! "^"
	, apo_d    ||
	, apo_d
;! "_"
	, stroke_x     ysh s_level
;! "`"
	, apo_d
;! "{"
	, serpent_n
	, serpent_s
;! "|"
	, stroke_y
;! "}"
	, serpent_n ||
	, serpent_s ||
;! "~"
	, serpent_x
;
=======================================================================
% Build the figures.
=======================================================================
% Strings and arrays to describe the glyph bounds:
=================
%                    " !" & ditto & "#$%&'()*+,-./:;<=>?@[\]^_`{|}~"
	String s_bonds = "+s" &  "m"  & "rsssmssrrcosslc>l>sssssmsmsssq";
	String n_bonds = "-n" &  "n"  & "RnnnnnnRRsosnL;<L<nonnnnsnnnn~";
	String w_bonds = "?0" &  "u"  & "vwww00w.v,v0w0,vvvww0ww^w000wv";
	String e_bonds = "!0" &  "U"  & "Veee0e0*V0V0e00VVVeeee0`e`e00V";

	save  bond;      numer  bond[];
	NUMER star_east, serpent_north; % values to compute

	bond[ ASCII "+" ] =  0+irreality;
	bond[ ASCII "-" ] = -1+irreality;
	bond[ ASCII "?" ] =  0;
	bond[ ASCII "!" ] = -1;

	bond[ ASCII "0" ] = 0;
	bond[ ASCII "w" ] = w_level;
	bond[ ASCII "e" ] = e_level;
	bond[ ASCII "s" ] = s_level;
	bond[ ASCII "n" ] = n_level;
	bond[ ASCII "o" ] = o_level;
	bond[ ASCII "c" ] = comma_s_level;

	bond[ ASCII "u" ] = -xdis;
	bond[ ASCII "U" ] = +xdis;
	bond[ ASCII "v" ] = xshort * w_level;
	bond[ ASCII "V" ] = xshort * e_level;
	bond[ ASCII "r" ] = eye_factor * xshort * w_level;
	bond[ ASCII "R" ] = eye_factor * xshort * e_level;

	bond[ ASCII "l" ] = -ydis;
	bond[ ASCII "L" ] = +ydis;
	bond[ ASCII ">" ] = -2ydis;
	bond[ ASCII "<" ] = +2ydis;
	bond[ ASCII ";" ] = s_level + 2 ydis;
	bond[ ASCII "m" ] = n_level - accent_height;
	bond[ ASCII "," ] = -comma_width;
	bond[ ASCII "`" ] = +accent_width;
	bond[ ASCII "^" ] = -accent_width;

	bond[ ASCII "*" ] = +star_east;
	bond[ ASCII "." ] = -star_east;
	bond[ ASCII "~" ] = o_level+serpent_north;
	bond[ ASCII "q" ] = o_level-serpent_north;
=================
NUMER  ccx;
PAIR   sign_id;
STRING c;
NUMER  ix;

for cx = 0  upto  127:
	if  known asc[ cx ] .hix :
		c       := char cx;
		ccx     := cx + asc_temp_base;
		sign_id := ( ASL, ccx );

		if    asc[ cx ] .hix >= 0 :
			glyph( sign_id )  =
			.   (
			.       ( ++++ asc[ cx ][ 0 ] )
			.       for kk = 1 upto asc[ cx ] .hix :
			.           +++ asc[ cx ][ kk ]
			.       endfor
			.   ) ysh( OO -+ OO_real );
		else:
			glyph( sign_id )  =  zero;
		fi

		if      c  is_in  ascii_digits :
			glyph_bounds( sign_id )[ y_axis ] = ( s_level, n_level );
			glyph_bounds( sign_id )[ x_axis ] = iwe_base;
		elseif  c  is_in  ascii_letters_uppercase :
			glyph_bounds( sign_id )[ y_axis ] = ( s_level, n_level );
			glyph_bounds( sign_id )[ x_axis ] = iwe_base;
		elseif  c  is_in  ( "bdfhiklt" ) :
			glyph_bounds( sign_id )[ y_axis ] = ( s_level, n_level );
			glyph_bounds( sign_id )[ x_axis ] = iwe_base;
		elseif  c  is_in  ( "acemnorsuvwxz" ) :
			glyph_bounds( sign_id )[ y_axis ] = ( s_level, o_level );
			glyph_bounds( sign_id )[ x_axis ] = iwe_base;
		elseif  c  is_in  ( "gpqy" ) :
			glyph_bounds( sign_id )[ y_axis ] = ( z_level, o_level );
			glyph_bounds( sign_id )[ x_axis ] = iwe_base;
		elseif  c  is_in  ( "j" ) :
			glyph_bounds( sign_id )[ y_axis ] = ( z_level, n_level );
			glyph_bounds( sign_id )[ x_axis ] = iwe_base;
		elseif  c  is_in   ascii_special_signs :
			if  c = "*" :  star_east     = glyph( sign_id ).?.x_e;  fi
			if  c = "~" :  serpent_north = glyph( sign_id ).?.y_n
			.                                         + irreality;  fi

			ix := find( ascii_special_signs, c );
			if ix >= 0 :
				glyph_bounds( sign_id )[ x_axis ] =
				.   ( bond[ ASCII substring(ix, ix+1) of w_bonds ]
				.   , bond[ ASCII substring(ix, ix+1) of e_bonds ] );
				glyph_bounds( sign_id )[ y_axis ] =
				.   ( bond[ ASCII substring(ix, ix+1) of s_bonds ]
				.   , bond[ ASCII substring(ix, ix+1) of n_bonds ] );
			fi
		else:
			glyph_bounds( sign_id )[ y_axis ] = glyph( sign_id ).?.sn;
			glyph_bounds( sign_id )[ x_axis ] = glyph( sign_id ).?.we;
		fi

		glyph_bounds( sign_id )[ y_axis ] :=
		.   glyph_bounds( sign_id )[ y_axis ] - ( irreality, irreality );
	fi
endfor

=======================================================================

% #####################################################################
endgroup ;     % ########### |  END PART 3  : ASCII glyph             |

if  resource_report >= 2 :
	showstats;
	if  resource_report >= 3 :
		show "fig_mem .path_hix= " & decimal fig_mem .path_hix;
		show "fig_mem .plus_lox= " & decimal fig_mem .plus_lox;
	fi
fi

fi % ASCII glyph

if  preliminary_signs_needed:
begingroup     % ########### |  BEG PART 4  : preliminary glyphs      |
% #####################################################################

if  progress_report >= 1 :
	show "Additional glyph generation starts ...";
fi

=======================================================================
% Generate glyphs from a list of strings.
=======================================================================

Numer  base_dist  =  asc_dx + preliminary_glyph_dist;

NUMER  cx , dx ;
NUMER  ccx, ddx;
PAIR   sign_id, sid;

cx := -1;
for cc = list_of_preliminary_glyph_strings:
	cx  := cx + 1;
	ccx := cx +  preliminary_temp_base;
	sign_id := ( ASL, ccx );

	glyph( sign_id ) =
		if length cc = 0:
			zero
		else: (
			for  j = 0  upto  length cc - 1:

				hide(
					dx  := ASCII( substring( j, j+1 ) of cc );
					ddx := dx + asc_temp_base;
					sid := ( ASL, ddx );
				)

				if j > 0: +++ fi   glyph( sid ) xsh( j * base_dist )

			endfor
			) xsh -1/2( ( length cc - 1 ) * base_dist )
		fi;

	glyph_bounds( sign_id )[ y_axis ] = sn_normal;
	glyph_bounds( sign_id )[ x_axis ] =
		.                     !! preliminary_bound_dist
		if  length cc > 0:  + !!( length cc * base_dist / 2 )  fi;

	Numer iw = first  glyph_bounds( sign_id )[ x_axis ];
	Numer ie = second glyph_bounds( sign_id )[ x_axis ];
	Numer is = first  glyph_bounds( sign_id )[ y_axis ];
	Numer in = second glyph_bounds( sign_id )[ y_axis ];

	glyph( sign_id ) :=
		glyph( sign_id ) ysh( asc_dz )
		+++  ( iWS -- iWN -- iEN -- iES -- cycle );
endfor

=======================================================================

% #####################################################################
endgroup ;     % ########### |  END PART 4  : preliminary glyphs      |

if  resource_report >= 2 :
	showstats;
	if  resource_report >= 3 :
		show "fig_mem .path_hix= " & decimal fig_mem .path_hix;
		show "fig_mem .plus_lox= " & decimal fig_mem .plus_lox;
	fi
fi

fi % preliminary glyphs

begingroup     % ########### |  BEG PART 5  : control bounds          |
% #####################################################################

if  progress_report >= 1 :
	show "Bound control and checking starts ...";
fi

=======================================================================
% Restrict figures to a maximal width.
=======================================================================
PAIR    k;
FIGURE  f;
NUMER   disp;
for  j  =  signs_in_sign_list( ASL ) :
	k := ( ASL, j );
	f := glyph( k );
	if  known f :
		if  q_dx( k )  >  dx_high :
			f := glyph( k ) := reduce_width( f );
			q_we( k ) := !! ( dx_high/2 );
			q_sn( k ) :=  f.?.sn;
		else :
			if          q_w( k )  <   -dx_high/2 :
				disp := q_w( k )  -+  -dx_high/2;
			elseif      q_e( k )  >   +dx_high/2 :
				disp := q_e( k )  -+  +dx_high/2;
			else:
				disp := 0;
			fi
			glyph( k ) := f  xsh disp;
			q_we( k )  := q_we( k )  +  ( disp, disp );
		fi
	fi
endfor
=======================================================================
% Check stored bounds, if wanted.
=======================================================================
Numer  bound_eps = 1/32; % Show deviations greater than bound_eps;
.                        % set it on 0 to get any deviation,
.                        % set it on a negative value, to get all bounds.

save  side_name;      string   side_name [][];
	side_name [ x_axis ][ 0 ] = "west" ;
	side_name [ x_axis ][ 1 ] = "east" ;
	side_name [ y_axis ][ 0 ] = "south";
	side_name [ y_axis ][ 1 ] = "north";

save  check_flag;     boolean  check_flag[][];
	check_flag[ x_axis ][ 0 ] = ( check_bounds_at_west  > 0 );
	check_flag[ x_axis ][ 1 ] = ( check_bounds_at_east  > 0 );
	check_flag[ y_axis ][ 0 ] = ( check_bounds_at_south > 0 );
	check_flag[ y_axis ][ 1 ] = ( check_bounds_at_north > 0 );
=========
NUMER   bo_s, bo_r;   % stored vers. real bound
FIGURE  sig;
for  k  =  signs_in_sign_list( ASL ) :
	sig := glyph( ASL, k );
	if  known sig:
		for  axis = x_axis, y_axis :
		for  xy = 0, 1 :
			bo_s := part\xy( glyph_bounds( ASL, k )[ axis ] );

			if unknown  bo_s:
				part\xy( glyph_bounds( ASL, k )[ axis ] )
				= sig.?.compass( axis )( xy );

				show "Warning: unset bound found for "  & decimal k
					&  " at "  &  side_name[ axis ][ xy ]
					&  ". (No harm - it's set now.)";
			fi

			if check_flag[ axis ][ xy ]:
				bo_r := sig.?.compass( axis )( xy );

				if abs( bo_s - bo_r ) > bound_eps :
					show  "bound warning (sign "  &  sign_name( ASL, k )
						&  " at "                 &  side_name[ axis ][ xy ]
						&  "): bound stored: "    &  decimal bo_s
						&  ", real bound: "       &  decimal bo_r;
				fi
			fi
		endfor
		endfor
	fi
endfor
=======================================================================

% #####################################################################
endgroup ;     % ########### |  END PART 5  : glyph bounds            |

if  resource_report >= 2 :
	showstats;
fi

user_intervention( stop_when_glyphs_ready > 0 ) "glyphs are ready - goon?:";

if  progress_report >= 1 :
	show "Sign code generation starts ...";
fi

% %%%%%%%%     % ########### |  BEG PART 6  : charcode                |
% #####################################################################

=======================================================================
%  Metafont only allows 256 different sign widths.
%  Worse: characters with the same charcode need to share all dimensions.
%  What can we do, without changing MF (what would be the real solution)?
%
%  1st way: collect the signs with have the same width `naturally'
%           - as i001 and i003 -
%           into a group with common charcode.
%
%      If we get no more than 256 groups, we can solve the problem.
%      But it fails:
%      I got 304 groups, interpreting `natural' in a strong way,
%      and 283 with a more weak interpretation.
%
%  2nd way: collect signs, which share their dimensions
%           - may be naturally, may be by chance -,
%           into a group with common charcode.
%      This works. I got about 100 groups.
%      (Some groups with more than 16 members need to be splitted,
%      so we got about 111 different charcode values.)
%
%  But there are hard problems with this way too:
%  1) The codes are spreading over nearly the full range
%     from x'e080' to x'efff'. We get a tfm-file, which extends to 490k!
%
%  2) We don't get a fixed code,
%     but one, changing with changes of the glyphs.
%
%  3) And finally, I were unable to find a full range of utilities
%     working with fonts, which use charext.
%
%  So the whole attempt needs to be abandoned.
%  Instead of producing one font only, we must produce two (or more),
%  each containing no more than 256 signs.
%  (There is some hope, to reunite them into a virtual font.
%   (But even that failed in a first attempt.))
%
%  This solution - missing any elegance - has merits too:
%  1) The signs can get a more or less natural code.
%  2) The danger of (memory) "capacity exceeded" will be reduced.
=======================================================================
Def   set_charcode_and_charext  primary sign_id =
	xxxpr    :=  logical_charnumber_to_real_charnumber_pair  sign_id;

	charcode :=  first  xxxpr;
	charext  :=  second xxxpr;
enddef;
=======================================================================
Vardef  logical_charnumber_to_real_charnumber_pair  primary sign_id =
	Numer  z  =  second  sign_id;
	PAIR  uv;

	if  is_ascii sign_id:
		z  :=  asc_temp_base  -+  z;
		uv = ( z mod 256, floor( z / 256 ) )  +  asc_code_base;
	elseif is_preliminary sign_id:
		z  :=  preliminary_temp_base  -+  z;
		uv = ( z mod 256, floor( z / 256 ) )  +  preliminary_code_base;
	else:
		uv = ( z mod 256, floor( z / 256 ) )  +  ind_code_base;
	fi

	( first uv, 0 )     % avoid problems with utilities, hating charext
enddef;
=========
Vardef  is_ascii primary sign_id =
	.   ( asc_temp_base <= second sign_id )
	and (                  second sign_id <= asc_temp_base + 127 )
enddef;
=========
Vardef  is_preliminary primary sign_id =
	.   ( preliminary_temp_base <= second sign_id )
	and (        second sign_id <= preliminary_temp_base + 127 )
enddef;
=======================================================================

% #####################################################################
% %%%%%%%%     % ########### |  END PART 6  : charcode                |

if  progress_report >= 1 :
	show "Sign export starts ...";
fi

begingroup     % ########### |  BEG PART 7  : draw/display/export     |
% #####################################################################

=======================================================================
% Some utilities first:
%
% openit, etc.        : prepare online display
% set_sharp_dimensions: compute sharp dimensions, needed for beginchar
% evaluate            : compute picture from figure
%
% At last the font will be generated.
=======================================================================

=======================================================================
% ======================================== |  prepare online display  |
=======================================================================
Numer  screen_upper_row = 20;
Numer  screen_left_col  = 20;

Numer  screen_rows = 40 + dy_high;
Numer  screen_cols = 40 + glyph_distance
.                  + min( dx_high, floor infinity - 40 - glyph_distance );
=========
save  openit;
def   openit =
	openwindow currentwindow
	from ( screen_upper_row              , screen_left_col               )
	to   ( screen_upper_row + screen_rows, screen_left_col + screen_cols )
	at   ( -20, dy_high + 20 );
enddef;
=========
openit; % to get an empty screen first
=======================================================================
% =========================================== |  evaluate dimensions  |
=======================================================================
Vardef  set_sharp_dimensions( expr sign_id )
.                           ( suffix w_sharp, h_sharp, d_sharp )
.                           ( expr mid_x ) =

	Pair  xbo = glyph_bounds( sign_id )[ x_axis ];
	Pair  ybo = glyph_bounds( sign_id )[ y_axis ];

	Numer max_xbo = max( first xbo -+ mid_x, mid_x -+ second xbo );
	Pair  mod_xbo = !! max_xbo;

	w_sharp :=  dimension_wanted( sign_id )( x_axis )(          mod_xbo )
	.         + glyph_distance#;
	h_sharp :=  dimension_wanted( sign_id )( y_axis )( -$ 6, second ybo )
	.         + stroke_thickness_y#;
	d_sharp :=  dimension_wanted( sign_id )( z_axis )( first ybo , -$ 6 )
	.         + 0;
enddef;
=======================================================================
% ============================ |  convert free dimension into wanted  |
=======================================================================
Vardef  sharp  primary u  =  u / hppp  enddef;
=========
Numer   sharp_bound_tolerance = 0.01 glyph_distance#;
=========
Vardef  dimension_wanted( expr sign_id )( expr ax ) primary bounds =
	Numer  bb         =  max( 0, first bounds -+ second bounds );
	Numer  sharp_res :=  sharp bb;          % list may be empty

	Boolean  asc = is_ascii       sign_id;
	Boolean  pre = is_preliminary sign_id;

	for  dim =
		if      ax = x_axis :
			if asc: asc_dx_list elseif pre: pre_dx_list else: dx_list fi
		elseif  ax = y_axis :
			if asc: asc_dy_list elseif pre: pre_dy_list else: dy_list fi
		else                :
			if asc: asc_dz_list elseif pre: pre_dz_list else: dz_list fi
		fi
	:
		sharp_res :=
			if  numer dim: dim;
			else         : min( max( sharp bb, first dim ), second dim );
			fi;

		exitif  ( sharp bb <= sharp_res + sharp_bound_tolerance );
	endfor

	sharp_res
enddef;
=======================================================================
% =============================================== |  evaluate figure  |
=======================================================================
Vardef   evaluate( expr f, t ) =
	Transform  tt  =  trf f  transformed  t;

	if      op f = op_plus :  evaluate( lef f, tt );
	.                         evaluate( rgt f, tt );

	elseif  op f = op_path :
		if  length pth f > 0 :  draw           pth f   transformed  tt;
		else                 :  pickup  point_pen;
		.                       drawdot  beg ( pth f   transformed  tt );
		.                       pickup  stroke_pen;
		fi

	else : % op f = op_zero :   ;
	fi
enddef;
=======================================================================
% ============================================== |  produce the font  |
=======================================================================
% The convention `origin = glyph centre', has been used until now.
% Here we need to return to Metafonts convention
% `origin = left lower corner of (white embedded) glyph'.
%
% The wanted centering of glyphs in their space:
%     none ( value 0 of align_centered[_asc] )
%     full ( value 1 of align_centered[_asc] )
%     to some degree ( values from the range 0 to 1 )
% must be realized too.
% (? Is there any use for values <0, or >1 ?)
=======================================================================
string  currenttitle;

NUMER   w_sharp, h_sharp, d_sharp;
NUMER   w      , h      , d      ;
NUMER   mid_x  , bas_y  ;        % initial glyph `middle' (x-), base (y-part)
PAIR    xbo    ;

PAIR    sign_id;
FIGURE  sig;
NUMER   assoc_nr;
STRING  assoc_string;

	% To simplify working on the code of signs, shipped out,
	% special parentheses could be set in front and after
	% the row of `[c]' - progress reports:            %%% (unused now)
% if  proofing >= 0:  show "(-export starts-)";  fi

for  k  =  signs_in_sign_list( ASL ) :
	sign_id := ( ASL, k );
	sig     := glyph( sign_id );

	assoc_nr :=
		if      is_ascii       sign_id:  asc_temp_base -+ k
		elseif  is_preliminary sign_id:  preliminary_temp_base -+ k
		else                          :  k
		fi;

	assoc_string :=
		if      is_ascii       sign_id:  "asc "
		elseif  is_preliminary sign_id:  "pre "
		else                          :  sign_list_string_lc( ASL )
		fi;

	if  known sig
	and(
		.   (     is_ascii  sign_id
		.   cand( char assoc_nr  is_in  wanted_ascii_chars ) )

		cor(     is_preliminary  sign_id

		cor( is_may_be_range_element( second sign_id )
		.                      ( list_of_indus_signs_wanted ) )
	)):
		currenttitle := assoc_string  &  decimal assoc_nr;
		currenttitle;

		xbo   :=  glyph_bounds( sign_id ) [ x_axis ];

		mid_x :=  if            is_ascii sign_id:  align_centered_asc
		.         elseif  is_preliminary sign_id:  0
		.         else                          :  align_centered
		.         fi   [ 0, 0.5[ first xbo, second xbo ] ];

		mid_x :=  max( mid_x, second xbo - 0.5 dx_high ); % respect ...
		mid_x :=  min( mid_x, first  xbo + 0.5 dx_high ); % hard limits.

		bas_y :=  -( $$ + stroke_thickness_y ) / 2;

		set_sharp_dimensions( sign_id )( w_sharp, h_sharp, d_sharp )( mid_x );

		beginchar( 0, w_sharp, h_sharp, d_sharp );
			set_charcode_and_charext( ASL, k );

			pickup  stroke_pen;            % beginchar clears the pen
			evaluate( sig, identity shifted( (mid_x, bas_y) -+ (0.5w, 0) ) );

			if  stop_at_shipout > 0 :  stop ditto;  fi
		endchar;
	fi
endfor

% if  proofing >= 0:  show "(-export ended-)";  fi

=======================================================================

% #####################################################################
endgroup ;     % ########### |  END PART 7  : draw/display/export     |

user_intervention( stop_after_work > 0 ) "All work has been done - goon?:";

% #####################################################################

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FILE .END.
