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-2020 by the Pygments team, see AUTHORS. |
8 :copyright: Copyright 2006-2021 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 import os |
12 import os |
13 import sys |
13 import sys |
124 font_map = {} |
124 font_map = {} |
125 for font_dir in (os.path.join(os.getenv("HOME"), 'Library/Fonts/'), |
125 for font_dir in (os.path.join(os.getenv("HOME"), 'Library/Fonts/'), |
126 '/Library/Fonts/', '/System/Library/Fonts/'): |
126 '/Library/Fonts/', '/System/Library/Fonts/'): |
127 font_map.update( |
127 font_map.update( |
128 (os.path.splitext(f)[0].lower(), os.path.join(font_dir, f)) |
128 (os.path.splitext(f)[0].lower(), os.path.join(font_dir, f)) |
129 for f in os.listdir(font_dir) if f.lower().endswith('ttf')) |
129 for f in os.listdir(font_dir) |
|
130 if f.lower().endswith(('ttf', 'ttc'))) |
130 |
131 |
131 for name in STYLES['NORMAL']: |
132 for name in STYLES['NORMAL']: |
132 path = self._get_mac_font_path(font_map, self.font_name, name) |
133 path = self._get_mac_font_path(font_map, self.font_name, name) |
133 if path is not None: |
134 if path is not None: |
134 self.fonts['NORMAL'] = ImageFont.truetype(path, self.font_size) |
135 self.fonts['NORMAL'] = ImageFont.truetype(path, self.font_size) |
205 def get_char_size(self): |
206 def get_char_size(self): |
206 """ |
207 """ |
207 Get the character size. |
208 Get the character size. |
208 """ |
209 """ |
209 return self.fonts['NORMAL'].getsize('M') |
210 return self.fonts['NORMAL'].getsize('M') |
|
211 |
|
212 def get_text_size(self, text): |
|
213 """ |
|
214 Get the text size(width, height). |
|
215 """ |
|
216 return self.fonts['NORMAL'].getsize(text) |
210 |
217 |
211 def get_font(self, bold, oblique): |
218 def get_font(self, bold, oblique): |
212 """ |
219 """ |
213 Get the font based on bold and italic flags. |
220 Get the font based on bold and italic flags. |
214 """ |
221 """ |
416 """ |
423 """ |
417 Get the width of a character. |
424 Get the width of a character. |
418 """ |
425 """ |
419 return self.fontw |
426 return self.fontw |
420 |
427 |
421 def _get_char_x(self, charno): |
428 def _get_char_x(self, linelength): |
422 """ |
429 """ |
423 Get the X coordinate of a character position. |
430 Get the X coordinate of a character position. |
424 """ |
431 """ |
425 return charno * self.fontw + self.image_pad + self.line_number_width |
432 return linelength + self.image_pad + self.line_number_width |
426 |
433 |
427 def _get_text_pos(self, charno, lineno): |
434 def _get_text_pos(self, linelength, lineno): |
428 """ |
435 """ |
429 Get the actual position for a character and line position. |
436 Get the actual position for a character and line position. |
430 """ |
437 """ |
431 return self._get_char_x(charno), self._get_line_y(lineno) |
438 return self._get_char_x(linelength), self._get_line_y(lineno) |
432 |
439 |
433 def _get_linenumber_pos(self, lineno): |
440 def _get_linenumber_pos(self, lineno): |
434 """ |
441 """ |
435 Get the actual position for the start of a line number. |
442 Get the actual position for the start of a line number. |
436 """ |
443 """ |
450 """ |
457 """ |
451 Get the correct font for the style. |
458 Get the correct font for the style. |
452 """ |
459 """ |
453 return self.fonts.get_font(style['bold'], style['italic']) |
460 return self.fonts.get_font(style['bold'], style['italic']) |
454 |
461 |
455 def _get_image_size(self, maxcharno, maxlineno): |
462 def _get_image_size(self, maxlinelength, maxlineno): |
456 """ |
463 """ |
457 Get the required image size. |
464 Get the required image size. |
458 """ |
465 """ |
459 return (self._get_char_x(maxcharno) + self.image_pad, |
466 return (self._get_char_x(maxlinelength) + self.image_pad, |
460 self._get_line_y(maxlineno + 0) + self.image_pad) |
467 self._get_line_y(maxlineno + 0) + self.image_pad) |
461 |
468 |
462 def _draw_linenumber(self, posno, lineno): |
469 def _draw_linenumber(self, posno, lineno): |
463 """ |
470 """ |
464 Remember a line number drawable to paint later. |
471 Remember a line number drawable to paint later. |
480 def _create_drawables(self, tokensource): |
487 def _create_drawables(self, tokensource): |
481 """ |
488 """ |
482 Create drawables for the token content. |
489 Create drawables for the token content. |
483 """ |
490 """ |
484 lineno = charno = maxcharno = 0 |
491 lineno = charno = maxcharno = 0 |
|
492 maxlinelength = linelength = 0 |
485 for ttype, value in tokensource: |
493 for ttype, value in tokensource: |
486 while ttype not in self.styles: |
494 while ttype not in self.styles: |
487 ttype = ttype.parent |
495 ttype = ttype.parent |
488 style = self.styles[ttype] |
496 style = self.styles[ttype] |
489 # TODO: make sure tab expansion happens earlier in the chain. It |
497 # TODO: make sure tab expansion happens earlier in the chain. It |
494 # print lines |
502 # print lines |
495 for i, line in enumerate(lines): |
503 for i, line in enumerate(lines): |
496 temp = line.rstrip('\n') |
504 temp = line.rstrip('\n') |
497 if temp: |
505 if temp: |
498 self._draw_text( |
506 self._draw_text( |
499 self._get_text_pos(charno, lineno), |
507 self._get_text_pos(linelength, lineno), |
500 temp, |
508 temp, |
501 font = self._get_style_font(style), |
509 font = self._get_style_font(style), |
502 fill = self._get_text_color(style) |
510 fill = self._get_text_color(style) |
503 ) |
511 ) |
|
512 temp_width, temp_hight = self.fonts.get_text_size(temp) |
|
513 linelength += temp_width |
|
514 maxlinelength = max(maxlinelength, linelength) |
504 charno += len(temp) |
515 charno += len(temp) |
505 maxcharno = max(maxcharno, charno) |
516 maxcharno = max(maxcharno, charno) |
506 if line.endswith('\n'): |
517 if line.endswith('\n'): |
507 # add a line for each extra line in the value |
518 # add a line for each extra line in the value |
|
519 linelength = 0 |
508 charno = 0 |
520 charno = 0 |
509 lineno += 1 |
521 lineno += 1 |
|
522 self.maxlinelength = maxlinelength |
510 self.maxcharno = maxcharno |
523 self.maxcharno = maxcharno |
511 self.maxlineno = lineno |
524 self.maxlineno = lineno |
512 |
525 |
513 def _draw_line_numbers(self): |
526 def _draw_line_numbers(self): |
514 """ |
527 """ |
548 """ |
561 """ |
549 self._create_drawables(tokensource) |
562 self._create_drawables(tokensource) |
550 self._draw_line_numbers() |
563 self._draw_line_numbers() |
551 im = Image.new( |
564 im = Image.new( |
552 'RGB', |
565 'RGB', |
553 self._get_image_size(self.maxcharno, self.maxlineno), |
566 self._get_image_size(self.maxlinelength, self.maxlineno), |
554 self.background_color |
567 self.background_color |
555 ) |
568 ) |
556 self._paint_line_number_bg(im) |
569 self._paint_line_number_bg(im) |
557 draw = ImageDraw.Draw(im) |
570 draw = ImageDraw.Draw(im) |
558 # Highlight |
571 # Highlight |