% WEB change file containing HZ extensions for pdfTeX % % Copyright (c) 1996-2002 Han Th\^e\llap{\raise 0.5ex\hbox{\'{}}} Th\`anh, % % This file is part of pdfTeX. % % pdfTeX is free software; you can redistribute it and/or modify % it under the terms of the GNU General Public License as published by % the Free Software Foundation; either version 2 of the License, or % (at your option) any later version. % % pdfTeX is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the % GNU General Public License for more details. % % You should have received a copy of the GNU General Public License % along with pdfTeX; if not, write to the Free Software % Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA % % $Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/hz.ch#15 $ @x [155] - margin kerning @d acc_kern=2 {|subtype| of kern nodes from accents} @y @d acc_kern=2 {|subtype| of kern nodes from accents} @# {memory structure for marginal kerns} @d margin_kern_node = 40 @d margin_kern_node_size = 3 @d margin_char(#) == info(# + 2) @# {|subtype| of marginal kerns} @d left_side == 0 @d right_side == 1 @# {base for lp/rp/ef codes starts from 2: 0 for |hyphen_char|, 1 for |skew_char|} @d lp_code_base == 2 @d rp_code_base == 3 @d ef_code_base == 4 @d max_hlist_stack = 512 {maximum fill level for |hlist_stack|} {maybe good if larger than |2 * max_quarterword|, so that box nesting level would overflow first} @z @x [183] - margin kerning kern_node: @; @y margin_kern_node: begin print_esc("kern"); print_scaled(width(p)); if subtype(p) = left_side then print(" (left margin)") else print(" (right margin)"); end; kern_node: @; @z @x [202] - margin kerning kern_node,math_node,penalty_node: do_nothing; @y kern_node,math_node,penalty_node: do_nothing; margin_kern_node: begin free_avail(margin_char(p)); free_node(p, margin_kern_node_size); goto done; end; @z @x [206] - margin kerning kern_node,math_node,penalty_node: begin r:=get_node(small_node_size); words:=small_node_size; end; @y kern_node,math_node,penalty_node: begin r:=get_node(small_node_size); words:=small_node_size; end; margin_kern_node: begin r := get_node(margin_kern_node_size); fast_get_avail(margin_char(r)); font(margin_char(r)) := font(margin_char(p)); character(margin_char(r)) := character(margin_char(p)); words := small_node_size; end; @z @x [236] @d pdf_int_pars=pdftex_first_integer_code + 17 {total number of \pdfTeX's integer parameters} @y @d pdf_adjust_spacing_code = pdftex_first_integer_code + 17 {level of spacing adjusting} @d pdf_protrude_chars_code = pdftex_first_integer_code + 18 {protrude chars at left/right edge of paragraphs} @d pdf_tracing_fonts_code = pdftex_first_integer_code + 19 {level of font detail in log} @d pdf_int_pars=pdftex_first_integer_code + 20 {total number of \pdfTeX's integer parameters} @z @x [236] @d error_context_lines==int_par(error_context_lines_code) @y @d error_context_lines==int_par(error_context_lines_code) @# @d pdf_adjust_spacing == int_par(pdf_adjust_spacing_code) @d pdf_protrude_chars == int_par(pdf_protrude_chars_code) @d pdf_tracing_fonts == int_par(pdf_tracing_fonts_code) @z @x [237] error_context_lines_code:print_esc("errorcontextlines"); @y error_context_lines_code:print_esc("errorcontextlines"); @# pdf_adjust_spacing_code: print_esc("pdfadjustspacing"); pdf_protrude_chars_code: print_esc("pdfprotrudechars"); pdf_tracing_fonts_code: print_esc("pdftracingfonts"); @z @x [238] primitive("errorcontextlines",assign_int,int_base+error_context_lines_code);@/ @!@:error_context_lines_}{\.{\\errorcontextlines} primitive@> @y primitive("errorcontextlines",assign_int,int_base+error_context_lines_code);@/ @!@:error_context_lines_}{\.{\\errorcontextlines} primitive@> primitive("pdfadjustspacing",assign_int,int_base+pdf_adjust_spacing_code);@/ @!@:pdf_adjust_spacing_}{\.{\\pdfadjustspacing} primitive@> primitive("pdfprotrudechars",assign_int,int_base+pdf_protrude_chars_code);@/ @!@:pdf_protrude_chars_}{\.{\\pdfprotrudechars} primitive@> primitive("pdftracingfonts",assign_int,int_base+pdf_tracing_fonts_code);@/ @!@:pdf_tracing_fonts_}{\.{\\pdftracingfonts} primitive@> @z @x [267] - displaying fonts @= print_esc(font_id_text(font(p))) @y @= begin print_esc(font_id_text(font(p))); if pdf_tracing_fonts > 0 then begin print(" ("); print(font_name[font(p)]); if font_size[font(p)] <> font_dsize[font(p)] then begin print("@@"); print_scaled(font_size[font(p)]); print("pt"); end; print(")"); end else if pdf_font_expand_ratio[font(p)] <> 0 then begin print(" ("); if pdf_font_expand_ratio[font(p)] > 0 then print("+"); print_int(pdf_font_expand_ratio[font(p)]); print(")"); end; end @z @x [413] - font expansion var m:halfword; {|chr_code| part of the operand token} @y var m:halfword; {|chr_code| part of the operand token} n, k: integer; {accumulators} @z @x [426] - font expansion, margin kerning begin scan_font_ident; if m=0 then scanned_result(hyphen_char[cur_val])(int_val) else scanned_result(skew_char[cur_val])(int_val); @y begin scan_font_ident; if m=0 then scanned_result(hyphen_char[cur_val])(int_val) else if m=1 then scanned_result(skew_char[cur_val])(int_val) else begin n := cur_val; scan_char_num; k := cur_val; case m of lp_code_base: scanned_result(get_lp_code(n, k))(int_val); rp_code_base: scanned_result(get_rp_code(n, k))(int_val); ef_code_base: scanned_result(get_ef_code(n, k))(int_val); end; end; @z @x [468] @d pdftex_convert_codes = pdftex_first_expand_code + 9 {end of \pdfTeX's command codes} @y @d left_margin_kern_code = pdftex_first_expand_code + 9 {command code for \.{\\leftmarginkern}} @d right_margin_kern_code = pdftex_first_expand_code + 10 {command code for \.{\\rightmarginkern}} @d pdftex_convert_codes = pdftex_first_expand_code + 11 {end of \pdfTeX's command codes} @z @x [468] primitive("pdfpageref",convert,pdf_page_ref_code);@/ @!@:pdf_page_ref_}{\.{\\pdfpageref} primitive@> @y primitive("pdfpageref",convert,pdf_page_ref_code);@/ @!@:pdf_page_ref_}{\.{\\pdfpageref} primitive@> primitive("leftmarginkern",convert,left_margin_kern_code);@/ @!@:left_margin_kern_}{\.{\\leftmarginkern} primitive@> primitive("rightmarginkern",convert,right_margin_kern_code);@/ @!@:right_margin_kern_}{\.{\\rightmarginkern} primitive@> @z @x [469] pdf_page_ref_code: print_esc("pdfpageref"); @y pdf_page_ref_code: print_esc("pdfpageref"); left_margin_kern_code: print_esc("leftmarginkern"); right_margin_kern_code: print_esc("rightmarginkern"); @z @x [470] var old_setting:0..max_selector; {holds |selector| setting} @y var old_setting:0..max_selector; {holds |selector| setting} p, q: pointer; @z @x [471] pdf_page_ref_code: begin scan_int; if cur_val <= 0 then pdf_error("pageref", "invalid page number"); end; @y pdf_page_ref_code: begin scan_int; if cur_val <= 0 then pdf_error("pageref", "invalid page number"); end; left_margin_kern_code, right_margin_kern_code: begin scan_int; if (box(cur_val) = null) or (type(box(cur_val)) <> hlist_node) then pdf_error("marginkern", "a non-empty hbox expected") end; @z @x [472] pdf_page_ref_code: print_int(get_obj(obj_type_page, cur_val, false)); @y pdf_page_ref_code: print_int(get_obj(obj_type_page, cur_val, false)); left_margin_kern_code: begin p := list_ptr(box(cur_val)); if (p <> null) and (not is_char_node(p)) and (type(p) = glue_node) and (subtype(p) = left_skip_code + 1) then p := link(p); if (p <> null) and (not is_char_node(p)) and (type(p) = margin_kern_node) and (subtype(p) = left_side) then print_scaled(width(p)) else print("0"); print("pt"); end; right_margin_kern_code: begin q := list_ptr(box(cur_val)); p := null; if q <> null then begin p := prev_rightmost(q, null); if (p <> null) and (not is_char_node(p)) and (type(p) = glue_node) and (subtype(p) = right_skip_code + 1) then p := prev_rightmost(q, p); end; if (p <> null) and (not is_char_node(p)) and (type(p) = margin_kern_node) and (subtype(p) = right_side) then print_scaled(width(p)) else print("0"); print("pt"); end; @z @x [622] - margin kerning glue_node: @; @y glue_node: @; margin_kern_node, @z @x [???] - font expansion @!tmp_f: internal_font_number; {for use with |pdf_init_font|} @y @!tmp_f: internal_font_number; {for use with |pdf_init_font|} @ Here come some subroutines to deal with expanded fonts for HZ-algorithm. @p function init_font_base(v: integer): integer; var i, j: integer; begin i := pdf_get_mem(256); for j := 0 to 255 do pdf_mem[i + j] := v; init_font_base := i; end; procedure set_lp_code(f: internal_font_number; c: eight_bits; i: integer); begin if pdf_font_lp_base[f] = 0 then pdf_font_lp_base[f] := init_font_base(0); pdf_mem[pdf_font_lp_base[f] + c] := fix_int(i, -1000, 1000); end; procedure set_rp_code(f: internal_font_number; c: eight_bits; i: integer); begin if pdf_font_rp_base[f] = 0 then pdf_font_rp_base[f] := init_font_base(0); pdf_mem[pdf_font_rp_base[f] + c] := fix_int(i, -1000, 1000); end; procedure set_ef_code(f: internal_font_number; c: eight_bits; i: integer); begin if pdf_font_ef_base[f] = 0 then pdf_font_ef_base[f] := init_font_base(1000); pdf_mem[pdf_font_ef_base[f] + c] := fix_int(i, 0, 1000); end; function expand_font_name(f: internal_font_number; e: integer): str_number; var old_setting:0..max_selector; {holds |selector| setting} begin old_setting:=selector; selector:=new_string; print(font_name[f]); if e > 0 then print("+"); {minus sign will be printed by |print_int|} print_int(e); selector:=old_setting; expand_font_name := make_string; end; function auto_expand_font(f: internal_font_number; e: integer): internal_font_number; {creates an expanded font from the base font; doesn't load expanded tfm at all} var k: internal_font_number; nw, nk, ni, i, j: integer; begin k := font_ptr + 1; incr(font_ptr); if (font_ptr >= font_max) then overflow("maximum internal font number (font_max)", font_max); font_name[k] := expand_font_name(f, e); font_area[k] := font_area[f]; font_id_text(k) := font_id_text(f); hyphen_char[k] := hyphen_char[f]; skew_char[k] := skew_char[f]; font_bchar[k] := font_bchar[f]; font_false_bchar[k] := font_false_bchar[f]; font_bc[k] := font_bc[f]; font_ec[k] := font_ec[f]; font_size[k] := font_size[f]; font_dsize[k] := font_dsize[f]; font_params[k] := font_params[f]; font_glue[k] := font_glue[f]; bchar_label[k] := bchar_label[f]; char_base[k] := char_base[f]; height_base[k] := height_base[f]; depth_base[k] := depth_base[f]; lig_kern_base[k] := lig_kern_base[f]; exten_base[k] := exten_base[f]; param_base[k] := param_base[f]; nw := height_base[f] - width_base[f]; ni := lig_kern_base[f] - italic_base[f]; nk := exten_base[f] - (kern_base[f] + kern_base_offset); if (fmem_ptr + nw + ni + nk >= font_mem_size) then overflow("number of words of font memory (font_mem_size)", font_mem_size); width_base[k] := fmem_ptr; italic_base[k] := width_base[k] + nw; kern_base[k] := italic_base[k] + ni - kern_base_offset; fmem_ptr := fmem_ptr + nw + ni + nk; for i := 0 to nw - 1 do font_info[width_base[k] + i].sc := round_xn_over_d(font_info[width_base[f] + i].sc, 1000 + e, 1000); for i := 0 to ni - 1 do font_info[italic_base[k] + i].sc := round_xn_over_d(font_info[italic_base[f] + i].sc, 1000 + e, 1000); for i := 0 to nk - 1 do font_info[kern_base[k] + kern_base_offset + i].sc := round_xn_over_d(font_info[kern_base[f] + kern_base_offset + i].sc, 1000 + e, 1000); auto_expand_font := k; end; procedure set_expand_param(k, f: internal_font_number; e: integer); var i, j: integer; begin if pdf_font_rp_base[f] = 0 then pdf_font_rp_base[f] := init_font_base(0); if pdf_font_lp_base[f] = 0 then pdf_font_lp_base[f] := init_font_base(0); if pdf_font_ef_base[f] = 0 then pdf_font_ef_base[f] := init_font_base(1000); pdf_font_expand_ratio[k] := e; pdf_font_step[k] := pdf_font_step[f]; pdf_font_auto_expand[k] := pdf_font_auto_expand[f]; pdf_font_blink[k] := f; {???} pdf_font_lp_base[k] := pdf_font_lp_base[f]; pdf_font_rp_base[k] := pdf_font_rp_base[f]; pdf_font_ef_base[k] := pdf_font_ef_base[f]; end; function tfm_lookup(s: str_number; fs: scaled): internal_font_number; {looks up for a TFM with name |s| loaded at |fs| size; if found then flushes |s|} var k: internal_font_number; begin if fs <> 0 then begin for k := font_base + 1 to font_ptr do if str_eq_str(font_name[k], s) and (font_size[k] = fs) then begin flush_str(s); tfm_lookup := k; return; end; end else begin for k := font_base + 1 to font_ptr do if str_eq_str(font_name[k], s) then begin flush_str(s); tfm_lookup := k; return; end; end; tfm_lookup := null_font; end; function load_expand_font(f: internal_font_number; e: integer): internal_font_number; {loads font |f| expanded by |e| thousandths into font memory; |e| is nonzero and is a multiple of |pdf_font_step[f]|} label found; var s: str_number; {font name} k: internal_font_number; begin s := expand_font_name(f, e); k := tfm_lookup(s, font_size[f]); if k = null_font then begin if pdf_font_auto_expand[f] then k := auto_expand_font(f, e) else k := read_font_info(null_cs, s, "", font_size[f]); end; set_expand_param(k, f, e); load_expand_font := k; end; function auto_expand_vf(f: internal_font_number): boolean; {check for a virtual auto-expanded font} var save_f, bf, lf, k: internal_font_number; e: integer; begin auto_expand_vf := false; if (not pdf_font_auto_expand[f]) or (pdf_font_blink[f] = null_font) then return; {not an auto-expanded font} bf := pdf_font_blink[f]; if pdf_font_type[bf] = new_font_type then {we must process the base font first} begin save_f := tmp_f; tmp_f := bf; do_vf; tmp_f := save_f; end; if pdf_font_type[bf] <> virtual_font_type then return; {not a virtual font} e := pdf_font_expand_ratio[f]; for k := 0 to vf_local_font_num[bf] - 1 do begin lf := vf_default_font[bf] + k; vf_e_fnts[vf_nf] := vf_e_fnts[lf]; vf_i_fnts[vf_nf] := auto_expand_font(vf_i_fnts[lf], e); set_expand_param(vf_i_fnts[vf_nf], vf_i_fnts[lf], e); incr(vf_nf); end; vf_packet_base[f] := vf_packet_base[bf]; vf_local_font_num[f] := vf_local_font_num[bf]; vf_default_font[f] := vf_nf - vf_local_font_num[f]; pdf_font_type[f] := virtual_font_type; auto_expand_vf := true; end; function fix_expand_value(f: internal_font_number; e: integer): integer; {return the multiple of |pdf_font_step[f]| that is nearest to |e|} var step: integer; max_expand: integer; neg: boolean; begin fix_expand_value := 0; if e = 0 then return; if e < 0 then begin e := -e; neg := true; max_expand := -pdf_font_expand_ratio[pdf_font_shrink[f]]; end else begin neg := false; max_expand := pdf_font_expand_ratio[pdf_font_stretch[f]]; end; if e > max_expand then e := max_expand else begin step := pdf_font_step[f]; if e mod step > 0 then e := step*round_xn_over_d(e, 1, step); end; if neg then e := -e; fix_expand_value := e; end; function get_expand_font(f: internal_font_number; e: integer): internal_font_number; {look up and create if not found an expanded version of |f|; |f| is an expandable font; |e| is nonzero and is a multiple of |pdf_font_step[f]|} var k: internal_font_number; begin k := pdf_font_elink[f]; while k <> null_font do begin if pdf_font_expand_ratio[k] = e then begin get_expand_font := k; return; end; k := pdf_font_elink[k]; end; k := load_expand_font(f, e); pdf_font_elink[k] := pdf_font_elink[f]; pdf_font_elink[f] := k; get_expand_font := k; end; function expand_font(f: internal_font_number; e: integer): internal_font_number; {looks up for font |f| expanded by |e| thousandths, |e| is an arbitrary value between max stretch and max shrink of |f|; if not found then creates it} var max_expand: integer; begin expand_font := f; if e = 0 then return; e := fix_expand_value(f, e); if e = 0 then return; if pdf_font_elink[f] = null_font then pdf_error("font expansion", "uninitialized pdf_font_elink"); expand_font := get_expand_font(f, e); end; procedure read_expand_font; {read font expansion spec and load expanded font} var font_shrink, font_stretch, font_step: integer; f: internal_font_number; auto_expand: boolean; begin {read font expansion parameters} scan_font_ident; f := cur_val; if f = null_font then pdf_error("font expansion", "invalid font identifier"); scan_optional_equals; scan_int; font_stretch := fix_int(cur_val, 0, 1000); scan_int; font_shrink := fix_int(cur_val, 0, 1000); scan_int; font_step := fix_int(cur_val, 0, 1000); if font_step = 0 then pdf_error("font expansion", "invalid step"); font_stretch := font_stretch - font_stretch mod font_step; if font_stretch < 0 then font_stretch := 0; font_shrink := font_shrink - font_shrink mod font_step; if font_shrink < 0 then font_shrink := 0; if font_shrink = 1000 then font_shrink := font_shrink - font_step; {don't allow zero-width font} if (font_stretch = 0) and (font_shrink = 0) then pdf_error("font expansion", "invalid limit"); auto_expand := false; if scan_keyword("autoexpand") then begin auto_expand := true; @; end; {check if the font can be expanded} if (pdf_font_expand_ratio[f] <> 0) then pdf_error("font expansion", "this font has been expanded by another font so it cannot be used now"); if (pdf_font_step[f] <> 0) then {this font has been expanded, ensure the expansion parameters are identical} begin if (pdf_font_step[f] <> font_step) or ((pdf_font_stretch[f] = null_font) and (font_stretch <> 0)) or ((pdf_font_stretch[f] <> null_font) and (pdf_font_expand_ratio[pdf_font_stretch[f]] <> font_stretch)) or ((pdf_font_shrink[f] = null_font) and (font_shrink <> 0)) or ((pdf_font_shrink[f] <> null_font) and (pdf_font_expand_ratio[pdf_font_shrink[f]] <> -font_shrink)) or (pdf_font_auto_expand[f] <> auto_expand) then pdf_error("font expansion", "font has been expanded with different parameters"); end else begin pdf_font_step[f] := font_step; pdf_font_auto_expand[f] := auto_expand; if font_stretch > 0 then pdf_font_stretch[f] := get_expand_font(f, font_stretch); if font_shrink > 0 then pdf_font_shrink[f] := get_expand_font(f, -font_shrink); end; end; @z @x [32f] - margin kerning glue_node: @<(\pdfTeX) Move right or output leaders@>; @y glue_node: @<(\pdfTeX) Move right or output leaders@>; margin_kern_node, @z @x [649] - font expansion @ Here now is |hpack|, which contains few if any surprises. @p function hpack(@!p:pointer;@!w:scaled;@!m:small_number):pointer; @y @ @= @!pdf_font_blink: ^internal_font_number; {link to base font (used for expanded fonts only)} @!pdf_font_elink: ^internal_font_number; {link to expanded fonts (used for base fonts only)} @!pdf_font_stretch: ^integer; {limit of stretching} @!pdf_font_shrink: ^integer; {limit of shrinking} @!pdf_font_step: ^integer; {amount of one step of expansion} @!pdf_font_expand_ratio: ^integer; {expansion ratio of a particular font} @!pdf_font_auto_expand: ^boolean; {this font is auto-expanded?} @!pdf_font_lp_base: ^integer; {base of left-protruding factor} @!pdf_font_rp_base: ^integer; {base of right-protruding factor} @!pdf_font_ef_base: ^integer; {base of font expansion factor} @!font_expand_ratio: integer; {current expansion ratio} @!last_leftmost_char: pointer; @!last_rightmost_char: pointer; @!hlist_stack:array[0..max_hlist_stack] of pointer; {stack for |find_protchar_left()| and |find_protchar_right()|} @!hlist_stack_level:0..max_hlist_stack; {fill level for |hlist_stack|} @ @d cal_margin_kern_var(#) == begin character(cp) := character(#); font(cp) := font(#); do_subst_font(cp, 1000); if font(cp) <> font(#) then margin_kern_stretch := margin_kern_stretch + left_pw(#) - left_pw(cp); font(cp) := font(#); do_subst_font(cp, -1000); if font(cp) <> font(#) then margin_kern_shrink := margin_kern_shrink + left_pw(cp) - left_pw(#); end @= begin lp := last_leftmost_char; rp := last_rightmost_char; fast_get_avail(cp); if lp <> null then cal_margin_kern_var(lp); if rp <> null then cal_margin_kern_var(rp); free_avail(cp); end @ Here is |hpack|, which is place where we do font substituting when font expansion is being used. We define some constants used when calling |hpack| to deal with font expansion. @d cal_expand_ratio == 2 {calculate amount for font expansion after breaking paragraph into lines} @d subst_ex_font == 3 {substitute fonts} @d substituted = 3 {|subtype| of kern nodes that should be substituted} @d left_pw(#) == char_pw(#, left_side) @d right_pw(#) == char_pw(#, right_side) @p function check_expand_pars(f: internal_font_number): boolean; var k: internal_font_number; begin check_expand_pars := false; if (pdf_font_step[f] = 0) or ((pdf_font_stretch[f] = null_font) and (pdf_font_shrink[f] = null_font)) then return; if cur_font_step < 0 then cur_font_step := pdf_font_step[f] else if cur_font_step <> pdf_font_step[f] then pdf_error("font expansion", "using fonts with different step of expansion in one paragraph is not allowed"); k := pdf_font_stretch[f]; if k <> null_font then begin if max_stretch_ratio < 0 then max_stretch_ratio := pdf_font_expand_ratio[k] else if max_stretch_ratio <> pdf_font_expand_ratio[k] then pdf_error("font expansion", "using fonts with different limit of expansion in one paragraph is not allowed"); end; k := pdf_font_shrink[f]; if k <> null_font then begin if max_shrink_ratio < 0 then max_shrink_ratio := pdf_font_expand_ratio[k] else if max_shrink_ratio <> pdf_font_expand_ratio[k] then pdf_error("font expansion", "using fonts with different limit of expansion in one paragraph is not allowed"); end; check_expand_pars := true; end; function char_stretch(f: internal_font_number; c: eight_bits): scaled; var k: internal_font_number; dw: scaled; ef: integer; begin char_stretch := 0; k := pdf_font_stretch[f]; ef := get_ef_code(f, c); if (k <> null_font) and (ef > 0) then begin dw := char_width(k)(char_info(k)(c)) - char_width(f)(char_info(f)(c)); if dw > 0 then char_stretch := round_xn_over_d(dw, ef, 1000); end; end; function char_shrink(f: internal_font_number; c: eight_bits): scaled; var k: internal_font_number; dw: scaled; ef: integer; begin char_shrink := 0; k := pdf_font_shrink[f]; ef := get_ef_code(f, c); if (k <> null_font) and (ef > 0) then begin dw := char_width(f)(char_info(f)(c)) - char_width(k)(char_info(k)(c)); if dw > 0 then char_shrink := round_xn_over_d(dw, ef, 1000); end; end; function get_kern(f: internal_font_number; lc, rc: eight_bits): scaled; label continue; var i: four_quarters; j: four_quarters; k: font_index; p: pointer; s: integer; begin get_kern := 0; i := char_info(f)(lc); if char_tag(i) <> lig_tag then return; k := lig_kern_start(f)(i); j := font_info[k].qqqq; if skip_byte(j) <= stop_flag then goto continue + 1; k := lig_kern_restart(f)(j); continue: j := font_info[k].qqqq; continue + 1: if (next_char(j) = rc) and (skip_byte(j) <= stop_flag) and (op_byte(j) >= kern_flag) then begin get_kern := char_kern(f)(j); return; end; if skip_byte(j) = qi(0) then incr(k) else begin if skip_byte(j) >= stop_flag then return; k := k + qo(skip_byte(j)) + 1; end; goto continue; end; function kern_stretch(p: pointer): scaled; var l, r: pointer; d: scaled; begin kern_stretch := 0; if (prev_char_p = null) or (link(prev_char_p) <> p) or (link(p) = null) then return; l := prev_char_p; r := link(p); if type(l) = ligature_node then l := lig_char(l); if type(r) = ligature_node then r := lig_char(r); if not (is_char_node(l) and is_char_node(r) and (font(l) = font(r)) and (pdf_font_stretch[font(l)] <> null_font)) then return; d := get_kern(pdf_font_stretch[font(l)], character(l), character(r)); kern_stretch := round_xn_over_d(d - width(p), get_ef_code(font(l), character(l)), 1000); end; function kern_shrink(p: pointer): scaled; var l, r: pointer; d: scaled; begin kern_shrink := 0; if (prev_char_p = null) or (link(prev_char_p) <> p) or (link(p) = null) then return; l := prev_char_p; r := link(p); if type(l) = ligature_node then l := lig_char(l); if type(r) = ligature_node then r := lig_char(r); if not (is_char_node(l) and is_char_node(r) and (font(l) = font(r)) and (pdf_font_shrink[font(l)] <> null_font)) then return; d := get_kern(pdf_font_shrink[font(l)], character(l), character(r)); kern_shrink := round_xn_over_d(width(p) - d, get_ef_code(font(l), character(l)), 1000); end; procedure do_subst_font(p: pointer; ex_ratio: integer); var f, k: internal_font_number; r: pointer; ef: integer; begin if not is_char_node(p) and (type(p) = disc_node) then begin r := pre_break(p); while r <> null do begin if is_char_node(r) or (type(r) = ligature_node) then do_subst_font(r, ex_ratio); r := link(r); end; r := post_break(p); while r <> null do begin if is_char_node(r) or (type(r) = ligature_node) then do_subst_font(r, ex_ratio); r := link(r); end; return; end; if is_char_node(p) then r := p else if type(p) = ligature_node then r := lig_char(p) else begin {|short_display_n(p, 5);|} pdf_error("font expansion", "invalid node type"); end; f := font(r); ef := get_ef_code(f, character(r)); if ef = 0 then return; if (pdf_font_stretch[f] <> null_font) and (ex_ratio > 0) then k := expand_font(f, divide_scaled(ex_ratio* pdf_font_expand_ratio[pdf_font_stretch[f]]*ef, 1000000, 0)) else if (pdf_font_shrink[f] <> null_font) and (ex_ratio < 0) then k := expand_font(f, -divide_scaled(ex_ratio* pdf_font_expand_ratio[pdf_font_shrink[f]]*ef, 1000000, 0)) else k := f; if k <> f then begin font(r) := k; if not is_char_node(p) then begin r := lig_ptr(p); while r <> null do begin font(r) := k; r := link(r); end; end; end; end; function char_pw(p: pointer; side: small_number): scaled; var f: internal_font_number; c: integer; begin char_pw := 0; if side = left_side then last_leftmost_char := null else last_rightmost_char := null; if p = null then return; if not is_char_node(p) then begin if type(p) = ligature_node then p := lig_char(p) else return; end; f := font(p); if side = left_side then begin c := get_lp_code(f, character(p)); last_leftmost_char := p; end else begin c := get_rp_code(f, character(p)); last_rightmost_char := p; end; if c = 0 then return; char_pw := round_xn_over_d(quad(f), c, 1000); end; function new_margin_kern(w: scaled; p: pointer; side: small_number): pointer; var k: pointer; begin k := get_node(margin_kern_node_size); type(k) := margin_kern_node; subtype(k) := side; width(k) := w; if p = null then pdf_error("margin kerning", "invalid pointer to marginal char node"); fast_get_avail(margin_char(k)); character(margin_char(k)) := character(p); font(margin_char(k)) := font(p); new_margin_kern := k; end; function hpack(@!p:pointer;@!w:scaled;@!m:small_number):pointer; @z @x [649] - font expansion begin last_badness:=0; r:=get_node(box_node_size); type(r):=hlist_node; subtype(r):=min_quarterword; shift_amount(r):=0; q:=r+list_offset; link(q):=p;@/ @y font_stretch: scaled; font_shrink: scaled; k: scaled; begin last_badness:=0; r:=get_node(box_node_size); type(r):=hlist_node; subtype(r):=min_quarterword; shift_amount(r):=0; q:=r+list_offset; link(q):=p;@/ if m = cal_expand_ratio then begin prev_char_p := null; font_stretch := 0; font_shrink := 0; font_expand_ratio := 0; end; @z @x [649] - font expansion hpack:=r; @y if (m = cal_expand_ratio) and (font_expand_ratio <> 0) then begin font_expand_ratio := fix_int(font_expand_ratio, -1000, 1000); q := list_ptr(r); free_node(r, box_node_size); r := hpack(q, w, subst_ex_font); end; hpack:=r; @z @x [651] - font expansion kern_node: x:=x+width(p); @y margin_kern_node: begin if m = cal_expand_ratio then begin f := font(margin_char(p)); do_subst_font(margin_char(p), 1000); if f <> font(margin_char(p)) then font_stretch := font_stretch - width(p) - char_pw(margin_char(p), subtype(p)); font(margin_char(p)) := f; do_subst_font(margin_char(p), -1000); if f <> font(margin_char(p)) then font_shrink := font_shrink - width(p) - char_pw(margin_char(p), subtype(p)); font(margin_char(p)) := f; end else if m = subst_ex_font then begin do_subst_font(margin_char(p), font_expand_ratio); width(p) := -char_pw(margin_char(p), subtype(p)); end; x := x + width(p); end; kern_node: begin if (m = cal_expand_ratio) and (subtype(p) = normal) then begin k := kern_stretch(p); if k <> 0 then begin subtype(p) := substituted; font_stretch := font_stretch + k; end; k := kern_shrink(p); if k <> 0 then begin subtype(p) := substituted; font_shrink := font_shrink + k; end; end else if (m = subst_ex_font) and (subtype(p) = substituted) then begin if type(link(p)) = ligature_node then width(p) := get_kern(font(prev_char_p), character(prev_char_p), character(lig_char(link(p)))) else width(p) := get_kern(font(prev_char_p), character(prev_char_p), character(link(p))) end; x := x + width(p); end; @z @x [651] - font expansion ligature_node: @; @y ligature_node: begin if m = subst_ex_font then do_subst_font(p, font_expand_ratio); @; end; disc_node: if m = subst_ex_font then do_subst_font(p, font_expand_ratio); @z @x [654] - font expansion begin f:=font(p); i:=char_info(f)(character(p)); hd:=height_depth(i); @y begin if m >= cal_expand_ratio then begin prev_char_p := p; case m of cal_expand_ratio: begin f := font(p); add_char_stretch(font_stretch)(character(p)); add_char_shrink(font_shrink)(character(p)); end; subst_ex_font: do_subst_font(p, font_expand_ratio); endcases; end; f:=font(p); i:=char_info(f)(character(p)); hd:=height_depth(i); @z @x [658] - font expansion @ @= begin @; @y @ If |hpack| is called with |m=cal_expand_ratio| we calculate |font_expand_ratio| and return without checking for overfull or underfull box. @= begin @; if (m = cal_expand_ratio) and (o = normal) and (font_stretch > 0) then begin font_expand_ratio := divide_scaled(x, font_stretch, 3); return; end; @z @x [664] - font expansion @ @= begin @; @y @ @= begin @; if (m = cal_expand_ratio) and (o = normal) and (font_shrink > 0) then begin font_expand_ratio := divide_scaled(x, font_shrink, 3); return; end; @z @x [822] - font expansion @d delta_node_size=7 {number of words in a delta node} @y @d delta_node_size=9 {number of words in a delta node} @z @x [823] - font expansion, margin kerning, avoiding overfull boxes @= @!active_width:array[1..6] of scaled; {distance from first active node to~|cur_p|} @!cur_active_width:array[1..6] of scaled; {distance from current active node} @!background:array[1..6] of scaled; {length of an ``empty'' line} @!break_width:array[1..6] of scaled; {length being computed after current break} @y @d do_seven_eight(#) == if pdf_adjust_spacing > 1 then begin #(7);#(8); end @d do_all_eight(#) == do_all_six(#); do_seven_eight(#) @d do_one_seven_eight(#) == #(1); do_seven_eight(#) @d total_font_stretch == cur_active_width[7] @d total_font_shrink == cur_active_width[8] @d save_active_width(#) == prev_active_width[#] := active_width[#] @d restore_active_width(#) == active_width[#] := prev_active_width[#] @= @!active_width:array[1..8] of scaled; {distance from first active node to~|cur_p|} @!cur_active_width:array[1..8] of scaled; {distance from current active node} @!background:array[1..8] of scaled; {length of an ``empty'' line} @!break_width:array[1..8] of scaled; {length being computed after current break} @# @!auto_breaking: boolean; {make |auto_breaking| accessible out of |line_break|} @!prev_p: pointer; {make |prev_p| accessible out of |line_break|} @!first_p: pointer; {to access the first node of the paragraph} @!prev_char_p: pointer; {pointer to the previous char of an implicit kern} @!next_char_p: pointer; {pointer to the next char of an implicit kern} @# @!try_prev_break: boolean; {force break at the previous legal breakpoint?} @!prev_legal: pointer; {the previous legal breakpoint} @!prev_prev_legal: pointer; {to save |prev_p| corresponding to |prev_legal|} @!prev_auto_breaking: boolean; {to save |auto_breaking| corresponding to |prev_legal|} @!prev_active_width: array[1..8] of scaled; {to save |active_width| corresponding to |prev_legal|} @!rejected_cur_p: pointer; {the last |cur_p| that has been rejected} @!before_rejected_cur_p: boolean; {|cur_p| is still before |rejected_cur_p|?} @# @!max_stretch_ratio: integer; {maximal stretch ratio of expanded fonts} @!max_shrink_ratio: integer; {maximal shrink ratio of expanded fonts} @!cur_font_step: integer; {the current step of expanded fonts} @z @x [827] - font expansion background[6]:=shrink(q)+shrink(r); @y background[6]:=shrink(q)+shrink(r); if pdf_adjust_spacing > 1 then begin background[7] := 0; background[8] := 0; max_stretch_ratio := -1; max_shrink_ratio := -1; cur_font_step := -1; prev_char_p := null; end; @z @x [829] - margin kerning @= procedure try_break(@!pi:integer;@!break_type:small_number); @y @d cp_skipable(#) == {skipable nodes at the margins during character protrusion} ( not is_char_node(#) and ( (type(#) = ins_node) or (type(#) = mark_node) or (type(#) = adjust_node) or (type(#) = penalty_node) or ((type(#) = whatsit_node) and (subtype(#) <> pdf_refximage_node) and (subtype(#) <> pdf_refxform_node)) {reference to an image or XObject form} or ((type(#) = disc_node) and (pre_break(#) = null) and (post_break(#) = null) and (replace_count(#) = 0)) {an empty |disc_node|} or ((type(#) = math_node) and (width(#) = 0)) or ((type(#) = kern_node) and ((width(#) = 0) or (subtype(#) = normal))) or ((type(#) = glue_node) and (glue_ptr(#) = zero_glue)) or ((type(#) = hlist_node) and (width(#) = 0) and (height(#) = 0) and (depth(#) = 0) and (list_ptr(#) = null)) ) ) @= procedure push_node(p: pointer); begin if hlist_stack_level > max_hlist_stack then pdf_error("push_node", "stack overflow"); hlist_stack[hlist_stack_level] := p; hlist_stack_level := hlist_stack_level + 1; end; function pop_node: pointer; begin hlist_stack_level := hlist_stack_level - 1; if hlist_stack_level < 0 then {would point to some bug} pdf_error("pop_node", "stack underflow (internal error)"); pop_node := hlist_stack[hlist_stack_level]; end; function find_protchar_left(l: pointer; d: boolean): pointer; {searches left to right from list head |l|, returns 1st non-skipable item} var t: pointer; run: boolean; begin if (link(l) <> null) and (type(l) = hlist_node) and (width(l) = 0) and (height(l) = 0) and (depth(l) = 0) and (list_ptr(l) = null) then l := link(l) {for paragraph start with \.{\\parindent = 0pt}} else if d then while (link(l) <> null) and (not (is_char_node(l) or non_discardable(l))) do l := link(l); {std.\ discardables at line break, \TeX book, p 95} hlist_stack_level := 0; run := true; repeat t := l; while run and (type(l) = hlist_node) and (list_ptr(l) <> null) do begin push_node(l); l := list_ptr(l); end; while run and cp_skipable(l) do begin while (link(l) = null) and (hlist_stack_level > 0) do begin l := pop_node; {don't visit this node again} end; if link(l) <> null then l := link(l) else if hlist_stack_level = 0 then run := false end; until t = l; find_protchar_left := l; end; function find_protchar_right(l, r: pointer): pointer; {searches right to left from list tail |r| to head |l|, returns 1st non-skipable item} var t: pointer; run: boolean; begin find_protchar_right := null; if r = null then return; hlist_stack_level := 0; run := true; repeat t := r; while run and (type(r) = hlist_node) and (list_ptr(r) <> null) do begin push_node(l); push_node(r); l := list_ptr(r); r := l; while link(r) <> null do r := link(r); end; while run and cp_skipable(r) do begin while (r = l) and (hlist_stack_level > 0) do begin r := pop_node; {don't visit this node again} l := pop_node; end; if (r <> l) and (r <> null) then r := prev_rightmost(l, r) else if (r = l) and (hlist_stack_level = 0) then run := false end; until t = r; find_protchar_right := r; end; function total_pw(q, p: pointer): scaled; {returns the total width of character protrusion of a line; |cur_break(break_node(q))| and |p| is the leftmost resp. rightmost node in the horizontal list representing the actual line} var l, r, s: pointer; n: integer; begin if break_node(q) = null then l := first_p else l := cur_break(break_node(q)); r := prev_rightmost(prev_p, p); {get |link(r)=p|} {let's look at the right margin first} {| short_display_n(r, 2); print("&"); short_display_n(p, 2); print_ln; |} if (p <> null) and (type(p) = disc_node) and (pre_break(p) <> null) then {a |disc_node| with non-empty |pre_break|, protrude the last char of |pre_break|} begin r := pre_break(p); while link(r) <> null do r := link(r); end else r := find_protchar_right(l, r); {now the left margin} {| short_display_n(l, 2); print_ln; breadth_max := 10; depth_threshold := 2; show_node_list(l); print_ln; |} if (l <> null) and (type(l) = disc_node) then begin if post_break(l) <> null then begin l := post_break(l); {protrude the first char} goto done; end else {discard |replace_count(l)| nodes} begin n := replace_count(l); l := link(l); while n > 0 do begin if link(l) <> null then l := link(l); decr(n); end; end; end; l := find_protchar_left(l, true); done: total_pw := left_pw(l) + right_pw(r); end; procedure try_break(@!pi:integer;@!break_type:small_number); @z @x var r:pointer; {runs through the active list} @y var r:pointer; {runs through the active list} @!margin_kern_stretch: scaled; @!margin_kern_shrink: scaled; @!lp, rp, cp: pointer; @z @x [829] - font expansion do_all_six(copy_to_cur_active); @y do_all_eight(copy_to_cur_active); @z @x [832] - font expansion begin do_all_six(update_width); @y begin do_all_eight(update_width); @z @x [837] - font expansion begin no_break_yet:=false; do_all_six(set_break_width_to_background); @y begin no_break_yet:=false; do_all_eight(set_break_width_to_background); @z @x [839] - font expansion @= @!disc_width:scaled; {the length of discretionary material preceding a break} @y @d reset_disc_width(#) == disc_width[#] := 0 @d add_disc_width_to_break_width(#) == break_width[#] := break_width[#] + disc_width[#] @d add_disc_width_to_active_width(#) == active_width[#] := active_width[#] + disc_width[#] @d sub_disc_width_from_active_width(#) == active_width[#] := active_width[#] - disc_width[#] @d add_char_stretch_end(#) == char_stretch(f, #) @d add_char_stretch(#) == # := # + add_char_stretch_end @d add_char_shrink_end(#) == char_shrink(f, #) @d add_char_shrink(#) == # := # + add_char_shrink_end @d sub_char_stretch_end(#) == char_stretch(f, #) @d sub_char_stretch(#) == # := # - sub_char_stretch_end @d sub_char_shrink_end(#) == char_shrink(f, #) @d sub_char_shrink(#) == # := # - sub_char_shrink_end @d add_kern_stretch_end(#) == kern_stretch(#) @d add_kern_stretch(#) == # := # + add_kern_stretch_end @d add_kern_shrink_end(#) == kern_shrink(#) @d add_kern_shrink(#) == # := # + add_kern_shrink_end @d sub_kern_stretch_end(#) == kern_stretch(#) @d sub_kern_stretch(#) == # := # - sub_kern_stretch_end @d sub_kern_shrink_end(#) == kern_shrink(#) @d sub_kern_shrink(#) == # := # - sub_kern_shrink_end @= @!disc_width: array[1..8] of scaled; {the length of discretionary material preceding a break} @z @x [840] - font expansion break_width[1]:=break_width[1]+disc_width; @y do_one_seven_eight(add_disc_width_to_break_width); @z @x [841] - font expansion break_width[1]:=break_width[1]-char_width(f)(char_info(f)(character(v))); @y break_width[1]:=break_width[1]-char_width(f)(char_info(f)(character(v))); if (pdf_adjust_spacing > 1) and check_expand_pars(f) then begin prev_char_p := v; sub_char_stretch(break_width[7])(character(v)); sub_char_shrink(break_width[8])(character(v)); end; @z @x [841] - font expansion break_width[1]:=@|break_width[1]- char_width(f)(char_info(f)(character(lig_char(v)))); @y break_width[1]:=@|break_width[1]- char_width(f)(char_info(f)(character(lig_char(v)))); if (pdf_adjust_spacing > 1) and check_expand_pars(f) then begin prev_char_p := v; sub_char_stretch(break_width[7])(character(lig_char(v))); sub_char_shrink(break_width[8])(character(lig_char(v))); end; @z @x [841] - font expansion hlist_node,vlist_node,rule_node,kern_node: break_width[1]:=break_width[1]-width(v); @y hlist_node,vlist_node,rule_node,kern_node: begin break_width[1]:=break_width[1]-width(v); if (type(v) = kern_node) and (pdf_adjust_spacing > 1) and (subtype(v) = normal) then begin sub_kern_stretch(break_width[7])(v); sub_kern_shrink(break_width[8])(v); end; end; @z @x [842] - font expansion break_width[1]:=@|break_width[1]+char_width(f)(char_info(f)(character(s))); @y break_width[1]:=@|break_width[1]+char_width(f)(char_info(f)(character(s))); if (pdf_adjust_spacing > 1) and check_expand_pars(f) then begin prev_char_p := s; add_char_stretch(break_width[7])(character(s)); add_char_shrink(break_width[8])(character(s)); end; @z @x [842] - font expansion break_width[1]:=break_width[1]+ char_width(f)(char_info(f)(character(lig_char(s)))); @y break_width[1]:=break_width[1]+ char_width(f)(char_info(f)(character(lig_char(s)))); if (pdf_adjust_spacing > 1) and check_expand_pars(f) then begin prev_char_p := s; add_char_stretch(break_width[7])(character(lig_char(s))); add_char_shrink(break_width[8])(character(lig_char(s))); end; @z @x [842] - font expansion hlist_node,vlist_node,rule_node,kern_node: break_width[1]:=break_width[1]+width(s); @y hlist_node,vlist_node,rule_node,kern_node: begin break_width[1]:=break_width[1]+width(s); if (type(s) = kern_node) and (pdf_adjust_spacing > 1) and (subtype(s) = normal) then begin add_kern_stretch(break_width[7])(s); add_kern_shrink(break_width[8])(s); end; end; @z @x [843] - font expansion begin do_all_six(convert_to_break_width); @y begin do_all_eight(convert_to_break_width); @z @x [843] - font expansion begin do_all_six(store_break_width); @y begin do_all_eight(store_break_width); @z @x [843] - font expansion do_all_six(new_delta_to_break_width); @y do_all_eight(new_delta_to_break_width); @z @x [844] - font expansion do_all_six(new_delta_from_break_width); @y do_all_eight(new_delta_from_break_width); @z @x [851] - font expansion, margin kerning shortfall:=line_width-cur_active_width[1]; {we're this much too short} @y shortfall:=line_width-cur_active_width[1]; {we're this much too short} {| if pdf_output > 2 then begin print_ln; if (r <> null) and (break_node(r) <> null) then short_display_n(cur_break(break_node(r)), 5); print_ln; short_display_n(cur_p, 5); print_ln; end; |} if pdf_protrude_chars > 1 then shortfall := shortfall + total_pw(r, cur_p); if (pdf_adjust_spacing > 1) and (shortfall <> 0) then begin margin_kern_stretch := 0; margin_kern_shrink := 0; if pdf_protrude_chars > 1 then @; if (shortfall > 0) and ((total_font_stretch + margin_kern_stretch) > 0) then begin if (total_font_stretch + margin_kern_stretch) > shortfall then shortfall := ((total_font_stretch + margin_kern_stretch) div (max_stretch_ratio div cur_font_step)) div 2 else shortfall := shortfall - (total_font_stretch + margin_kern_stretch); end else if (shortfall < 0) and ((total_font_shrink + margin_kern_shrink) > 0) then begin if (total_font_shrink + margin_kern_shrink) > -shortfall then shortfall := -((total_font_shrink + margin_kern_shrink) div (max_shrink_ratio div cur_font_step)) div 2 else shortfall := shortfall + (total_font_shrink + margin_kern_shrink); end; end; @z @x [860] - font expansion begin do_all_six(downdate_width); @y begin do_all_eight(downdate_width); @z @x [860] - font expansion begin do_all_six(update_width); do_all_six(combine_two_deltas); @y begin do_all_eight(update_width); do_all_eight(combine_two_deltas); @z @x [861] - font expansion begin do_all_six(update_active); do_all_six(copy_to_cur_active); @y begin do_all_eight(update_active); do_all_eight(copy_to_cur_active); @z @x [862] - margin kerning, avoiding overfull boxes @!auto_breaking:boolean; {is node |cur_p| outside a formula?} @!prev_p:pointer; {helps to determine when glue nodes are breakpoints} @y @z @x [863] - margin kerning, avoiding overfull boxes while (cur_p<>null)and(link(active)<>last_active) do @y prev_char_p := null; prev_legal := null; rejected_cur_p := null; try_prev_break := false; before_rejected_cur_p := false; first_p := cur_p; {to access the first node of paragraph as the first active node has |break_node=null|} while (cur_p<>null)and(link(active)<>last_active) do @z @x [864] - font expansion do_all_six(store_background);@/ @y do_all_eight(store_background);@/ @z @x [666] - font expansion else act_width:=act_width+width(cur_p); @y else begin act_width:=act_width+width(cur_p); if (pdf_adjust_spacing > 1) and (subtype(cur_p) = normal) then begin add_kern_stretch(active_width[7])(cur_p); add_kern_shrink(active_width[8])(cur_p); end; end; @z @x [866] - font expansion act_width:=act_width+char_width(f)(char_info(f)(character(lig_char(cur_p)))); @y act_width:=act_width+char_width(f)(char_info(f)(character(lig_char(cur_p)))); if (pdf_adjust_spacing > 1) and check_expand_pars(f) then begin prev_char_p := cur_p; add_char_stretch(active_width[7])(character(lig_char(cur_p))); add_char_shrink(active_width[8])(character(lig_char(cur_p))); end; @z @x [867] - font expansion act_width:=act_width+char_width(f)(char_info(f)(character(cur_p))); @y act_width:=act_width+char_width(f)(char_info(f)(character(cur_p))); if (pdf_adjust_spacing > 1) and check_expand_pars(f) then begin prev_char_p := cur_p; add_char_stretch(active_width[7])(character(cur_p)); add_char_shrink(active_width[8])(character(cur_p)); end; @z @x [869] - font expansion begin s:=pre_break(cur_p); disc_width:=0; @y begin s:=pre_break(cur_p); do_one_seven_eight(reset_disc_width); @z @x [869] - font expansion act_width:=act_width+disc_width; try_break(hyphen_penalty,hyphenated); act_width:=act_width-disc_width; @y do_one_seven_eight(add_disc_width_to_active_width); try_break(hyphen_penalty,hyphenated); do_one_seven_eight(sub_disc_width_from_active_width); @z @x [870] - font expansion disc_width:=disc_width+char_width(f)(char_info(f)(character(s))); @y disc_width[1]:=disc_width[1]+char_width(f)(char_info(f)(character(s))); if (pdf_adjust_spacing > 1) and check_expand_pars(f) then begin prev_char_p := s; add_char_stretch(disc_width[7])(character(s)); add_char_shrink(disc_width[8])(character(s)); end; @z @x [870] - font expansion disc_width:=disc_width+ char_width(f)(char_info(f)(character(lig_char(s)))); @y disc_width[1]:=disc_width[1]+ char_width(f)(char_info(f)(character(lig_char(s)))); if (pdf_adjust_spacing > 1) and check_expand_pars(f) then begin prev_char_p := s; add_char_stretch(disc_width[7])(character(lig_char(s))); add_char_shrink(disc_width[8])(character(lig_char(s))); end; @z @x [870] - font expansion hlist_node,vlist_node,rule_node,kern_node: disc_width:=disc_width+width(s); @y hlist_node,vlist_node,rule_node,kern_node: begin disc_width[1]:=disc_width[1]+width(s); if (type(s) = kern_node) and (pdf_adjust_spacing > 1) and (subtype(s) = normal) then begin add_kern_stretch(disc_width[7])(s); add_kern_shrink(disc_width[8])(s); end; end; @z @x [871] - font expansion act_width:=act_width+char_width(f)(char_info(f)(character(s))); @y act_width:=act_width+char_width(f)(char_info(f)(character(s))); if (pdf_adjust_spacing > 1) and check_expand_pars(f) then begin prev_char_p := s; add_char_stretch(active_width[7])(character(s)); add_char_shrink(active_width[8])(character(s)); end; @z @x [871] - font expansion act_width:=act_width+ char_width(f)(char_info(f)(character(lig_char(s)))); @y act_width:=act_width+ char_width(f)(char_info(f)(character(lig_char(s)))); if (pdf_adjust_spacing > 1) and check_expand_pars(f) then begin prev_char_p := s; add_char_stretch(active_width[7])(character(lig_char(s))); add_char_shrink(active_width[8])(character(lig_char(s))); end; @z @x [871] - font expansion hlist_node,vlist_node,rule_node,kern_node: act_width:=act_width+width(s); @y hlist_node,vlist_node,rule_node,kern_node: begin act_width:=act_width+width(s); if (type(s) = kern_node) and (pdf_adjust_spacing > 1) and (subtype(s) = normal) then begin add_kern_stretch(active_width[7])(s); add_kern_shrink(active_width[8])(s); end; end; @z @x [877] - margin kerning var q,@!r,@!s:pointer; {temporary registers for list manipulation} @y var q,@!r,@!s:pointer; {temporary registers for list manipulation} p, k: pointer; w: scaled; glue_break: boolean; {was a break at glue?} ptmp: pointer; @z @x [881] - margin kerning q:=cur_break(cur_p); disc_break:=false; post_disc_break:=false; @y q:=cur_break(cur_p); disc_break:=false; post_disc_break:=false; glue_break := false; @z @x [881] - margin kerning subtype(q):=right_skip_code+1; add_glue_ref(right_skip); goto done; @y subtype(q):=right_skip_code+1; add_glue_ref(right_skip); glue_break := true; goto done; @z @x [881] - margin kerning @; done: @y done: {at this point |q| is the rightmost breakpoint; the only exception is the case of a discretionary break with non-empty |pre_break|, then |q| has been changed to the last node of the |pre_break| list} if pdf_protrude_chars > 0 then begin if disc_break and (is_char_node(q) or (type(q) <> disc_node)) {|q| has been reset to the last node of |pre_break|} then begin p := q; ptmp := p; end else begin p := prev_rightmost(temp_head, q); {get |link(p) = q|} ptmp := p; p := find_protchar_right(temp_head, p); end; {| short_display_n(p, 1); print_ln; |} w := right_pw(p); if w <> 0 then {we have found a marginal kern, append it after |ptmp|} begin k := new_margin_kern(-w, last_rightmost_char, right_side); link(k) := link(ptmp); link(ptmp) := k; if (ptmp = q) then q := link(q); end; end; {if |q| was not a breakpoint at glue and has been reset to |rightskip| then we append |rightskip| after |q| now} if not glue_break then begin @; end; @z @x [887] - margin kerning if left_skip<>zero_glue then @y {at this point |q| is the leftmost node; all discardable nodes have been discarded} if pdf_protrude_chars > 0 then begin p := q; p := find_protchar_left(p, false); {no more discardables} w := left_pw(p); if w <> 0 then begin k := new_margin_kern(-w, last_leftmost_char, left_side); link(k) := q; q := k; end; end; if left_skip<>zero_glue then @z @x [889] - font expansion, pre vadjust just_box:=hpack(q,cur_width,exactly); @y if pdf_adjust_spacing > 0 then just_box := hpack(q, cur_width, cal_expand_ratio) else just_box := hpack(q, cur_width, exactly); @z @x [1110] - margin kerning var p:pointer; {the box} @y var p:pointer; {the box} r: pointer; {to remove marginal kern nodes} @z @x [1110] - margin kerning while link(tail)<>null do tail:=link(tail); @y while link(tail) <> null do begin r := link(tail); if not is_char_node(r) and (type(r) = margin_kern_node) then begin link(tail) := link(r); free_avail(margin_char(r)); free_node(r, margin_kern_node_size); end; tail:=link(tail); end; @z @x [1147] - margin kerning ligature_node:@; @y ligature_node:@; margin_kern_node: d:=width(p); @z @x [1253] - font expansion assign_font_int: begin n:=cur_chr; scan_font_ident; f:=cur_val; scan_optional_equals; scan_int; if n=0 then hyphen_char[f]:=cur_val@+else skew_char[f]:=cur_val; end; @y assign_font_int: begin n:=cur_chr; scan_font_ident; f:=cur_val; if n < lp_code_base then begin scan_optional_equals; scan_int; if n=0 then hyphen_char[f]:=cur_val@+else skew_char[f]:=cur_val; end else begin scan_char_num; p := cur_val; scan_optional_equals; scan_int; case n of lp_code_base: set_lp_code(f, p, cur_val); rp_code_base: set_rp_code(f, p, cur_val); ef_code_base: set_ef_code(f, p, cur_val); end; end; end; @z @x [1254] - font expansion primitive("skewchar",assign_font_int,1); @!@:skew_char_}{\.{\\skewchar} primitive@> @y primitive("skewchar",assign_font_int,1); @!@:skew_char_}{\.{\\skewchar} primitive@> primitive("lpcode",assign_font_int,lp_code_base); @!@:lp_code_}{\.{\\lpcode} primitive@> primitive("rpcode",assign_font_int,rp_code_base); @!@:rp_code_}{\.{\\rpcode} primitive@> primitive("efcode",assign_font_int,ef_code_base); @!@:ef_code_}{\.{\\efcode} primitive@> @z @x [1255] - font expansion assign_font_int: if chr_code=0 then print_esc("hyphenchar") else print_esc("skewchar"); @y assign_font_int: case chr_code of 0: print_esc("hyphenchar"); 1: print_esc("skewchar"); lp_code_base: print_esc("lpcode"); rp_code_base: print_esc("rpcode"); ef_code_base: print_esc("efcode"); endcases; @z @x [1344] @d pdftex_last_extension_code == pdftex_first_extension_code + 27 @y @d pdf_font_expand_code == pdftex_first_extension_code + 28 @d pdftex_last_extension_code == pdftex_first_extension_code + 28 @z @x [1344] primitive("setlanguage",extension,set_language_code);@/ @!@:set_language_}{\.{\\setlanguage} primitive@> @y primitive("setlanguage",extension,set_language_code);@/ @!@:set_language_}{\.{\\setlanguage} primitive@> primitive("pdffontexpand",extension,pdf_font_expand_code);@/ @!@:pdf_font_expand_}{\.{\\pdffontexpand} primitive@> @z @x [1346] immediate_code:print_esc("immediate"); set_language_code:print_esc("setlanguage"); @y immediate_code:print_esc("immediate"); set_language_code:print_esc("setlanguage"); pdf_font_expand_code: print_esc("pdffontexpand"); @z @x [1348] set_language_code:@; @y set_language_code:@; pdf_font_expand_code: @; @z @x [1354] @= begin new_whatsit(special_node,write_node_size); write_stream(tail):=null; p:=scan_toks(false,true); write_tokens(tail):=def_ref; end @y @= begin new_whatsit(special_node,write_node_size); write_stream(tail):=null; p:=scan_toks(false,true); write_tokens(tail):=def_ref; end @ @= read_expand_font @z @x [15??] @= @y @= function prev_rightmost(s, e: pointer): pointer; {finds the node preceding the rightmost node |e|; |s| is some node before |e|} var p: pointer; begin prev_rightmost := null; p := s; if p = null then return; while link(p) <> e do begin p := link(p); if p = null then return; end; prev_rightmost := p; end; @z