chromatic-python 0.3.2__tar.gz → 0.3.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. {chromatic_python-0.3.2/chromatic_python.egg-info → chromatic_python-0.3.3}/PKG-INFO +1 -1
  2. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/chromatic/__init__.pyi +19 -3
  3. chromatic_python-0.3.3/chromatic/_version.py +34 -0
  4. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/chromatic/color/__init__.pyi +8 -4
  5. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/chromatic/color/core.py +31 -30
  6. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/chromatic/color/core.pyi +2 -0
  7. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/chromatic/demo.py +20 -0
  8. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/chromatic/image/_array.py +19 -17
  9. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/chromatic/image/_glyph_proc.py +12 -12
  10. {chromatic_python-0.3.2 → chromatic_python-0.3.3/chromatic_python.egg-info}/PKG-INFO +1 -1
  11. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/pyproject.toml +1 -3
  12. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/tests/test_color_str.py +3 -3
  13. chromatic_python-0.3.2/chromatic/_version.py +0 -21
  14. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/.gitattributes +0 -0
  15. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/.gitignore +0 -0
  16. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/LICENSE +0 -0
  17. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/README.md +0 -0
  18. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/chromatic/__init__.py +0 -0
  19. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/chromatic/_typing.py +0 -0
  20. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/chromatic/color/__init__.py +0 -0
  21. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/chromatic/color/colorconv.py +0 -0
  22. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/chromatic/color/iterators.py +0 -0
  23. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/chromatic/color/palette.py +0 -0
  24. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/chromatic/color/palette.pyi +0 -0
  25. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/chromatic/data/__init__.py +0 -0
  26. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/chromatic/data/__init__.pyi +0 -0
  27. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/chromatic/data/_fetchers.py +0 -0
  28. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/chromatic/data/butterfly.jpg +0 -0
  29. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/chromatic/data/escher.png +0 -0
  30. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/chromatic/data/fonts/consolas.ttf +0 -0
  31. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/chromatic/data/fonts/vga437.ttf +0 -0
  32. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/chromatic/data/goblin_virus.png +0 -0
  33. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/chromatic/data/registry.json +0 -0
  34. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/chromatic/data/userfont.py +0 -0
  35. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/chromatic/data/userfont.pyi +0 -0
  36. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/chromatic/data/userfont.schema.json +0 -0
  37. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/chromatic/image/__init__.py +0 -0
  38. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/chromatic/image/__init__.pyi +0 -0
  39. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/chromatic/image/_curses.py +0 -0
  40. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/chromatic_python.egg-info/SOURCES.txt +0 -0
  41. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/chromatic_python.egg-info/dependency_links.txt +0 -0
  42. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/chromatic_python.egg-info/requires.txt +0 -0
  43. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/chromatic_python.egg-info/top_level.txt +0 -0
  44. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/logo/logo.ANS +0 -0
  45. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/logo/logo.PNG +0 -0
  46. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/requirements.txt +0 -0
  47. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/setup.cfg +0 -0
  48. {chromatic_python-0.3.2 → chromatic_python-0.3.3}/tests/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chromatic-python
3
- Version: 0.3.2
3
+ Version: 0.3.3
4
4
  Summary: ANSI art image processing and colored terminal text
5
5
  Author: crypt0lith
6
6
  Project-URL: Homepage, https://github.com/crypt0lith/chromatic
