Patch title: Release 83 bulk changes
Abstract:
File: /pliant/graphic/filter/escp2.pli
Key:
    Removed line
    Added line
   
# Copyright  Hubert Tonneau  hubert.tonneau@pliant.cx
#
# Writing this driver was possible only thanks to the great 
# Robert L Krawitz to gather and document detailed informati
# Epson inkjet printers.


# Copyright  Hubert Tonneau  hubert.tonneau@pliant.cx
#
# Writing this driver was possible only thanks to the great 
# Robert L Krawitz to gather and document detailed informati
# Epson inkjet printers.



#-----------------------------------------------------------
# dithering matrix



method f open s options h -> status
  arg_rw ImageWriteFilterEscp2 f ; arg_rw Stream s ; arg Str
  # send printer setup commands, and copy the values we will
  if h:gamut:dimension<>1 and h:gamut:dimension<>3 and h:gam
    return failure:"Only black and white or CMY or CMYK imag
  var Int dpi_x dpi_y base_unit page_unit
  var Int heads jets dot_size bpc dot_levels space_x space_y
  var Int dpi_shift ; var Array:Int shift
  var Float page_x := undefined ; var Float page_y := undefi
  var Str command
  dpi_x := options option "escp2_dpi_x" Int (cast h:size_x/(
  dpi_y := options option "escp2_dpi_y" Int (cast h:size_y/(
  if (dpi_x%360<>0 or dpi_y%360<>0) and not (options option 
    return (failure "Incorrect resolution "+string:dpi_x+" x
  base_unit := options option "escp2_base_unit" Int (shunt d
  page_unit := options option "escp2_page_unit" Int 720
  var Str model := options option "model" Str
  if model=""
    return failure:"You must specify the printer model"
  if model="Epson C80" or model="Epson C82"
    heads := 0Fh
    jets := shunt h:gamut:dimension=1 180 60
    dot_size := 12h
    if h:gamut:dimension<>1
      dpi_shift := 180 ; shift += 120 ; shift += 60 ; shift 
    space_x := dpi_x\360
    space_y := dpi_y\180
    page_x := 210
    page_y := 297
    command := ""
  eif model="Epson 750"
    heads := 3Fh
    jets := 48
    dot_size := 10h
    space_x := dpi_x\360
    space_y := dpi_y\120
    page_x := 210
    page_y := 297
    command := ""
  eif model="Epson 1280" or model="Epson 1290"
    heads := 3Fh
    jets := 48
    dot_size := 10h
    space_x := dpi_x\360
    space_y := dpi_y\120
    page_x := 13*25.4
    page_y := 19*25.4
    command := "coord4 zero_margin roll"
  eif model="Epson 2100" or model="Epson 2200"
    heads := 0BFh
    jets := 96
    dot_size := 10h
    if h:gamut:dimension<>1
      dpi_shift := 360 ; shift += 0 ; shift += 0 ; shift += 
    space_x := dpi_x\360
    space_y := dpi_y\180
    page_x := 13*25.4
    page_y := 19*25.4
    command := "coord4 roll"
  eif model="Epson 3000" # does not work yet
    heads := 0Fh
    jets := shunt h:gamut:dimension=1 128 64
    dot_size := 1
    space_x := dpi_x\360
    space_y := dpi_y\180
    page_x := 17*25.4
    page_y := 44*25.4
    command := "old"
  eif model="Epson 7600" or model="Epson 9600" or model="Eps
    heads := shunt model="Epson 10600" 03Fh 0BFh
    jets := 1
    dot_size := 10h
    space_x := 1
    space_y := 1
#-----------------------------------------------------------
# dithering matrix



method f open s options h -> status
  arg_rw ImageWriteFilterEscp2 f ; arg_rw Stream s ; arg Str
  # send printer setup commands, and copy the values we will
  if h:gamut:dimension<>1 and h:gamut:dimension<>3 and h:gam
    return failure:"Only black and white or CMY or CMYK imag
  var Int dpi_x dpi_y base_unit page_unit
  var Int heads jets dot_size bpc dot_levels space_x space_y
  var Int dpi_shift ; var Array:Int shift
  var Float page_x := undefined ; var Float page_y := undefi
  var Str command
  dpi_x := options option "escp2_dpi_x" Int (cast h:size_x/(
  dpi_y := options option "escp2_dpi_y" Int (cast h:size_y/(
  if (dpi_x%360<>0 or dpi_y%360<>0) and not (options option 
    return (failure "Incorrect resolution "+string:dpi_x+" x
  base_unit := options option "escp2_base_unit" Int (shunt d
  page_unit := options option "escp2_page_unit" Int 720
  var Str model := options option "model" Str
  if model=""
    return failure:"You must specify the printer model"
  if model="Epson C80" or model="Epson C82"
    heads := 0Fh
    jets := shunt h:gamut:dimension=1 180 60
    dot_size := 12h
    if h:gamut:dimension<>1
      dpi_shift := 180 ; shift += 120 ; shift += 60 ; shift 
    space_x := dpi_x\360
    space_y := dpi_y\180
    page_x := 210
    page_y := 297
    command := ""
  eif model="Epson 750"
    heads := 3Fh
    jets := 48
    dot_size := 10h
    space_x := dpi_x\360
    space_y := dpi_y\120
    page_x := 210
    page_y := 297
    command := ""
  eif model="Epson 1280" or model="Epson 1290"
    heads := 3Fh
    jets := 48
    dot_size := 10h
    space_x := dpi_x\360
    space_y := dpi_y\120
    page_x := 13*25.4
    page_y := 19*25.4
    command := "coord4 zero_margin roll"
  eif model="Epson 2100" or model="Epson 2200"
    heads := 0BFh
    jets := 96
    dot_size := 10h
    if h:gamut:dimension<>1
      dpi_shift := 360 ; shift += 0 ; shift += 0 ; shift += 
    space_x := dpi_x\360
    space_y := dpi_y\180
    page_x := 13*25.4
    page_y := 19*25.4
    command := "coord4 roll"
  eif model="Epson 3000" # does not work yet
    heads := 0Fh
    jets := shunt h:gamut:dimension=1 128 64
    dot_size := 1
    space_x := dpi_x\360
    space_y := dpi_y\180
    page_x := 17*25.4
    page_y := 44*25.4
    command := "old"
  eif model="Epson 7600" or model="Epson 9600" or model="Eps
    heads := shunt model="Epson 10600" 03Fh 0BFh
    jets := 1
    dot_size := 10h
    space_x := 1
    space_y := 1
    command := "coord4 roll"
    command := "coord4 roll cutter"
  else
    return (failure "'"+model+"' is not a valid printer mode
  command := options option "escp2_command" Str command
  var CBool old := command option "old"
  var CBool coord4 := command option "coord4"
  var CBool job_ticket := shunt (options option "escp2_job_t
  heads := options option "escp2_heads" Int heads
  jets := options option "escp2_jets" Int jets
  dot_size := options option "escp2_dot_size" Int dot_size
  space_x := options option "escp2_space_x" Int space_x
  space_y := options option "escp2_space_y" Int space_y
  bpc := options option "escp2_bpc" Int (shunt old 1 2)
  dot_levels := options option "escp2_dot_levels" Int 2^bpc-
  page_x := options option "escp2_page_x" Float page_x
  page_y := options option "escp2_page_y" Float page_y
  if ((options (options option_position "page" options:len) 
    page_x := px ; page_y := py
  if not ((options (options option_position "offset" 0) opti
    offset_x := 0 ; offset_y := 0
  if job_ticket
    s writechars "[0][0][0]"
    s writechars escape+character:1+"@EJL 1284.4[lf]@EJL    
    s writechars escape+"@"
  s writechars escape+"@"
  if job_ticket
    s writechars (escp2 "R" character:0+"REMOTE1")
  else
    return (failure "'"+model+"' is not a valid printer mode
  command := options option "escp2_command" Str command
  var CBool old := command option "old"
  var CBool coord4 := command option "coord4"
  var CBool job_ticket := shunt (options option "escp2_job_t
  heads := options option "escp2_heads" Int heads
  jets := options option "escp2_jets" Int jets
  dot_size := options option "escp2_dot_size" Int dot_size
  space_x := options option "escp2_space_x" Int space_x
  space_y := options option "escp2_space_y" Int space_y
  bpc := options option "escp2_bpc" Int (shunt old 1 2)
  dot_levels := options option "escp2_dot_levels" Int 2^bpc-
  page_x := options option "escp2_page_x" Float page_x
  page_y := options option "escp2_page_y" Float page_y
  if ((options (options option_position "page" options:len) 
    page_x := px ; page_y := py
  if not ((options (options option_position "offset" 0) opti
    offset_x := 0 ; offset_y := 0
  if job_ticket
    s writechars "[0][0][0]"
    s writechars escape+character:1+"@EJL 1284.4[lf]@EJL    
    s writechars escape+"@"
  s writechars escape+"@"
  if job_ticket
    s writechars (escp2 "R" character:0+"REMOTE1")
    # s writechars (remote "PM" "[0][0]") # unknown
    s writechars (remote "SN" "[0][0]"+character:0) # paper 
    if (command option "duplex") and ( (options option "fron
    if (options option "escp2_ink")
      s writechars (remote "IK" "[0]"+character:(options option "escp2_ink" Int 0))
    if (options option "escp2_paper")
      s writechars (remote "SN" "[0][0]"+character:(options option "escp2_paper" Int 0)) # paper 0=default, 1=plain, 3=glossy photo, 5=plain (fast load), 6=heavyweight matte, 7=coated, 8=photo
    if (options option "escp2_thickness")
      s writechars (remote "PH" "[0]"+character:(cast (options option "escp2_thickness" Float 0)*10 Int))
    if (command option "duplex") and ( (options option "front") or (options option "back"))
      s writechars (remote "SN" "[0]"+character:7+character:
    if (command option "zero_margin")
      s writechars (remote "FP" "[0]"+character:B0h+characte
      s writechars (remote "SN" "[0]"+character:7+character:
    if (command option "zero_margin")
      s writechars (remote "FP" "[0]"+character:B0h+characte
    # s writechars (remote "IR" "[0]"+character:3) # unkown
    if (command+" "+options option "roll")
      s writechars (remote "EX"  "[0][0][0][0]"+character:5+
    if (command+" "+options option "roll")
      s writechars (remote "EX"  "[0][0][0][0]"+character:5+
    if (command option "cutter")
      s writechars (remote "AC" "[0]"+character:(shunt (options option "cutter") 1 0)) # cutter
    if (options option "escp2_load")
      s writechars (remote "SN" "[0]"+character:2+character:(options option "escp2_load" Int 0)) # 0=normal, 1=fast, 2=slow
    if (options option "escp2_dry")
      s writechars (remote "DR" "[0][0]"+num2:(cast (options option "escp_dry" Float 0)*1000 Int)) # dry time between scan lines
    if (options option "escp2_pause")
      s writechars (remote "DR" "[0]"+character:1+num2:(cast (options option "escp_dry" Float 0) Int)) # dry time between page
    s writechars escape+"[0][0][0]"
  s writechars (escp2 "G" character:1) # graphic mode
  if not old
    s writechars (escp2 "U" (num1 base_unit\page_unit)+(num1
  else
    s writechars (escp2 "U" (num1 3600\dpi_y))
  s writechars (escp2 "K" character:0+character:2) # color m
  s writechars (escp2 "i" character:(options option "escp2_m
  s writechars escape+"U"+character:(shunt (options option "
  if (options option "escp2_head_speed")
    s writechars (escp2 "s" character:(options option "escp2
  s writechars (escp2 "e" character:0+character:dot_size) # 
  if page_y=defined
    s writechars (escp2 "C" (num2_or_4 coord4 (cast page_y/2
    s writechars (escp2 "c" (num2_or_4 coord4 0)+(num2_or_4 
  if page_x=defined and page_y=defined and not old
    s writechars (escp2 "S" num4:(cast page_x/25.4*page_unit
  if not old
    s writechars (escp2 "D" num2:14400+(num1 14400\dpi_y*spa
  f stream :> s
  f:input_line size := h size_y
  for (var Int y) 0 f:input_line:size-1
    f:input_line y := null
  f dim := h:gamut dimension
  f size_x := h size_x
  f size_y := h size_y
  f input_y := 0 ; f input_line_size := h line_size
  f dpi_x := dpi_x
  f dpi_y := dpi_y
  f space_x := space_x
  f space_y := space_y
  f heads := heads
  f jets := jets
  f dot_size := dot_size
  f dot_levels := dot_levels
  f bpc := bpc
  f:shift size := heads_count
  var Int sm := 0
  for (var Int i) 0 heads_count-1
    if i<shift:size
      f:shift i := shift:i*dpi_y\dpi_shift
      sm := max sm f:shift:i
    else
      f:shift i := 0
  f delta := jets*space_y+sm
  f old := old
  f coord4 := coord4
  f job_ticket := job_ticket
  f:pass size := h:size_y+2*f:delta
  for (var Int y) 0 f:pass:size-1
    f:pass y := 0
  f output_line_size := (h:size_x\space_x*bpc+7)\8
  f output_lines := memory_allocate f:output_line_size*jets 
  f output_y := -(f delta)
  f left := cast offset_x/25.4*dpi_x Int
  if top_enhancement
    f top := cast offset_y/25.4*dpi_y Int
  else
    f top := max (cast offset_y/25.4*dpi_y Int) f:delta
  f buffer := memory_allocate 2*f:output_line_size*jets+4 ad
  for (var Int i) 0 heads_count-1
    if (heads .and. 2^i)<>0
      var Pointer:Escp2Channel ch :> f:head i
      if i<4
        if (ch:dither load "file:/pliant_data/pliant/graphic
          var Int m1 := options option "escp2_matrix_mini" I
          var Int m2 := options option "escp2_matrix_maxi" I
          part shake "select dithering pattern size for chan
            part shake_x
              var Int sx := m1+(random m2-m1+1)
              if not is_prime:sx
                restart shake_x
            part shake_y
              var Int sy := m1+(random m2-m1+1)
              if not is_prime:sy
                restart shake_y
            for (var Int j) 0 i-1
              if f:head:j:dither:size_x=sx or f:head:j:dithe
                restart shake
          part matrix "compute "+string:sx+" x "+string:sy+"
            ch dither := random_matrix sx sy 64 16 (shunt dp
          ch:dither save "file:/pliant_data/pliant/graphic/d
      var Float middle := options option "escp2_middle"+(str
      var Float limit := options option "escp2_limit"+(strin
      var Str bend1 := string (options option "escp2_bend"+(
      var Str ident := shunt (options option "escp2_dot"+(st
      var Str opt := shunt (options option ident) options bp
      var CBool light := (heads .and. 2^(i%4+4))<>0
      var Array:Int dot ; var Array:Float density ; var Arra
      dot size := 0 ; density size := 0 ; bend size := 0
      dot += 0 ; density += 0 ; bend += 0
      var Int j := 0
      while (opt option_position ident j -1)>=0
        if not ((opt (opt option_position ident j opt:len) o
          return (failure "Icorrect '"+ident+"' parameter")
        if light or dot0>=0
          dot += shunt i<4 and dot0>0 dot0 i>=4 and dot0<0 -
        j += 1
      for (var Int j) 0 255
        var Float d := j/255
        d := exposure d middle
        d *= limit
        var Int k := 0
        while k+2<density:size and d>=(density k+1)
          k += 1
        var Pointer:Escp2Level l :> ch:level j
        l dot0 := dot k
        l dot1 := dot k+1
        l remain := cast (exposure (d-density:k)/(density:(k
  status := success



method f close -> status
  arg_rw ImageWriteFilterEscp2 f ; arg ExtendedStatus status
  # send printer termination commands
  implicit f
    for (var Int y) 0 size_y-1
      check (pass y+delta)=2^space_x-1
      if f:input_line:y<>null
        memory_free f:input_line:y
  var Pointer:Stream s :> f stream
  s writechars escape+"@"
  s writechars character:0Ch
  if f:job_ticket
    s writechars (escp2 "R" character:0+"REMOTE1")
    s writechars escape+"[0][0][0]"
  s writechars (escp2 "G" character:1) # graphic mode
  if not old
    s writechars (escp2 "U" (num1 base_unit\page_unit)+(num1
  else
    s writechars (escp2 "U" (num1 3600\dpi_y))
  s writechars (escp2 "K" character:0+character:2) # color m
  s writechars (escp2 "i" character:(options option "escp2_m
  s writechars escape+"U"+character:(shunt (options option "
  if (options option "escp2_head_speed")
    s writechars (escp2 "s" character:(options option "escp2
  s writechars (escp2 "e" character:0+character:dot_size) # 
  if page_y=defined
    s writechars (escp2 "C" (num2_or_4 coord4 (cast page_y/2
    s writechars (escp2 "c" (num2_or_4 coord4 0)+(num2_or_4 
  if page_x=defined and page_y=defined and not old
    s writechars (escp2 "S" num4:(cast page_x/25.4*page_unit
  if not old
    s writechars (escp2 "D" num2:14400+(num1 14400\dpi_y*spa
  f stream :> s
  f:input_line size := h size_y
  for (var Int y) 0 f:input_line:size-1
    f:input_line y := null
  f dim := h:gamut dimension
  f size_x := h size_x
  f size_y := h size_y
  f input_y := 0 ; f input_line_size := h line_size
  f dpi_x := dpi_x
  f dpi_y := dpi_y
  f space_x := space_x
  f space_y := space_y
  f heads := heads
  f jets := jets
  f dot_size := dot_size
  f dot_levels := dot_levels
  f bpc := bpc
  f:shift size := heads_count
  var Int sm := 0
  for (var Int i) 0 heads_count-1
    if i<shift:size
      f:shift i := shift:i*dpi_y\dpi_shift
      sm := max sm f:shift:i
    else
      f:shift i := 0
  f delta := jets*space_y+sm
  f old := old
  f coord4 := coord4
  f job_ticket := job_ticket
  f:pass size := h:size_y+2*f:delta
  for (var Int y) 0 f:pass:size-1
    f:pass y := 0
  f output_line_size := (h:size_x\space_x*bpc+7)\8
  f output_lines := memory_allocate f:output_line_size*jets 
  f output_y := -(f delta)
  f left := cast offset_x/25.4*dpi_x Int
  if top_enhancement
    f top := cast offset_y/25.4*dpi_y Int
  else
    f top := max (cast offset_y/25.4*dpi_y Int) f:delta
  f buffer := memory_allocate 2*f:output_line_size*jets+4 ad
  for (var Int i) 0 heads_count-1
    if (heads .and. 2^i)<>0
      var Pointer:Escp2Channel ch :> f:head i
      if i<4
        if (ch:dither load "file:/pliant_data/pliant/graphic
          var Int m1 := options option "escp2_matrix_mini" I
          var Int m2 := options option "escp2_matrix_maxi" I
          part shake "select dithering pattern size for chan
            part shake_x
              var Int sx := m1+(random m2-m1+1)
              if not is_prime:sx
                restart shake_x
            part shake_y
              var Int sy := m1+(random m2-m1+1)
              if not is_prime:sy
                restart shake_y
            for (var Int j) 0 i-1
              if f:head:j:dither:size_x=sx or f:head:j:dithe
                restart shake
          part matrix "compute "+string:sx+" x "+string:sy+"
            ch dither := random_matrix sx sy 64 16 (shunt dp
          ch:dither save "file:/pliant_data/pliant/graphic/d
      var Float middle := options option "escp2_middle"+(str
      var Float limit := options option "escp2_limit"+(strin
      var Str bend1 := string (options option "escp2_bend"+(
      var Str ident := shunt (options option "escp2_dot"+(st
      var Str opt := shunt (options option ident) options bp
      var CBool light := (heads .and. 2^(i%4+4))<>0
      var Array:Int dot ; var Array:Float density ; var Arra
      dot size := 0 ; density size := 0 ; bend size := 0
      dot += 0 ; density += 0 ; bend += 0
      var Int j := 0
      while (opt option_position ident j -1)>=0
        if not ((opt (opt option_position ident j opt:len) o
          return (failure "Icorrect '"+ident+"' parameter")
        if light or dot0>=0
          dot += shunt i<4 and dot0>0 dot0 i>=4 and dot0<0 -
        j += 1
      for (var Int j) 0 255
        var Float d := j/255
        d := exposure d middle
        d *= limit
        var Int k := 0
        while k+2<density:size and d>=(density k+1)
          k += 1
        var Pointer:Escp2Level l :> ch:level j
        l dot0 := dot k
        l dot1 := dot k+1
        l remain := cast (exposure (d-density:k)/(density:(k
  status := success



method f close -> status
  arg_rw ImageWriteFilterEscp2 f ; arg ExtendedStatus status
  # send printer termination commands
  implicit f
    for (var Int y) 0 size_y-1
      check (pass y+delta)=2^space_x-1
      if f:input_line:y<>null
        memory_free f:input_line:y
  var Pointer:Stream s :> f stream
  s writechars escape+"@"
  s writechars character:0Ch
  if f:job_ticket
    s writechars (escp2 "R" character:0+"REMOTE1")
    s writechars (remote "IR" "[0]"+character:2)
    s writechars (remote "LD" "")
    s writechars (remote "LD" "")
    s writechars (remote "JE" "[0]")
    s writechars escape+"[0][0][0]"
  memory_free f:output_lines
  memory_free f:buffer
  if verbose
    console (repeat 60 " ")+"[cr]"
  status := success


image_record_filters ".escp2" Void ImageWriteFilterEscp2
export escp2_generator
    s writechars escape+"[0][0][0]"
  memory_free f:output_lines
  memory_free f:buffer
  if verbose
    console (repeat 60 " ")+"[cr]"
  status := success


image_record_filters ".escp2" Void ImageWriteFilterEscp2
export escp2_generator