;;; cl-pdf copyright 2002-2003 Marc Battyani see license.txt for the details
;;; You can reach me at marc.battyani@fractalconcept.com or marc@battyani.net
;;; The homepage of cl-pdf is here: http://www.fractalconcept.com/asp/html/cl-pdf.html

(in-package pdf)

(defvar *default-encoding* :win-ansi-encoding)

(defvar *encodings* (make-hash-table :test #'equal))

(defclass encoding ()
  ((name :accessor name :initform nil :initarg :name)
   (keyword-name :accessor keyword-name :initform nil :initarg :keyword-name)
   (standard-encoding :accessor standard-encoding :initform nil :initarg :standard-encoding)
   (char-names :accessor char-names :initform nil :initarg :char-names)
   (char-codes :accessor char-codes :initform (make-hash-table :test #'equal))))

(defmethod initialize-instance :after ((encoding encoding) &rest init-options &key &allow-other-keys)
  (unless (and (name encoding)(char-names encoding))
    (error "You must provide a name and the codes to char names array (256) when you create an encoding"))
  (unless (keyword-name encoding)
    (setf (keyword-name encoding)(intern (string-upcase (name encoding)) :keyword)))
  (setf (gethash encoding *encodings*) encoding
	(gethash (name encoding) *encodings*) encoding
	(gethash (keyword-name encoding) *encodings*) encoding)
  (loop with char-codes = (char-codes encoding)
	for char-name across (char-names encoding)
	for code from 0
	when char-name do (setf (gethash char-name char-codes) code)))

(defmethod make-dictionary ((encoding encoding) &key &allow-other-keys)
  (with-slots (base-encoding) encoding
    (make-instance 'dictionary
      :dict-values
      `(("/Type" . "/Encoding")
	("/Differences" . ,(compute-encoding-differences encoding nil))))))

(defmethod print-object ((self encoding) stream)
  (print-unreadable-object (self stream :identity t :type t)
    (format stream "~a" (name self))))

(defun get-encoding (encoding-designator)
  (gethash encoding-designator *encodings*))

(defun compute-encoding-differences (encoding &optional (from *standard-encoding*))
  (let ((differences (make-array 20 :fill-pointer 0 :adjustable t))
	(range-started nil))
    (if from
	(flet ((start-range (code)
		 (when (or (and code (not range-started))(and (not code) range-started))
		   (setf range-started code)
		   (when code (vector-push-extend code differences)))))
	  (loop with start-code = nil
		for standard-char-name across (char-names from)
		for char-name across (char-names encoding)
		for code from 0
		do
		(cond
		  ((and (not char-name) standard-char-name)
		   (start-range code) (vector-push-extend ".notdef" differences))
		  ((and char-name (not (equal char-name standard-char-name)))
		   (start-range code)
		   (vector-push-extend (add-/ char-name) differences))
		  (t (start-range nil)))))
	(full-encoding-differences encoding))
	differences))

;;; Just put all...
(defun full-encoding-differences (encoding)
  (let ((differences (make-array 20 :fill-pointer 0 :adjustable t)))
    (vector-push-extend 0 differences)
    (loop for char-name across (char-names encoding)
	  for code from 0
	  do (if char-name
		 (vector-push-extend (concatenate 'string "/" char-name) differences)
		 (vector-push-extend "/.notdef" differences)))
    differences))

(defvar *standard-encoding*
  (make-instance 'encoding :name "StandardEncoding" :keyword-name :standard-encoding
		 :standard-encoding t :char-names #(
nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil 
nil nil nil nil nil nil nil nil nil nil nil nil nil nil "space" 
"exclam" "quotedbl" "numbersign" "dollar" "percent" "ampersand" 
"quoteright" "parenleft" "parenright" "asterisk" "plus" "comma" 
"hyphen" "period" "slash" "zero" "one" "two" "three" "four" "five" 
"six" "seven" "eight" "nine" "colon" "semicolon" "less" "equal" 
"greater" "question" "at" "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" 
"L" "M" "N" "O" "P" "Q" "R" "S" "T" "U" "V" "W" "X" "Y" "Z" 
"bracketleft" "backslash" "bracketright" "asciicircum" "underscore" 
"quoteleft" "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" 
"p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z" "braceleft" "bar" 
"braceright" "asciitilde" nil nil nil nil nil nil nil nil nil nil nil 
nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil 
nil nil nil nil nil "exclamdown" "cent" "sterling" "fraction" "yen" 
"florin" "section" "currency" "quotesingle" "quotedblleft" 
"guillemotleft" "guilsinglleft" "guilsinglright" "fi" "fl" nil "endash" 
"dagger" "daggerdbl" "periodcentered" nil "paragraph" "bullet" 
"quotesinglbase" "quotedblbase" "quotedblright" "guillemotright" 
"ellipsis" "perthousand" nil "questiondown" nil "grave" "acute" 
"circumflex" "tilde" "macron" "breve" "dotaccent" "dieresis" nil "ring" 
"cedilla" nil "hungarumlaut" "ogonek" "caron" "emdash" nil nil nil nil 
nil nil nil nil nil nil nil nil nil nil nil nil "AE" nil "ordfeminine" 
nil nil nil nil "Lslash" "Oslash" "OE" "ordmasculine" nil nil nil nil 
nil "ae" nil nil nil "dotlessi" nil nil "lslash" "oslash" "oe" 
"germandbls" nil nil nil nil )))

(defvar *mac-roman-encoding*
  (make-instance 'encoding :name "MacRomanEncoding" :keyword-name :mac-roman-encoding
		 :standard-encoding t :char-names #(
nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil 
nil nil nil nil nil nil nil nil nil nil nil nil nil nil "space" 
"exclam" "quotedbl" "numbersign" "dollar" "percent" "ampersand" 
"quotesingle" "parenleft" "parenright" "asterisk" "plus" "comma" 
"hyphen" "period" "slash" "zero" "one" "two" "three" "four" "five" 
"six" "seven" "eight" "nine" "colon" "semicolon" "less" "equal" 
"greater" "question" "at" "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" 
"L" "M" "N" "O" "P" "Q" "R" "S" "T" "U" "V" "W" "X" "Y" "Z" 
"bracketleft" "backslash" "bracketright" "asciicircum" "underscore" 
"grave" "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" 
"q" "r" "s" "t" "u" "v" "w" "x" "y" "z" "braceleft" "bar" "braceright" 
"asciitilde" nil "Adieresis" "Aring" "Ccedilla" "Eacute" "Ntilde" 
"Odieresis" "Udieresis" "aacute" "agrave" "acircumflex" "adieresis" 
"atilde" "aring" "ccedilla" "eacute" "egrave" "ecircumflex" "edieresis" 
"iacute" "igrave" "icircumflex" "idieresis" "ntilde" "oacute" "ograve" 
"ocircumflex" "odieresis" "otilde" "uacute" "ugrave" "ucircumflex" 
"udieresis" "dagger" "degree" "cent" "sterling" "section" "bullet" 
"paragraph" "germandbls" "registered" "copyright" "trademark" "acute" 
"dieresis" nil "AE" "Oslash" nil "plusminus" nil nil "yen" "mu" nil nil 
nil nil nil "ordfeminine" "ordmasculine" nil "ae" "oslash" 
"questiondown" "exclamdown" "logicalnot" nil "florin" nil nil 
"guillemotleft" "guillemotright" "ellipsis" "space" "Agrave" "Atilde" 
"Otilde" "OE" "oe" "endash" "emdash" "quotedblleft" "quotedblright" 
"quoteleft" "quoteright" "divide" nil "ydieresis" "Ydieresis" 
"fraction" "currency" "guilsinglleft" "guilsinglright" "fi" "fl" 
"daggerdbl" "periodcentered" "quotesinglbase" "quotedblbase" 
"perthousand" "Acircumflex" "Ecircumflex" "Aacute" "Edieresis" "Egrave" 
"Iacute" "Icircumflex" "Idieresis" "Igrave" "Oacute" "Ocircumflex" nil 
"Ograve" "Uacute" "Ucircumflex" "Ugrave" "dotlessi" "circumflex" 
"tilde" "macron" "breve" "dotaccent" "ring" "cedilla" "hungarumlaut" 
"ogonek" "caron" )))

(defvar *win-ansi-encoding*
  (make-instance 'encoding :name "WinAnsiEncoding" :keyword-name :win-ansi-encoding
		 :standard-encoding t :char-names #(
nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil 
nil nil nil nil nil nil nil nil nil nil nil nil nil nil "space" 
"exclam" "quotedbl" "numbersign" "dollar" "percent" "ampersand" 
"quotesingle" "parenleft" "parenright" "asterisk" "plus" "comma" 
"hyphen" "period" "slash" "zero" "one" "two" "three" "four" "five" 
"six" "seven" "eight" "nine" "colon" "semicolon" "less" "equal" 
"greater" "question" "at" "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" 
"L" "M" "N" "O" "P" "Q" "R" "S" "T" "U" "V" "W" "X" "Y" "Z" 
"bracketleft" "backslash" "bracketright" "asciicircum" "underscore" 
"grave" "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" 
"q" "r" "s" "t" "u" "v" "w" "x" "y" "z" "braceleft" "bar" "braceright" 
"asciitilde" "bullet" "Euro" "bullet" "quotesinglbase" "florin" 
"quotedblbase" "ellipsis" "dagger" "daggerdbl" "circumflex" 
"perthousand" "Scaron" "guilsinglleft" "OE" "bullet" "Zcaron" "bullet" 
"bullet" "quoteleft" "quoteright" "quotedblleft" "quotedblright" 
"bullet" "endash" "emdash" "tilde" "trademark" "scaron" 
"guilsinglright" "oe" "bullet" "zcaron" "Ydieresis" "space" 
"exclamdown" "cent" "sterling" "currency" "yen" "brokenbar" "section" 
"dieresis" "copyright" "ordfeminine" "guillemotleft" "logicalnot" 
"hyphen" "registered" "macron" "degree" "plusminus" "twosuperior" 
"threesuperior" "acute" "mu" "paragraph" "periodcentered" "cedilla" 
"onesuperior" "ordmasculine" "guillemotright" "onequarter" "onehalf" 
"threequarters" "questiondown" "Agrave" "Aacute" "Acircumflex" "Atilde" 
"Adieresis" "Aring" "AE" "Ccedilla" "Egrave" "Eacute" "Ecircumflex" 
"Edieresis" "Igrave" "Iacute" "Icircumflex" "Idieresis" "Eth" "Ntilde" 
"Ograve" "Oacute" "Ocircumflex" "Otilde" "Odieresis" "multiply" 
"Oslash" "Ugrave" "Uacute" "Ucircumflex" "Udieresis" "Yacute" "Thorn" 
"germandbls" "agrave" "aacute" "acircumflex" "atilde" "adieresis" 
"aring" "ae" "ccedilla" "egrave" "eacute" "ecircumflex" "edieresis" 
"igrave" "iacute" "icircumflex" "idieresis" "eth" "ntilde" "ograve" 
"oacute" "ocircumflex" "otilde" "odieresis" "divide" "oslash" "ugrave" 
"uacute" "ucircumflex" "udieresis" "yacute" "thorn" "ydieresis" )))

(defvar *pdf-doc-encoding*
  (make-instance 'encoding :name "PDFDocEncoding" :keyword-name :pdf-doc-encoding
		 :standard-encoding t :char-names #(
nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil 
nil nil nil nil nil nil "breve" "caron" "circumflex" "dotaccent" 
"hungarumlaut" "ogonek" "ring" "tilde" "space" "exclam" "quotedbl" 
"numbersign" "dollar" "percent" "ampersand" "quotesingle" "parenleft" 
"parenright" "asterisk" "plus" "comma" "hyphen" "period" "slash" "zero" 
"one" "two" "three" "four" "five" "six" "seven" "eight" "nine" "colon" 
"semicolon" "less" "equal" "greater" "question" "at" "A" "B" "C" "D" 
"E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q" "R" "S" "T" "U" "V" 
"W" "X" "Y" "Z" "bracketleft" "backslash" "bracketright" "asciicircum" 
"underscore" "grave" "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" 
"m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z" "braceleft" 
"bar" "braceright" "asciitilde" nil "bullet" "dagger" "daggerdbl" 
"ellipsis" "emdash" "endash" "florin" "fraction" "guilsinglleft" 
"guilsinglright" "minus" "perthousand" "quotedblbase" "quotedblleft" 
"quotedblright" "quoteleft" "quoteright" "quotesinglbase" "trademark" 
"fi" "fl" "Lslash" "OE" "Scaron" "Ydieresis" "Zcaron" "dotlessi" 
"lslash" "oe" "scaron" "zcaron" nil "Euro" "exclamdown" "cent" 
"sterling" "currency" "yen" "brokenbar" "section" "dieresis" 
"copyright" "ordfeminine" "guillemotleft" "logicalnot" nil "registered" 
"macron" "degree" "plusminus" "twosuperior" "threesuperior" "acute" 
"mu" "paragraph" "periodcentered" "cedilla" "onesuperior" 
"ordmasculine" "guillemotright" "onequarter" "onehalf" "threequarters" 
"questiondown" "Agrave" "Aacute" "Acircumflex" "Atilde" "Adieresis" 
"Aring" "AE" "Ccedilla" "Egrave" "Eacute" "Ecircumflex" "Edieresis" 
"Igrave" "Iacute" "Icircumflex" "Idieresis" "Eth" "Ntilde" "Ograve" 
"Oacute" "Ocircumflex" "Otilde" "Odieresis" "multiply" "Oslash" 
"Ugrave" "Uacute" "Ucircumflex" "Udieresis" "Yacute" "Thorn" 
"germandbls" "agrave" "aacute" "acircumflex" "atilde" "adieresis" 
"aring" "ae" "ccedilla" "egrave" "eacute" "ecircumflex" "edieresis" 
"igrave" "iacute" "icircumflex" "idieresis" "eth" "ntilde" "ograve" 
"oacute" "ocircumflex" "otilde" "odieresis" "divide" "oslash" "ugrave" 
"uacute" "ucircumflex" "udieresis" "yacute" "thorn" "ydieresis" )))

(defvar *mac-expert-encoding*
  (make-instance 'encoding :name "MacExpertEncoding" :keyword-name :mac-expert-encoding
		 :standard-encoding t :char-names #(
nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil 
nil nil nil nil nil nil nil nil nil nil nil nil nil nil "space" 
"exclamsmall" "Hungarumlautsmall" "centoldstyle" "dollaroldstyle" 
"dollarsuperior" "ampersandsmall" "Acutesmall" "parenleftsuperior" 
"parenrightsuperior" "twodotenleader" "onedotenleader" "comma" "hyphen" 
"period" "fraction" "zerooldstyle" "oneoldstyle" "twooldstyle" 
"threeoldstyle" "fouroldstyle" "fiveoldstyle" "sixoldstyle" 
"sevenoldstyle" "eightoldstyle" "nineoldstyle" "colon" "semicolon" nil 
"threequartersemdash" nil "questionsmall" nil nil nil nil "Ethsmall" 
nil nil "onequarter" "onehalf" "threequarters" "oneeighth" 
"threeeighths" "fiveeighths" "seveneighths" "onethird" "twothirds" nil 
nil nil nil nil nil "ff" "fi" "fl" "ffi" "ffl" "parenleftinferior" nil 
"parenrightinferior" "Circumflexsmall" "hypheninferior" "Gravesmall" 
"Asmall" "Bsmall" "Csmall" "Dsmall" "Esmall" "Fsmall" "Gsmall" "Hsmall" 
"Ismall" "Jsmall" "Ksmall" "Lsmall" "Msmall" "Nsmall" "Osmall" "Psmall" 
"Qsmall" "Rsmall" "Ssmall" "Tsmall" "Usmall" "Vsmall" "Wsmall" "Xsmall" 
"Ysmall" "Zsmall" "colonmonetary" "onefitted" "rupiah" "Tildesmall" nil 
nil "asuperior" "centsuperior" nil nil nil nil "Aacutesmall" 
"Agravesmall" "Acircumflexsmall" "Adieresissmall" "Atildesmall" 
"Aringsmall" "Ccedillasmall" "Eacutesmall" "Egravesmall" 
"Ecircumflexsmall" "Edieresissmall" "Iacutesmall" "Igravesmall" 
"Icircumflexsmall" "Idieresissmall" "Ntildesmall" "Oacutesmall" 
"Ogravesmall" "Ocircumflexsmall" "Odieresissmall" "Otildesmall" 
"Uacutesmall" "Ugravesmall" "Ucircumflexsmall" "Udieresissmall" nil 
"eightsuperior" "fourinferior" "threeinferior" "sixinferior" 
"eightinferior" "seveninferior" "Scaronsmall" nil "centinferior" 
"twoinferior" nil "Dieresissmall" nil "Caronsmall" "osuperior" 
"fiveinferior" nil "commainferior" "periodinferior" "Yacutesmall" nil 
"dollarinferior" nil nil "Thornsmall" nil "nineinferior" "zeroinferior" 
"Zcaronsmall" "AEsmall" "Oslashsmall" "questiondownsmall" "oneinferior" 
"Lslashsmall" nil nil nil nil nil nil "Cedillasmall" nil nil nil nil 
nil "OEsmall" "figuredash" "hyphensuperior" nil nil nil nil 
"exclamdownsmall" nil "Ydieresissmall" nil "onesuperior" "twosuperior" 
"threesuperior" "foursuperior" "fivesuperior" "sixsuperior" 
"sevensuperior" "ninesuperior" "zerosuperior" nil "esuperior" 
"rsuperior" "tsuperior" nil nil "isuperior" "ssuperior" "dsuperior" nil 
nil nil nil nil "lsuperior" "Ogoneksmall" "Brevesmall" "Macronsmall" 
"bsuperior" "nsuperior" "msuperior" "commasuperior" "periodsuperior" 
"Dotaccentsmall" "Ringsmall" nil nil nil nil )))

(defvar *symbol-encoding*
  (make-instance 'encoding :name "SymbolEncoding" :keyword-name :symbol-encoding
		 :standard-encoding t :char-names #(
nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil 
nil nil nil nil nil nil nil nil nil nil nil nil nil nil "space" 
"exclam" "universal" "numbersign" "existential" "percent" "ampersand" 
"suchthat" "parenleft" "parenright" "asteriskmath" "plus" "comma" 
"minus" "period" "slash" "zero" "one" "two" "three" "four" "five" "six" 
"seven" "eight" "nine" "colon" "semicolon" "less" "equal" "greater" 
"question" "congruent" "Alpha" "Beta" "Chi" "Delta" "Epsilon" "Phi" 
"Gamma" "Eta" "Iota" "theta1" "Kappa" "Lambda" "Mu" "Nu" "Omicron" "Pi" 
"Theta" "Rho" "Sigma" "Tau" "Upsilon" "sigma1" "Omega" "Xi" "Psi" 
"Zeta" "bracketleft" "therefore" "bracketright" "perpendicular" 
"underscore" "radicalex" "alpha" "beta" "chi" "delta" "epsilon" "phi" 
"gamma" "eta" "iota" "phi1" "kappa" "lambda" "mu" "nu" "omicron" "pi" 
"theta" "rho" "sigma" "tau" "upsilon" "omega1" "omega" "xi" "psi" 
"zeta" "braceleft" "bar" "braceright" "similar" nil nil nil nil nil nil 
nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil 
nil nil nil nil nil nil nil nil nil "Euro" "Upsilon1" "minute" 
"lessequal" "fraction" "infinity" "florin" "club" "diamond" "heart" 
"spade" "arrowboth" "arrowleft" "arrowup" "arrowright" "arrowdown" 
"degree" "plusminus" "second" "greaterequal" "multiply" "proportional" 
"partialdiff" "bullet" "divide" "notequal" "equivalence" "approxequal" 
"ellipsis" "arrowvertex" "arrowhorizex" "carriagereturn" "aleph" 
"Ifraktur" "Rfraktur" "weierstrass" "circlemultiply" "circleplus" 
"emptyset" "intersection" "union" "propersuperset" "reflexsuperset" 
"notsubset" "propersubset" "reflexsubset" "element" "notelement" 
"angle" "gradient" "registerserif" "copyrightserif" "trademarkserif" 
"product" "radical" "dotmath" "logicalnot" "logicaland" "logicalor" 
"arrowdblboth" "arrowdblleft" "arrowdblup" "arrowdblright" 
"arrowdbldown" "lozenge" "angleleft" "registersans" "copyrightsans" 
"trademarksans" "summation" "parenlefttp" "parenleftex" "parenleftbt" 
"bracketlefttp" "bracketleftex" "bracketleftbt" "bracelefttp" 
"braceleftmid" "braceleftbt" "braceex" nil "angleright" "integral" 
"integraltp" "integralex" "integralbt" "parenrighttp" "parenrightex" 
"parenrightbt" "bracketrighttp" "bracketrightex" "bracketrightbt" 
"bracerighttp" "bracerightmid" "bracerightbt" nil )))

(defvar *zapf-dingbats-encoding*
  (make-instance 'encoding :name "ZapfDingbatsEncoding" :keyword-name :zapf-dingbats-encoding
		 :standard-encoding t :char-names #(
nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil 
nil nil nil nil nil nil nil nil nil nil nil nil nil nil "space" "a1" 
"a2" "a202" "a3" "a4" "a5" "a119" "a118" "a117" "a11" "a12" "a13" "a14" 
"a15" "a16" "a105" "a17" "a18" "a19" "a20" "a21" "a22" "a23" "a24" 
"a25" "a26" "a27" "a28" "a6" "a7" "a8" "a9" "a10" "a29" "a30" "a31" 
"a32" "a33" "a34" "a35" "a36" "a37" "a38" "a39" "a40" "a41" "a42" "a43" 
"a44" "a45" "a46" "a47" "a48" "a49" "a50" "a51" "a52" "a53" "a54" "a55" 
"a56" "a57" "a58" "a59" "a60" "a61" "a62" "a63" "a64" "a65" "a66" "a67" 
"a68" "a69" "a70" "a71" "a72" "a73" "a74" "a203" "a75" "a204" "a76" 
"a77" "a78" "a79" "a81" "a82" "a83" "a84" "a97" "a98" "a99" "a100" nil 
"a89" "a90" "a93" "a94" "a91" "a92" "a205" "a85" "a206" "a86" "a87" 
"a88" "a95" "a96" nil nil nil nil nil nil nil nil nil nil nil nil nil 
nil nil nil nil nil nil "a101" "a102" "a103" "a104" "a106" "a107" 
"a108" "a112" "a111" "a110" "a109" "a120" "a121" "a122" "a123" "a124" 
"a125" "a126" "a127" "a128" "a129" "a130" "a131" "a132" "a133" "a134" 
"a135" "a136" "a137" "a138" "a139" "a140" "a141" "a142" "a143" "a144" 
"a145" "a146" "a147" "a148" "a149" "a150" "a151" "a152" "a153" "a154" 
"a155" "a156" "a157" "a158" "a159" "a160" "a161" "a163" "a164" "a196" 
"a165" "a192" "a166" "a167" "a168" "a169" "a170" "a171" "a172" "a173" 
"a162" "a174" "a175" "a176" "a177" "a178" "a179" "a193" "a180" "a199" 
"a181" "a200" "a182" nil "a201" "a183" "a184" "a197" "a185" "a194" 
"a198" "a186" "a195" "a187" "a188" "a189" "a190" "a191" nil )))

;;; custom encoding by Dmitri Ivanov: divanov_nosp@m_aha.ru (replace _nosp@m_ by @ to reply)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Custom Encoding

(defclass custom-encoding (encoding)
 ((base-encoding :initarg :base-encoding :reader base-encoding :initform nil)))

(defmethod initialize-instance :after ((encoding custom-encoding) &rest initargs
                                       &key &allow-other-keys)
  (with-slots (base-encoding) encoding
    (when (and base-encoding
               (or (stringp base-encoding) (symbolp base-encoding)))
      (setf base-encoding (gethash base-encoding *encodings* base-encoding)))))



(defmethod make-dictionary ((encoding custom-encoding) &key &allow-other-keys)
  (with-slots (base-encoding) encoding
    (make-instance 'dictionary
      :dict-values
      `(("/Type" . "/Encoding")
        ,@(when base-encoding
            `(("/BaseEncoding" . ,(add-/ (name base-encoding)))
              ("/Differences" . ,(compute-encoding-differences encoding
                                                               base-encoding))))))))

;;; CAUTION:
;;;  Basing on :win-ansi-encoding fails for embedded Type1 fonts!
;;;  For some installed fonts that are not embedded, :win-ansi-encoding gets better
;;;  results, so it should be specified explicitly for get-font.
;;;  It seems that get-font should not have any default for the encoding parameter.

(defvar *win-1251-encoding*
  (make-instance 'custom-encoding
                 :name "Win1251Encoding" :keyword-name :win-1251-encoding
                 :base-encoding :standard-encoding   ;:win-ansi-encoding doesn't work!
		 :standard-encoding nil                 
                 :char-names #(
	nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
	nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
	"space" "exclam" "quotedbl" "numbersign" "dollar" "percent" "ampersand"
	"quotesingle" "parenleft" "parenright" "asterisk" "plus" "comma" "hyphen"
	"period" "slash" "zero" "one" "two" "three" "four" "five" "six" "seven"
	"eight" "nine" "colon" "semicolon" "less" "equal" "greater" "question" "at"
	"A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q" "R" "S"
	"T" "U" "V" "W" "X" "Y" "Z" "bracketleft" "backslash" "bracketright"
        "asciicircum" "underscore" "grave"
        "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s"
        "t" "u" "v" "w" "x" "y" "z" "braceleft" "bar" "braceright" "asciitilde"
        nil "Djecyrillic" "Gjecyrillic" "quotesinglbase" "gjecyrillic" "quotedblbase"
        "ellipsis" "dagger" "daggerdbl" "Euro" "perthousand" "Ljecyrillic"
        "guilsinglleft" "Njecyrillic" "Kjecyrillic" "Tshecyrillic" "Dzhecyrillic"
        "djecyrillic" "quoteleft" "quoteright" "quotedblleft" "quotedblright" "bullet"
        "endash" "emdash" NIL "trademark" "ljecyrillic" "guilsinglright" "njecyrillic"
        "kjecyrillic" "tshecyrillic" "dzhecyrillic" "space" "Ushortcyrillic"
        "ushortcyrillic" "Jecyrillic" "currency" "Gheupturncyrillic" "brokenbar"
        "section" "Iocyrillic" "copyright" "Ecyrillic" "guillemotleft" "logicalnot"
        "hyphen" "registered" "Yicyrillic" "degree" "plusminus" "Icyrillic" "icyrillic"
        "gheupturncyrillic" "mu" "paragraph" "periodcentered" "iocyrillic" "numero"
        "ecyrillic" "guillemotright" "jecyrillic" "Dzecyrillic" "dzecyrillic" "yicyrillic"
        "Acyrillic" "Becyrillic" "Vecyrillic" "Gecyrillic" "Decyrillic" "Iecyrillic"
        "Zhecyrillic" "Zecyrillic" "Iicyrillic" "Iishortcyrillic" "Kacyrillic"
        "Elcyrillic" "Emcyrillic" "Encyrillic" "Ocyrillic" "Pecyrillic" "Ercyrillic"
        "Escyrillic" "Tecyrillic" "Ucyrillic" "Efcyrillic" "Khacyrillic" "Tsecyrillic"
        "Checyrillic" "Shacyrillic" "Shchacyrillic" "Hardsigncyrillic" "Yericyrillic"
        "Softsigncyrillic" "Ereversedcyrillic" "IUcyrillic" "IAcyrillic"
        "acyrillic" "becyrillic" "vecyrillic" "gecyrillic" "decyrillic" "iecyrillic"
        "zhecyrillic" "zecyrillic" "iicyrillic" "iishortcyrillic" "kacyrillic"
        "elcyrillic" "emcyrillic" "encyrillic" "ocyrillic" "pecyrillic" "ercyrillic"
        "escyrillic" "tecyrillic" "ucyrillic" "efcyrillic" "khacyrillic" "tsecyrillic"
        "checyrillic" "shacyrillic" "shchacyrillic" "hardsigncyrillic" "yericyrillic"
        "softsigncyrillic" "ereversedcyrillic" "iucyrillic" "iacyrillic")))