@@ -7,6 +7,7 @@ __all__ = [
7
7
  'Fore',
8
8
  'SgrParameter',
9
9
  'Style',
10
+ 'UserFont',
10
11
  '__version__',
11
12
  'ansi2img',
12
13
  'ansi_quantize',
@@ -14,10 +15,10 @@ __all__ = [
14
15
  'ansicolor4Bit',
15
16
  'ansicolor8Bit',
16
17
  'ansify',
17
- 'image',
18
18
  'ascii2img',
19
19
  'ascii_printable',
20
20
  'color',
21
+ 'color_chain',
21
22
  'colorbytes',
22
23
  'contrast_stretch',
23
24
  'cp437_printable',
@@ -26,14 +27,23 @@ __all__ = [
26
27
  'get_font_key',
27
28
  'get_font_object',
28
29
  'get_glyph_masks',
30
+ 'hexstr2rgb',
31
+ 'image',
29
32
  'img2ansi',
30
33
  'img2ascii',
34
+ 'int2rgb',
31
35
  'named_color',
32
36
  'read_ans',
33
37
  'register_userfont',
34
38
  'render_ans',
35
39
  'reshape_ansi',
40
+ 'rgb2hexstr',
41
+ 'rgb2int',
42
+ 'sort_glyphs',
36
43
  'to_sgr_array',
44
+ 'ttf_extract_codepoints',
45
+ 'userfont',
46
+ 'set_default_ansi',
37
47
  ]
38
48
  from . import color, data, image
39
49
  from ._version import version as __version__
@@ -48,10 +58,16 @@ from .color import (
48
58
  ansicolor24Bit,
49
59
  ansicolor4Bit,
50
60
  ansicolor8Bit,
61
+ color_chain,
51
62
  colorbytes,
63
+ hexstr2rgb,
64
+ int2rgb,
52
65
  named_color,
66
+ rgb2hexstr,
67
+ rgb2int,
68
+ set_default_ansi,
53
69
  )
54
- from .data import register_userfont
70
+ from .data import UserFont, register_userfont, userfont
55
71
  from .image import (
56
72
  AnsiImage,
57
73
  ansi2img,
@@ -71,4 +87,4 @@ from .image import (
71
87
  reshape_ansi,
72
88
  to_sgr_array,
73
89
  )
74
- from .image._glyph_proc import get_glyph_masks
90
+ from .image._glyph_proc import get_glyph_masks, sort_glyphs, ttf_extract_codepoints
@@ -0,0 +1,34 @@
1
+ # file generated by setuptools-scm
2
+ # don't change, don't track in version control
3
+
4
+ __all__ = [
5
+ "__version__",
6
+ "__version_tuple__",
7
+ "version",
8
+ "version_tuple",
9
+ "__commit_id__",
10
+ "commit_id",
11
+ ]
12
+
13
+ TYPE_CHECKING = False
14
+ if TYPE_CHECKING:
15
+ from typing import Tuple
16
+ from typing import Union
17
+
18
+ VERSION_TUPLE = Tuple[Union[int, str], ...]
19
+ COMMIT_ID = Union[str, None]
20
+ else:
21
+ VERSION_TUPLE = object
22
+ COMMIT_ID = object
23
+
24
+ version: str
25
+ __version__: str
26
+ __version_tuple__: VERSION_TUPLE
27
+ version_tuple: VERSION_TUPLE
28
+ commit_id: COMMIT_ID
29
+ __commit_id__: COMMIT_ID
30
+
31
+ __version__ = version = '0.3.3'
32
+ __version_tuple__ = version_tuple = (0, 3, 3)
33
+
34
+ __commit_id__ = commit_id = 'g23243f5d4'
@@ -5,6 +5,7 @@ __all__ = [
5
5
  'Color',
6
6
  'ColorNamespace',
7
7
  'ColorStr',
8
+ 'DEFAULT_ANSI',
8
9
  'Fore',
9
10
  'SGR_RESET',
10
11
  'SgrParameter',
@@ -18,10 +19,10 @@ __all__ = [
18
19
  'color_chain',
19
20
  'colorbytes',
20
21
  'get_ansi_type',
21
- 'int2rgb',
22
22
  'hexstr2rgb',
23
23
  'hsl2rgb',
24
24
  'hsv2rgb',
25
+ 'int2rgb',
25
26
  'is_u24',
26
27
  'lab2rgb',
27
28
  'lab2xyz',
@@ -30,15 +31,16 @@ __all__ = [
30
31
  'nearest_ansi_8bit_rgb',
31
32
  'randcolor',
32
33
  'rgb2ansi_escape',
33
- 'rgb2int',
34
34
  'rgb2hexstr',
35
35
  'rgb2hsl',
36
36
  'rgb2hsv',
37
+ 'rgb2int',
37
38
  'rgb2lab',
38
39
  'rgb2xyz',
39
40
  'rgb_diff',
40
41
  'rgb_dispatch',
41
42
  'rgb_to_ansi_8bit',
43
+ 'set_default_ansi',
42
44
  'xyz2lab',
43
45
  'xyz2rgb',
44
46
  ]
@@ -47,19 +49,19 @@ from .colorconv import (
47
49
  ANSI_4BIT_RGB,
48
50
  ansi_4bit_to_rgb,
49
51
  ansi_8bit_to_rgb,
50
- int2rgb,
51
52
  hexstr2rgb,
52
53
  hsl2rgb,
53
54
  hsv2rgb,
55
+ int2rgb,
54
56
  is_u24,
55
57
  lab2rgb,
56
58
  lab2xyz,
57
59
  nearest_ansi_4bit_rgb,
58
60
  nearest_ansi_8bit_rgb,
59
- rgb2int,
60
61
  rgb2hexstr,
61
62
  rgb2hsl,
62
63
  rgb2hsv,
64
+ rgb2int,
63
65
  rgb2lab,
64
66
  rgb2xyz,
65
67
  rgb_diff,
@@ -71,6 +73,7 @@ from .core import (
71
73
  CSI,
72
74
  Color,
73
75
  ColorStr,
76
+ DEFAULT_ANSI,
74
77
  SGR_RESET,
75
78
  SgrParameter,
76
79
  SgrSequence,
@@ -82,5 +85,6 @@ from .core import (
82
85
  get_ansi_type,
83
86
  randcolor,
84
87
  rgb2ansi_escape,
88
+ set_default_ansi,
85
89
  )
86
90
  from .palette import Back, ColorNamespace, Fore, Style, named_color, rgb_dispatch
@@ -266,8 +266,6 @@ class colorbytes(bytes):
266
266
  class ansicolor4Bit(colorbytes):
267
267
  """ANSI 4-bit color format.
268
268
 
269
- alias: '4b'
270
-
271
269
  Supports 16 colors:
272
270
  * 8 standard colors:
273
271
  {0: black, 1: red, 2: green, 3: yellow, 4: blue, 5: magenta, 6: cyan, 7: white}
@@ -298,8 +296,6 @@ class ansicolor4Bit(colorbytes):
298
296
  class ansicolor8Bit(colorbytes):
299
297
  """ANSI 8-Bit color format.
300
298
 
301
- alias: '8b'
302
-
303
299
  Supports 256 colors, mapped to the following value ranges:
304
300
  * (0, 15): Corresponds to ANSI 4-bit colors.
305
301
  * (16, 231): Represents a 6x6x6 RGB color cube.
@@ -328,8 +324,6 @@ class ansicolor8Bit(colorbytes):
328
324
  class ansicolor24Bit(colorbytes):
329
325
  """ANSI 24-Bit color format.
330
326
 
331
- alias: '24b'
332
-
333
327
  Supports all colors in the RGB color space (16,777,216 total).
334
328
 
335
329
  Color codes use escape sequences of the form:
@@ -407,7 +401,37 @@ def _is_ansi_type(typ: type):
407
401
  return False
408
402
 
409
403
 
410
- @lru_cache(maxsize=None)
404
+ @lru_cache
405
+ def get_ansi_type(typ):
406
+ try:
407
+ return _ANSI_FORMAT_MAP[typ]
408
+ except (TypeError, KeyError) as e:
409
+ if isinstance(typ, str):
410
+ err = ValueError(f"invalid ANSI color format alias: {e!r}")
411
+ else:
412
+ from .._typing import unionize
413
+
414
+ repr_getter = lambda t: (t if isinstance(t, type) else type(t))
415
+ msg = (
416
+ "Expected {.__name__!r} or {}, got {.__name__!r} object instead".format(
417
+ str,
418
+ type[unionize(set(map(repr_getter, _ANSI_FORMAT_MAP.values())))],
419
+ repr_getter(typ),
420
+ )
421
+ )
422
+ err = TypeError(msg)
423
+ err.__cause__ = e.__cause__
424
+ raise err
425
+
426
+
427
+ def set_default_ansi(typ):
428
+ """Sets the global `DEFAULT_ANSI` variable to the specified ANSI color format"""
429
+ if valid_typ := get_ansi_type(typ):
430
+ global DEFAULT_ANSI
431
+ DEFAULT_ANSI = valid_typ
432
+
433
+
434
+ @lru_cache(maxsize=1)
411
435
  def sgr_re_pattern():
412
436
  uint8_re = r"(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)"
413
437
  ansicolor_re = f"[3-4]8;(?:2(?:;{uint8_re}){{3}}|5;{uint8_re})"
@@ -456,29 +480,6 @@ def _concat_ansi_escape(__it: Iterable[bytes | bytearray]):
456
480
  return b'\x1b[%sm' % b';'.join(__it)
457
481
 
458
482
 
459
- @lru_cache
460
- def get_ansi_type(typ):
461
- try:
462
- return _ANSI_FORMAT_MAP[typ]
463
- except (TypeError, KeyError) as e:
464
- if isinstance(typ, str):
465
- err = ValueError(f"invalid ANSI color format alias: {e!r}")
466
- else:
467
- from .._typing import unionize
468
-
469
- repr_getter = lambda t: (t if isinstance(t, type) else type(t))
470
- msg = (
471
- "Expected {.__name__!r} or {}, got {.__name__!r} object instead".format(
472
- str,
473
- type[unionize(set(map(repr_getter, _ANSI_FORMAT_MAP.values())))],
474
- repr_getter(typ),
475
- )
476
- )
477
- err = TypeError(msg)
478
- err.__cause__ = e.__cause__
479
- raise err
480
-
481
-
482
483
  def rgb2ansi_escape(fmt, mode, rgb):
483
484
  fmt = get_ansi_type(fmt)
484
485
  if len(rgb) != 3:
@@ -54,6 +54,7 @@ from chromatic._typing import (
54
54
  TupleOf3,
55
55
  )
56
56
 
57
+
57
58
  @overload
58
59
  def get_ansi_type[_T: AnsiColorType](typ: _T) -> _T: ...
59
60
  @overload
@@ -62,6 +63,7 @@ def get_ansi_type(typ: Ansi4BitAlias) -> type[ansicolor4Bit]: ...
62
63
  def get_ansi_type(typ: Ansi8BitAlias) -> type[ansicolor8Bit]: ...
63
64
  @overload
64
65
  def get_ansi_type(typ: Ansi24BitAlias) -> type[ansicolor24Bit]: ...
66
+ def set_default_ansi(typ: AnsiColorAlias | AnsiColorType): ...
65
67
  def randcolor() -> Color: ...
66
68
  def rgb2ansi_escape(
67
69
  fmt: AnsiColorAlias | AnsiColorType, mode: ColorDictKeys, rgb: Int3Tuple
@@ -172,6 +172,26 @@ def named_colors():
172
172
  print(' | '.join(line))
173
173
 
174
174
 
175
+ @DEMO_FUNCS.register
176
+ def color_cube():
177
+ """Print the ANSI256 6x6x6 color cube"""
178
+ fmt_code = lambda n: f"\x1b[48;5;{n}m{n: >4}"
179
+ for i in range(0, 8, 4):
180
+ for j in range(i, i + 8):
181
+ print(fmt_code(i + j), end='')
182
+ else:
183
+ print("\x1b[m")
184
+ for i in range(6):
185
+ for j in range(0x10, 0xE8, 6):
186
+ print(fmt_code(i + j), end='')
187
+ else:
188
+ print("\x1b[m")
189
+ for i in range(0xE8, 0x100):
190
+ print(fmt_code(i), end='')
191
+ else:
192
+ print("\x1b[m")
193
+
194
+
175
195
  @DEMO_FUNCS.register
176
196
  def color_table():
177
197
  """Print foreground / background combinations in each ANSI format.
@@ -85,6 +85,7 @@ if TYPE_CHECKING:
85
85
  RGBImageLike,
86
86
  ShapedNDArray,
87
87
  TupleOf2,
88
+ TupleOf3,
88
89
  )
89
90
 
90
91
  LiteralDigit: TypeAlias = Sequence[
@@ -507,8 +508,8 @@ def img2ascii(
507
508
 
508
509
  def img2ascii(
509
510
  __img: RGBImageLike | PathLike[str] | str,
510
- __font: FontArgType = 'arial.ttf',
511
- factor: int = 100,
511
+ __font: FontArgType = userfont['vga437'],
512
+ factor: int = 200,
512
513
  char_set: Iterable[str] = None,
513
514
  sort_glyphs: bool | type[reversed] = True,
514
515
  *,
@@ -585,8 +586,8 @@ def img2ascii(
585
586
  @rgb_dispatch(('bg',))
586
587
  def img2ansi(
587
588
  __img: RGBImageLike | PathLike[str] | str,
588
- __font: FontArgType = 'arial.ttf',
589
- factor: int = 100,
589
+ __font: FontArgType = userfont['vga437'],
590
+ factor: int = 200,
590
591
  char_set: Iterable[str] = None,
591
592
  ansi_type: AnsiColorParam = DEFAULT_ANSI,
592
593
  sort_glyphs: bool | type[reversed] = True,
@@ -671,7 +672,7 @@ def img2ansi(
671
672
  x = []
672
673
  for j in range(w):
673
674
  char = lines[i][j]
674
- fg_color = Color.from_rgb(color_arr.getpixel([j, i]))
675
+ fg_color = Color.from_rgb(color_arr.getpixel((j, i)))
675
676
  if j > 0 and x[-1].fg == fg_color:
676
677
  x[-1] += char
677
678
  else:
@@ -683,8 +684,8 @@ def img2ansi(
683
684
  @rgb_dispatch(('fg', 'bg'))
684
685
  def ascii2img(
685
686
  __ascii: str,
686
- __font: FontArgType = 'arial.ttf',
687
- font_size=24,
687
+ __font: FontArgType = userfont['vga437'],
688
+ font_size=16,
688
689
  *,
689
690
  fg: Int3Tuple | str = (0, 0, 0),
690
691
  bg: Int3Tuple | str = (0xFF, 0xFF, 0xFF),
@@ -722,7 +723,8 @@ def ascii2img(
722
723
  n_rows, n_cols = map(len, (lines, lines[0]))
723
724
  cw, ch = _get_bbox_shape(font)
724
725
  iw, ih = (int(i * j) for i, j in zip((cw, ch), (n_cols, n_rows)))
725
- img = Image.new('RGB', (iw, ih), tuple(map(int, bg)))
726
+ (r, g, b) = tuple(map(int, bg))
727
+ img = Image.new('RGB', (iw, ih), (r, g, b))
726
728
  draw = ImageDraw.Draw(img)
727
729
  y_offset = 0
728
730
  for line in lines:
@@ -734,8 +736,8 @@ def ascii2img(
734
736
  @rgb_dispatch(('fg_default', 'bg_default'))
735
737
  def ansi2img(
736
738
  __ansi_array: list[list[ColorStr]],
737
- __font: FontArgType = 'arial.ttf',
738
- font_size=24,
739
+ __font: FontArgType = userfont['vga437'],
740
+ font_size=16,
739
741
  *,
740
742
  fg_default: Int3Tuple | str = (170, 170, 170),
741
743
  bg_default: Int3Tuple | str | Literal['auto'] = 'auto',
@@ -782,12 +784,13 @@ def ansi2img(
782
784
  for row in __ansi_array
783
785
  )
784
786
  iw, ih = map(int, (max_row_width, n_rows * row_height))
785
- input_fg = fg_default
787
+ input_fg: TupleOf3[int] = fg_default
786
788
  if auto := bg_default == 'auto':
787
789
  input_bg = bg_default = None
788
790
  else:
789
791
  input_bg = bg_default
790
- img = Image.new('RGB', (iw, ih), cast(tuple[float, ...], bg_default))
792
+ bg_default: Optional[TupleOf3[int] | ...]
793
+ img = Image.new('RGB', (iw, ih), bg_default)
791
794
  draw = ImageDraw.Draw(img)
792
795
  y_offset = 0
793
796
  for row in __ansi_array:
@@ -803,7 +806,7 @@ def ansi2img(
803
806
  if auto:
804
807
  bg_default = bg_color
805
808
  draw.rectangle(
806
- [x_offset, y_offset, x_offset + text_width, y_offset + row_height],
809
+ (x_offset, y_offset, x_offset + text_width, y_offset + row_height),
807
810
  fill=bg_color or (0, 0, 0),
808
811
  )
809
812
  draw.text(
@@ -882,7 +885,7 @@ def _is_csi_param(__c: str) -> TypeGuard[Literal[';'] | LiteralDigit]:
882
885
  return __c == ';' or __c.isdigit()
883
886
 
884
887
 
885
- @lru_cache(maxsize=None)
888
+ @lru_cache(maxsize=1)
886
889
  def sgr_span_re_pattern():
887
890
  sgr_re = sgr_re_pattern().pattern.removeprefix(r'\x1b\[')
888
891
  return re.compile(
@@ -952,7 +955,6 @@ def _sub_bold_colors(lines: Iterable[str]) -> Iterator[str]:
952
955
 
953
956
 
954
957
  def reshape_ansi(__str: str, w: int, h: int) -> str:
955
-
956
958
  def cursor() -> Generator[tuple[int, int], tuple[int, int], None]:
957
959
  idx, total = 0, h * w
958
960
  while idx < total:
@@ -1026,8 +1028,8 @@ def reshape_ansi(__str: str, w: int, h: int) -> str:
1026
1028
 
1027
1029
 
1028
1030
  @lru_cache
1029
- def to_sgr_array(__str: str, ansi_type: AnsiColorParam = DEFAULT_ANSI):
1030
- ansi_typ = get_ansi_type(ansi_type)
1031
+ def to_sgr_array(__str: str, ansi_type: AnsiColorParam = None):
1032
+ ansi_typ = DEFAULT_ANSI if ansi_type is None else get_ansi_type(ansi_type)
1031
1033
  new_cs = partial(ColorStr, ansi_type=ansi_typ, reset=False)
1032
1034
  xs = []
1033
1035
  for line in _sub_bold_colors(__str.splitlines()):
@@ -63,17 +63,19 @@ def get_glyph_masks(
63
63
 
64
64
 
65
65
  def sort_glyphs(__s: str, font: FontArgType, reverse: bool = False):
66
- def _sum_mask(item: tuple[str, np.ndarray]):
67
- return item[0], np.sum(item[1])
68
-
66
+ all_chars = list(__s)
67
+ mapping = {}
68
+ for c, arr in get_glyph_masks(font, __s, dist_transform=True).items():
69
+ v = np.sum(arr)
70
+ if v <= 0 and c != ' ':
71
+ continue
72
+ mapping[c] = v
69
73
  return ''.join(
70
- char
71
- for (char, value) in sorted(
72
- map(_sum_mask, get_glyph_masks(font, __s, dist_transform=True).items()),
73
- key=lambda x: x[1],
74
+ sorted(
75
+ filter(mapping.__contains__, all_chars),
76
+ key=mapping.__getitem__,
74
77
  reverse=reverse,
75
78
  )
76
- if value > 0 or char == ' '
77
79
  )
78
80
 
79
81
 
@@ -84,7 +86,5 @@ def ttf_extract_codepoints(
84
86
  with TTFont(__fp, **kwargs) as font:
85
87
  for table in font['cmap'].tables:
86
88
  codepoints |= table.cmap.keys()
87
-
88
- return np.sort(
89
- np.array([i for i in codepoints if chr(i).isprintable()], dtype='<u2')
90
- )
89
+ arr = np.array([i for i in codepoints if chr(i).isprintable()], dtype='<u2')
90
+ return np.sort(arr) # type: ignore[arg-type]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chromatic-python
3
- Version: 0.3.2
3
+ Version: 0.3.3
4
4
  Summary: ANSI art image processing and colored terminal text
5
5
  Author: crypt0lith
6
6
  Project-URL: Homepage, https://github.com/crypt0lith/chromatic
@@ -20,6 +20,7 @@ dependencies = [
20
20
  authors = [{ name = "crypt0lith" }]
21
21
  description = "ANSI art image processing and colored terminal text"
22
22
  readme = "README.md"
23
+ license-files = ["LICENSE"]
23
24
  keywords = ["ansi", "ascii", "art", "font", "image", "terminal", "parser"]
24
25
  classifiers = [
25
26
  "Programming Language :: Python :: 3.12",
@@ -31,9 +32,6 @@ classifiers = [
31
32
  [project.urls]
32
33
  Homepage = "https://github.com/crypt0lith/chromatic"
33
34
 
34
- [tool.setuptools]
35
- license-files = ["LICENSE"]
36
-
37
35
  [tool.setuptools_scm]
38
36
  write_to = "chromatic/_version.py"
39
37
 
@@ -178,10 +178,10 @@ def _rand_color_str_array(n_rows=10, n_cols=10):
178
178
  (
179
179
  current,
180
180
  *(
181
- (
182
- (c.as_ansi_type(t) if isinstance(c, ColorStr) else c)
181
+ [
182
+ c.as_ansi_type(t) if isinstance(c, ColorStr) else c
183
183
  for c in current
184
- )
184
+ ]
185
185
  for t in (ansicolor4Bit, ansicolor8Bit, ansicolor24Bit)
186
186
  ),
187
187
  ),
@@ -1,21 +0,0 @@
1
- # file generated by setuptools-scm
2
- # don't change, don't track in version control
3
-
4
- __all__ = ["__version__", "__version_tuple__", "version", "version_tuple"]
5
-
6
- TYPE_CHECKING = False
7
- if TYPE_CHECKING:
8
- from typing import Tuple
9
- from typing import Union
10
-
11
- VERSION_TUPLE = Tuple[Union[int, str], ...]
12
- else:
13
- VERSION_TUPLE = object
14
-
15
- version: str
16
- __version__: str
17
- __version_tuple__: VERSION_TUPLE
18
- version_tuple: VERSION_TUPLE
19
-
20
- __version__ = version = '0.3.2'
21
- __version_tuple__ = version_tuple = (0, 3, 2)