ThirdParty/Pygments/pygments/formatters/img.py

changeset 4172
4f20dba37ab6
parent 3145
a9de05d4a22f
child 4697
c2e9bf425554
equal deleted inserted replaced
4170:8bc578136279 4172:4f20dba37ab6
3 pygments.formatters.img 3 pygments.formatters.img
4 ~~~~~~~~~~~~~~~~~~~~~~~ 4 ~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 Formatter for Pixmap output. 6 Formatter for Pixmap output.
7 7
8 :copyright: Copyright 2006-2013 by the Pygments team, see AUTHORS. 8 :copyright: Copyright 2006-2014 by the Pygments team, see AUTHORS.
9 :license: BSD, see LICENSE for details. 9 :license: BSD, see LICENSE for details.
10 """ 10 """
11 11
12 from __future__ import unicode_literals
13
14 import sys 12 import sys
15 13
16 from pygments.formatter import Formatter 14 from pygments.formatter import Formatter
17 from pygments.util import get_bool_opt, get_int_opt, \ 15 from pygments.util import get_bool_opt, get_int_opt, get_list_opt, \
18 get_list_opt, get_choice_opt 16 get_choice_opt, xrange
19 17
20 # Import this carefully 18 # Import this carefully
21 try: 19 try:
22 from PIL import Image, ImageDraw, ImageFont 20 from PIL import Image, ImageDraw, ImageFont
23 pil_available = True 21 pil_available = True
24 except ImportError: 22 except ImportError:
25 pil_available = False 23 pil_available = False
26 24
27 try: 25 try:
28 import winreg 26 import _winreg
29 except ImportError: 27 except ImportError:
30 _winreg = None 28 try:
29 import winreg as _winreg
30 except ImportError:
31 _winreg = None
31 32
32 __all__ = ['ImageFormatter', 'GifImageFormatter', 'JpgImageFormatter', 33 __all__ = ['ImageFormatter', 'GifImageFormatter', 'JpgImageFormatter',
33 'BmpImageFormatter'] 34 'BmpImageFormatter']
34 35
35 36
72 if not font_name: 73 if not font_name:
73 self.font_name = DEFAULT_FONT_NAME_NIX 74 self.font_name = DEFAULT_FONT_NAME_NIX
74 self._create_nix() 75 self._create_nix()
75 76
76 def _get_nix_font_path(self, name, style): 77 def _get_nix_font_path(self, name, style):
77 from subprocess import getstatusoutput 78 try:
79 from commands import getstatusoutput
80 except ImportError:
81 from subprocess import getstatusoutput
78 exit, out = getstatusoutput('fc-list "%s:style=%s" file' % 82 exit, out = getstatusoutput('fc-list "%s:style=%s" file' %
79 (name, style)) 83 (name, style))
80 if not exit: 84 if not exit:
81 lines = out.splitlines() 85 lines = out.splitlines()
82 if lines: 86 if lines:
107 def _lookup_win(self, key, basename, styles, fail=False): 111 def _lookup_win(self, key, basename, styles, fail=False):
108 for suffix in ('', ' (TrueType)'): 112 for suffix in ('', ' (TrueType)'):
109 for style in styles: 113 for style in styles:
110 try: 114 try:
111 valname = '%s%s%s' % (basename, style and ' '+style, suffix) 115 valname = '%s%s%s' % (basename, style and ' '+style, suffix)
112 val, _ = winreg.QueryValueEx(key, valname) 116 val, _ = _winreg.QueryValueEx(key, valname)
113 return val 117 return val
114 except EnvironmentError: 118 except EnvironmentError:
115 continue 119 continue
116 else: 120 else:
117 if fail: 121 if fail:
119 (basename, styles[0])) 123 (basename, styles[0]))
120 return None 124 return None
121 125
122 def _create_win(self): 126 def _create_win(self):
123 try: 127 try:
124 key = winreg.OpenKey( 128 key = _winreg.OpenKey(
125 winreg.HKEY_LOCAL_MACHINE, 129 _winreg.HKEY_LOCAL_MACHINE,
126 r'Software\Microsoft\Windows NT\CurrentVersion\Fonts') 130 r'Software\Microsoft\Windows NT\CurrentVersion\Fonts')
127 except EnvironmentError: 131 except EnvironmentError:
128 try: 132 try:
129 key = winreg.OpenKey( 133 key = _winreg.OpenKey(
130 winreg.HKEY_LOCAL_MACHINE, 134 _winreg.HKEY_LOCAL_MACHINE,
131 r'Software\Microsoft\Windows\CurrentVersion\Fonts') 135 r'Software\Microsoft\Windows\CurrentVersion\Fonts')
132 except EnvironmentError: 136 except EnvironmentError:
133 raise FontNotFound('Can\'t open Windows font registry key') 137 raise FontNotFound('Can\'t open Windows font registry key')
134 try: 138 try:
135 path = self._lookup_win(key, self.font_name, STYLES['NORMAL'], True) 139 path = self._lookup_win(key, self.font_name, STYLES['NORMAL'], True)
142 if style == 'BOLDITALIC': 146 if style == 'BOLDITALIC':
143 self.fonts[style] = self.fonts['BOLD'] 147 self.fonts[style] = self.fonts['BOLD']
144 else: 148 else:
145 self.fonts[style] = self.fonts['NORMAL'] 149 self.fonts[style] = self.fonts['NORMAL']
146 finally: 150 finally:
147 winreg.CloseKey(key) 151 _winreg.CloseKey(key)
148 152
149 def get_char_size(self): 153 def get_char_size(self):
150 """ 154 """
151 Get the character size. 155 Get the character size.
152 """ 156 """
169 class ImageFormatter(Formatter): 173 class ImageFormatter(Formatter):
170 """ 174 """
171 Create a PNG image from source code. This uses the Python Imaging Library to 175 Create a PNG image from source code. This uses the Python Imaging Library to
172 generate a pixmap from the source code. 176 generate a pixmap from the source code.
173 177
174 *New in Pygments 0.10.* 178 .. versionadded:: 0.10
175 179
176 Additional options accepted: 180 Additional options accepted:
177 181
178 `image_format` 182 `image_format`
179 An image format to output to that is recognised by PIL, these include: 183 An image format to output to that is recognised by PIL, these include:
258 the source code area. 262 the source code area.
259 263
260 Default: 6 264 Default: 6
261 265
262 `hl_lines` 266 `hl_lines`
263 Specify a list of lines to be highlighted. *New in Pygments 1.2.* 267 Specify a list of lines to be highlighted.
268
269 .. versionadded:: 1.2
264 270
265 Default: empty list 271 Default: empty list
266 272
267 `hl_color` 273 `hl_color`
268 Specify the color for highlighting lines. *New in Pygments 1.2.* 274 Specify the color for highlighting lines.
275
276 .. versionadded:: 1.2
269 277
270 Default: highlight color of the selected style 278 Default: highlight color of the selected style
271 """ 279 """
272 280
273 # Required by the pygments mapper 281 # Required by the pygments mapper
285 """ 293 """
286 if not pil_available: 294 if not pil_available:
287 raise PilNotAvailable( 295 raise PilNotAvailable(
288 'Python Imaging Library is required for this formatter') 296 'Python Imaging Library is required for this formatter')
289 Formatter.__init__(self, **options) 297 Formatter.__init__(self, **options)
298 self.encoding = 'latin1' # let pygments.format() do the right thing
290 # Read the style 299 # Read the style
291 self.styles = dict(self.style) 300 self.styles = dict(self.style)
292 if self.style.background_color is None: 301 if self.style.background_color is None:
293 self.background_color = '#fff' 302 self.background_color = '#fff'
294 else: 303 else:
305 self.fontw, self.fonth = self.fonts.get_char_size() 314 self.fontw, self.fonth = self.fonts.get_char_size()
306 # Line number options 315 # Line number options
307 self.line_number_fg = options.get('line_number_fg', '#886') 316 self.line_number_fg = options.get('line_number_fg', '#886')
308 self.line_number_bg = options.get('line_number_bg', '#eed') 317 self.line_number_bg = options.get('line_number_bg', '#eed')
309 self.line_number_chars = get_int_opt(options, 318 self.line_number_chars = get_int_opt(options,
310 'line_number_chars', 2) 319 'line_number_chars', 2)
311 self.line_number_bold = get_bool_opt(options, 320 self.line_number_bold = get_bool_opt(options,
312 'line_number_bold', False) 321 'line_number_bold', False)
313 self.line_number_italic = get_bool_opt(options, 322 self.line_number_italic = get_bool_opt(options,
314 'line_number_italic', False) 323 'line_number_italic', False)
315 self.line_number_pad = get_int_opt(options, 'line_number_pad', 6) 324 self.line_number_pad = get_int_opt(options, 'line_number_pad', 6)
316 self.line_numbers = get_bool_opt(options, 'line_numbers', True) 325 self.line_numbers = get_bool_opt(options, 'line_numbers', True)
317 self.line_number_separator = get_bool_opt(options, 326 self.line_number_separator = get_bool_opt(options,
318 'line_number_separator', True) 327 'line_number_separator', True)
319 self.line_number_step = get_int_opt(options, 'line_number_step', 1) 328 self.line_number_step = get_int_opt(options, 'line_number_step', 1)
320 self.line_number_start = get_int_opt(options, 'line_number_start', 1) 329 self.line_number_start = get_int_opt(options, 'line_number_start', 1)
321 if self.line_numbers: 330 if self.line_numbers:
322 self.line_number_width = (self.fontw * self.line_number_chars + 331 self.line_number_width = (self.fontw * self.line_number_chars +
323 self.line_number_pad * 2) 332 self.line_number_pad * 2)
324 else: 333 else:
325 self.line_number_width = 0 334 self.line_number_width = 0
326 self.hl_lines = [] 335 self.hl_lines = []
327 hl_lines_str = get_list_opt(options, 'hl_lines', []) 336 hl_lines_str = get_list_opt(options, 'hl_lines', [])
328 for line in hl_lines_str: 337 for line in hl_lines_str:
427 # TODO: make sure tab expansion happens earlier in the chain. It 436 # TODO: make sure tab expansion happens earlier in the chain. It
428 # really ought to be done on the input, as to do it right here is 437 # really ought to be done on the input, as to do it right here is
429 # quite complex. 438 # quite complex.
430 value = value.expandtabs(4) 439 value = value.expandtabs(4)
431 lines = value.splitlines(True) 440 lines = value.splitlines(True)
432 #print lines 441 # print lines
433 for i, line in enumerate(lines): 442 for i, line in enumerate(lines):
434 temp = line.rstrip('\n') 443 temp = line.rstrip('\n')
435 if temp: 444 if temp:
436 self._draw_text( 445 self._draw_text(
437 self._get_text_pos(charno, lineno), 446 self._get_text_pos(charno, lineno),
452 """ 461 """
453 Create drawables for the line numbers. 462 Create drawables for the line numbers.
454 """ 463 """
455 if not self.line_numbers: 464 if not self.line_numbers:
456 return 465 return
457 for p in range(self.maxlineno): 466 for p in xrange(self.maxlineno):
458 n = p + self.line_number_start 467 n = p + self.line_number_start
459 if (n % self.line_number_step) == 0: 468 if (n % self.line_number_step) == 0:
460 self._draw_linenumber(p, n) 469 self._draw_linenumber(p, n)
461 470
462 def _paint_line_number_bg(self, im): 471 def _paint_line_number_bg(self, im):
468 if self.line_number_fg is None: 477 if self.line_number_fg is None:
469 return 478 return
470 draw = ImageDraw.Draw(im) 479 draw = ImageDraw.Draw(im)
471 recth = im.size[-1] 480 recth = im.size[-1]
472 rectw = self.image_pad + self.line_number_width - self.line_number_pad 481 rectw = self.image_pad + self.line_number_width - self.line_number_pad
473 draw.rectangle([(0, 0), 482 draw.rectangle([(0, 0), (rectw, recth)],
474 (rectw, recth)], 483 fill=self.line_number_bg)
475 fill=self.line_number_bg)
476 draw.line([(rectw, 0), (rectw, recth)], fill=self.line_number_fg) 484 draw.line([(rectw, 0), (rectw, recth)], fill=self.line_number_fg)
477 del draw 485 del draw
478 486
479 def format(self, tokensource, outfile): 487 def format(self, tokensource, outfile):
480 """ 488 """
513 class GifImageFormatter(ImageFormatter): 521 class GifImageFormatter(ImageFormatter):
514 """ 522 """
515 Create a GIF image from source code. This uses the Python Imaging Library to 523 Create a GIF image from source code. This uses the Python Imaging Library to
516 generate a pixmap from the source code. 524 generate a pixmap from the source code.
517 525
518 *New in Pygments 1.0.* (You could create GIF images before by passing a 526 .. versionadded:: 1.0
519 suitable `image_format` option to the `ImageFormatter`.)
520 """ 527 """
521 528
522 name = 'img_gif' 529 name = 'img_gif'
523 aliases = ['gif'] 530 aliases = ['gif']
524 filenames = ['*.gif'] 531 filenames = ['*.gif']
528 class JpgImageFormatter(ImageFormatter): 535 class JpgImageFormatter(ImageFormatter):
529 """ 536 """
530 Create a JPEG image from source code. This uses the Python Imaging Library to 537 Create a JPEG image from source code. This uses the Python Imaging Library to
531 generate a pixmap from the source code. 538 generate a pixmap from the source code.
532 539
533 *New in Pygments 1.0.* (You could create JPEG images before by passing a 540 .. versionadded:: 1.0
534 suitable `image_format` option to the `ImageFormatter`.)
535 """ 541 """
536 542
537 name = 'img_jpg' 543 name = 'img_jpg'
538 aliases = ['jpg', 'jpeg'] 544 aliases = ['jpg', 'jpeg']
539 filenames = ['*.jpg'] 545 filenames = ['*.jpg']
543 class BmpImageFormatter(ImageFormatter): 549 class BmpImageFormatter(ImageFormatter):
544 """ 550 """
545 Create a bitmap image from source code. This uses the Python Imaging Library to 551 Create a bitmap image from source code. This uses the Python Imaging Library to
546 generate a pixmap from the source code. 552 generate a pixmap from the source code.
547 553
548 *New in Pygments 1.0.* (You could create bitmap images before by passing a 554 .. versionadded:: 1.0
549 suitable `image_format` option to the `ImageFormatter`.)
550 """ 555 """
551 556
552 name = 'img_bmp' 557 name = 'img_bmp'
553 aliases = ['bmp', 'bitmap'] 558 aliases = ['bmp', 'bitmap']
554 filenames = ['*.bmp'] 559 filenames = ['*.bmp']

eric ide

mercurial