Parse a line in the font mapping file. The format is (partially) documented at http://mirrors.ctan.org/systems/doc/pdftex/manual/pdftex-a.pdf https://tug.org/texinfohtml/dvips.html#psfonts_002emap Each line can have the following fields: - tfmname (
(self, line)
| 1129 | f"your TeX package manager") from None |
| 1130 | |
| 1131 | def _parse_and_cache_line(self, line): |
| 1132 | """ |
| 1133 | Parse a line in the font mapping file. |
| 1134 | |
| 1135 | The format is (partially) documented at |
| 1136 | http://mirrors.ctan.org/systems/doc/pdftex/manual/pdftex-a.pdf |
| 1137 | https://tug.org/texinfohtml/dvips.html#psfonts_002emap |
| 1138 | Each line can have the following fields: |
| 1139 | |
| 1140 | - tfmname (first, only required field), |
| 1141 | - psname (defaults to tfmname, must come immediately after tfmname if |
| 1142 | present), |
| 1143 | - fontflags (integer, must come immediately after psname if present, |
| 1144 | ignored by us), |
| 1145 | - special (SlantFont and ExtendFont, only field that is double-quoted), |
| 1146 | - fontfile, encodingfile (optional, prefixed by <, <<, or <[; << always |
| 1147 | precedes a font, <[ always precedes an encoding, < can precede either |
| 1148 | but then an encoding file must have extension .enc; < and << also |
| 1149 | request different font subsetting behaviors but we ignore that; < can |
| 1150 | be separated from the filename by whitespace). |
| 1151 | |
| 1152 | special, fontfile, and encodingfile can appear in any order. |
| 1153 | """ |
| 1154 | # If the map file specifies multiple encodings for a font, we |
| 1155 | # follow pdfTeX in choosing the last one specified. Such |
| 1156 | # entries are probably mistakes but they have occurred. |
| 1157 | # https://tex.stackexchange.com/q/10826/ |
| 1158 | |
| 1159 | if not line or line.startswith((b" ", b"%", b"*", b";", b"#")): |
| 1160 | return |
| 1161 | tfmname = basename = special = encodingfile = fontfile = None |
| 1162 | is_subsetted = is_t1 = is_truetype = False |
| 1163 | matches = re.finditer(br'"([^"]*)(?:"|$)|(\S+)', line) |
| 1164 | for match in matches: |
| 1165 | quoted, unquoted = match.groups() |
| 1166 | if unquoted: |
| 1167 | if unquoted.startswith(b"<<"): # font |
| 1168 | fontfile = unquoted[2:] |
| 1169 | elif unquoted.startswith(b"<["): # encoding |
| 1170 | encodingfile = unquoted[2:] |
| 1171 | elif unquoted.startswith(b"<"): # font or encoding |
| 1172 | word = ( |
| 1173 | # <foo => foo |
| 1174 | unquoted[1:] |
| 1175 | # < by itself => read the next word |
| 1176 | or next(filter(None, next(matches).groups()))) |
| 1177 | if word.endswith(b".enc"): |
| 1178 | encodingfile = word |
| 1179 | else: |
| 1180 | fontfile = word |
| 1181 | is_subsetted = True |
| 1182 | elif tfmname is None: |
| 1183 | tfmname = unquoted |
| 1184 | elif basename is None: |
| 1185 | basename = unquoted |
| 1186 | elif quoted: |
| 1187 | special = quoted |
| 1188 | effects = {} |
no test coverage detected