PGTKernelbasic 0.23.0__py3-none-any.whl

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.
Kernel/ImageObj.py ADDED
@@ -0,0 +1,52 @@
1
+ import pygame
2
+ from Kernel.ObjType import RectTuple, PosTuple
3
+ import os
4
+ pygame_load = pygame.image.load
5
+ convert_alpha = pygame.Surface.convert_alpha
6
+ save = pygame.image.save
7
+ os_exists = os.path.exists
8
+ os_path_join = os.path.join
9
+ os_path_splitext = os.path.splitext
10
+ def is_image_file(path):
11
+ ext = os.path.splitext(path)[1].lower()
12
+ return ext in {'.png', '.jpg', '.jpeg', '.bmp', '.gif'}
13
+ class ImagePack:
14
+ def __init__(self, src: str, convert_alpha = True):
15
+ if os_exists(src) and is_image_file(src):
16
+ self.src = src
17
+ else:
18
+ raise ValueError("This is not a valid image path")
19
+ self.surface = pygame_load(src).convert_alpha() if convert_alpha else pygame_load(src)
20
+ def get_rect(self):
21
+ return self.surface.get_rect()
22
+ def get_size(self):
23
+ return self.surface.get_size()
24
+ def resize(self, size: PosTuple):
25
+ self.surface = pygame.transform.scale(self.surface, size)
26
+ return self
27
+ def scale_resize(self, scale):
28
+ w, h = self.get_size()
29
+ self.surface = pygame.transform.scale(self.surface, (w*scale, h * scale))
30
+ return self
31
+ def rotate(self, angle):
32
+ self.surface = pygame.transform.rotate(self.surface, angle)
33
+ return self
34
+ def crop(self, rect: RectTuple):
35
+ if (rect[0] < 0 or rect[1] < 0 or
36
+ rect[0] + rect[2] > self.surface.get_width() or
37
+ rect[1] + rect[3] > self.surface.get_height()):
38
+ raise ValueError("Crop rectangle out of image bounds")
39
+ else:
40
+ self.surface = self.surface.subsurface(rect)
41
+ return self
42
+ def take_from_crop(self, rect: RectTuple):
43
+ return self.surface.subsurface(rect).copy()
44
+ def get_image(self):
45
+ return self.surface
46
+ def flip(self, horizontal=False, vertical=False):
47
+ self.surface = pygame.transform.flip(self.surface, horizontal, vertical)
48
+ return self
49
+ def copy(self):
50
+ new_pack = ImagePack(self.src, convert_alpha=False)
51
+ new_pack.surface = self.surface.copy()
52
+ return new_pack
Kernel/KernalInit.py ADDED
@@ -0,0 +1,21 @@
1
+ import pygame
2
+ init_state = False
3
+ _fill_mode = True
4
+
5
+ def set_fill_mode(mode=False):
6
+ global _fill_mode
7
+ _fill_mode = mode
8
+
9
+ def should_fill():
10
+ global _fill_mode
11
+ tfill = _fill_mode
12
+ _fill_mode = False
13
+ return tfill
14
+ def init():
15
+ global init_state
16
+ if not init_state:
17
+ pygame.init()
18
+ pygame.key.set_repeat(500, 50)
19
+ init_state = True
20
+ set_fill_mode(_fill_mode)
21
+
Kernel/KernelAudio.py ADDED
@@ -0,0 +1,97 @@
1
+ import pygame
2
+ import miniaudio
3
+ import os
4
+
5
+ class Audio:
6
+ def __init__(self, filepath: str):
7
+ ext = os.path.splitext(filepath)[1].lower()
8
+ valid_exts = ('.mp3', '.wav', '.ogg', '.flac', '.m4a', '.aac')
9
+ if not os.path.exists(filepath):
10
+ raise FileNotFoundError(f"Audio file not found: {filepath}")
11
+ if ext not in valid_exts:
12
+ raise ValueError(f"Unsupported format: {ext}. Supported: {valid_exts}")
13
+ self.filepath = filepath
14
+ self.backend = self._detect_backend()
15
+ self._load()
16
+ self._stream = None
17
+ self._paused = False
18
+ self._volume = 1.0
19
+ def _detect_backend(self):
20
+ try:
21
+ import miniaudio
22
+ return 'miniaudio'
23
+ except ImportError:
24
+ return 'pygame'
25
+
26
+ def _load(self):
27
+ if self.backend == 'miniaudio':
28
+ self._info = miniaudio.get_file_info(self.filepath)
29
+ self._stream = None
30
+ else: # pygame
31
+ self._sound = pygame.mixer.Sound(self.filepath)
32
+
33
+ def play(self, loop=False, volume=None):
34
+ play_volume = volume if volume is not None else self._volume
35
+
36
+ if self.backend == 'miniaudio':
37
+ self._stream = miniaudio.play_file(
38
+ self.filepath,
39
+ loop=loop,
40
+ volume=play_volume
41
+ )
42
+ else: # pygame
43
+ self._sound.set_volume(play_volume)
44
+ self._sound.play(-1 if loop else 0)
45
+
46
+ self._paused = False
47
+ def stop(self):
48
+ if self.backend == 'miniaudio' and self._stream:
49
+ self._stream.stop()
50
+ self._stream = None
51
+ else:
52
+ self._sound.stop()
53
+
54
+ @property
55
+ def duration(self):
56
+ if self.backend == 'miniaudio':
57
+ return self._info.duration
58
+ else:
59
+ return self._sound.get_length()
60
+ def pause(self):
61
+ if self.backend == 'miniaudio' and self._stream:
62
+ self._stream.pause()
63
+ self._paused = True
64
+ elif self.backend == 'pygame':
65
+ pygame.mixer.pause()
66
+ def resume(self):
67
+ if self.backend == 'miniaudio' and self._stream and self._paused:
68
+ self._stream.resume()
69
+ self._paused = False
70
+ elif self.backend == 'pygame':
71
+ pygame.mixer.unpause()
72
+
73
+ def set_volume(self, volume: float):
74
+ self._volume = max(0.0, min(1.0, volume))
75
+
76
+ if self.backend == 'miniaudio' and self._stream:
77
+ self._stream.volume = self._volume
78
+ elif self.backend == 'pygame' and hasattr(self, '_sound'):
79
+ self._sound.set_volume(self._volume)
80
+
81
+ def get_volume(self) -> float:
82
+ return self._volume
83
+
84
+ def fade_out(self, duration_ms: int):
85
+ if self.backend == 'miniaudio' and self._stream:
86
+ self._stream.fade_out(duration_ms)
87
+ elif self.backend == 'pygame':
88
+ self._sound.fadeout(duration_ms)
89
+
90
+ def fade_in(self, duration_ms: int, loop=False):
91
+ if self.backend == 'miniaudio':
92
+ self._stream = miniaudio.play_file(
93
+ self.filepath,
94
+ loop=loop,
95
+ volume=0.0
96
+ )
97
+ self._stream.fade_in(duration_ms, target_volume=self._volume)
Kernel/KernelColor.py ADDED
@@ -0,0 +1,420 @@
1
+ import re
2
+ FLOAT_ERROR = 0.0000005
3
+ NAMES_TO_HEX = {
4
+ "aliceblue": "#f0f8ff",
5
+ "antiquewhite": "#faebd7",
6
+ "aqua": "#00ffff",
7
+ "aquamarine": "#7fffd4",
8
+ "azure": "#f0ffff",
9
+ "beige": "#f5f5dc",
10
+ "bisque": "#ffe4c4",
11
+ "black": "#000000",
12
+ "blanchedalmond": "#ffebcd",
13
+ "blue": "#0000ff",
14
+ "blueviolet": "#8a2be2",
15
+ "brown": "#a52a2a",
16
+ "burlywood": "#deb887",
17
+ "cadetblue": "#5f9ea0",
18
+ "chartreuse": "#7fff00",
19
+ "chocolate": "#d2691e",
20
+ "coral": "#ff7f50",
21
+ "cornflowerblue": "#6495ed",
22
+ "cornsilk": "#fff8dc",
23
+ "crimson": "#dc143c",
24
+ "cyan": "#00ffff",
25
+ "darkblue": "#00008b",
26
+ "darkcyan": "#008b8b",
27
+ "darkgoldenrod": "#b8860b",
28
+ "darkgray": "#a9a9a9",
29
+ "darkgrey": "#a9a9a9",
30
+ "darkgreen": "#006400",
31
+ "darkkhaki": "#bdb76b",
32
+ "darkmagenta": "#8b008b",
33
+ "darkolivegreen": "#556b2f",
34
+ "darkorange": "#ff8c00",
35
+ "darkorchid": "#9932cc",
36
+ "darkred": "#8b0000",
37
+ "darksalmon": "#e9967a",
38
+ "darkseagreen": "#8fbc8f",
39
+ "darkslateblue": "#483d8b",
40
+ "darkslategray": "#2f4f4f",
41
+ "darkslategrey": "#2f4f4f",
42
+ "darkturquoise": "#00ced1",
43
+ "darkviolet": "#9400d3",
44
+ "deeppink": "#ff1493",
45
+ "deepskyblue": "#00bfff",
46
+ "dimgray": "#696969",
47
+ "dimgrey": "#696969",
48
+ "dodgerblue": "#1e90ff",
49
+ "firebrick": "#b22222",
50
+ "floralwhite": "#fffaf0",
51
+ "forestgreen": "#228b22",
52
+ "fuchsia": "#ff00ff",
53
+ "gainsboro": "#dcdcdc",
54
+ "ghostwhite": "#f8f8ff",
55
+ "gold": "#ffd700",
56
+ "goldenrod": "#daa520",
57
+ "gray": "#808080",
58
+ "grey": "#808080",
59
+ "green": "#008000",
60
+ "greenyellow": "#adff2f",
61
+ "honeydew": "#f0fff0",
62
+ "hotpink": "#ff69b4",
63
+ "indianred": "#cd5c5c",
64
+ "indigo": "#4b0082",
65
+ "ivory": "#fffff0",
66
+ "khaki": "#f0e68c",
67
+ "lavender": "#e6e6fa",
68
+ "lavenderblush": "#fff0f5",
69
+ "lawngreen": "#7cfc00",
70
+ "lemonchiffon": "#fffacd",
71
+ "lightblue": "#add8e6",
72
+ "lightcoral": "#f08080",
73
+ "lightcyan": "#e0ffff",
74
+ "lightgoldenrodyellow": "#fafad2",
75
+ "lightgray": "#d3d3d3",
76
+ "lightgrey": "#d3d3d3",
77
+ "lightgreen": "#90ee90",
78
+ "lightpink": "#ffb6c1",
79
+ "lightsalmon": "#ffa07a",
80
+ "lightseagreen": "#20b2aa",
81
+ "lightskyblue": "#87cefa",
82
+ "lightslategray": "#778899",
83
+ "lightslategrey": "#778899",
84
+ "lightsteelblue": "#b0c4de",
85
+ "lightyellow": "#ffffe0",
86
+ "lime": "#00ff00",
87
+ "limegreen": "#32cd32",
88
+ "linen": "#faf0e6",
89
+ "magenta": "#ff00ff",
90
+ "maroon": "#800000",
91
+ "mediumaquamarine": "#66cdaa",
92
+ "mediumblue": "#0000cd",
93
+ "mediumorchid": "#ba55d3",
94
+ "mediumpurple": "#9370db",
95
+ "mediumseagreen": "#3cb371",
96
+ "mediumslateblue": "#7b68ee",
97
+ "mediumspringgreen": "#00fa9a",
98
+ "mediumturquoise": "#48d1cc",
99
+ "mediumvioletred": "#c71585",
100
+ "midnightblue": "#191970",
101
+ "mintcream": "#f5fffa",
102
+ "mistyrose": "#ffe4e1",
103
+ "moccasin": "#ffe4b5",
104
+ "navajowhite": "#ffdead",
105
+ "navy": "#000080",
106
+ "oldlace": "#fdf5e6",
107
+ "olive": "#808000",
108
+ "olivedrab": "#6b8e23",
109
+ "orange": "#ffa500",
110
+ "orangered": "#ff4500",
111
+ "orchid": "#da70d6",
112
+ "palegoldenrod": "#eee8aa",
113
+ "palegreen": "#98fb98",
114
+ "paleturquoise": "#afeeee",
115
+ "palevioletred": "#db7093",
116
+ "papayawhip": "#ffefd5",
117
+ "peachpuff": "#ffdab9",
118
+ "peru": "#cd853f",
119
+ "pink": "#ffc0cb",
120
+ "plum": "#dda0dd",
121
+ "powderblue": "#b0e0e6",
122
+ "purple": "#800080",
123
+ "red": "#ff0000",
124
+ "rosybrown": "#bc8f8f",
125
+ "royalblue": "#4169e1",
126
+ "saddlebrown": "#8b4513",
127
+ "salmon": "#fa8072",
128
+ "sandybrown": "#f4a460",
129
+ "seagreen": "#2e8b57",
130
+ "seashell": "#fff5ee",
131
+ "sienna": "#a0522d",
132
+ "silver": "#c0c0c0",
133
+ "skyblue": "#87ceeb",
134
+ "slateblue": "#6a5acd",
135
+ "slategray": "#708090",
136
+ "slategrey": "#708090",
137
+ "snow": "#fffafa",
138
+ "springgreen": "#00ff7f",
139
+ "steelblue": "#4682b4",
140
+ "tan": "#d2b48c",
141
+ "teal": "#008080",
142
+ "thistle": "#d8bfd8",
143
+ "tomato": "#ff6347",
144
+ "turquoise": "#40e0d0",
145
+ "violet": "#ee82ee",
146
+ "wheat": "#f5deb3",
147
+ "white": "#ffffff",
148
+ "whitesmoke": "#f5f5f5",
149
+ "yellow": "#ffff00",
150
+ "yellowgreen": "#9acd32",
151
+ }
152
+ class ColorTools:
153
+ def name_to_hex(self, name: str) -> str:
154
+ if hex_value := NAMES_TO_HEX.get(name.lower()):
155
+ return hex_value
156
+ raise ValueError(f'"{name}" is not defined as a named color in CSS3')
157
+ def hex_to_rgb(self, hex_value: str):
158
+ int_value = int(self.normalize_hex(hex_value)[1:], 16)
159
+ return int_value >> 16, int_value >> 8 & 0xFF, int_value & 0xFF
160
+ def name_to_rgb(self, name):
161
+ return self.hex_to_rgb(self.name_to_hex(name))
162
+ def normalize_hex(self, hex_value : str):
163
+ if (match := re.compile(r"^#([a-fA-F0-9]{3}|[a-fA-F0-9]{6})$").match(hex_value)) is None:
164
+ raise ValueError(f'"{hex_value}" is not a valid hexadecimal color value.')
165
+ hex_digits = match.group(1)
166
+ if len(hex_digits) == 3:
167
+ hex_digits = "".join(2 * s for s in hex_digits)
168
+ return f"#{hex_digits.lower()}"
169
+
170
+ def hue_to_rgb(self, v1, v2, vH):
171
+
172
+ while vH < 0: vH += 1
173
+ while vH > 1: vH -= 1
174
+
175
+ if 6 * vH < 1: return v1 + (v2 - v1) * 6 * vH
176
+ if 2 * vH < 1: return v2
177
+ if 3 * vH < 2: return v1 + (v2 - v1) * ((2.0 / 3) - vH) * 6
178
+
179
+ return v1
180
+ def hsl_to_rgb(self, hsl):
181
+ h, s, l = (float(v) for v in hsl)
182
+
183
+ if not (0.0 - FLOAT_ERROR <= s <= 1.0 + FLOAT_ERROR):
184
+ raise ValueError("Saturation must be between 0 and 1.")
185
+ if not (0.0 - FLOAT_ERROR <= l <= 1.0 + FLOAT_ERROR):
186
+ raise ValueError("Lightness must be between 0 and 1.")
187
+
188
+ if s == 0:
189
+ return l, l, l
190
+
191
+ if l < 0.5:
192
+ v2 = l * (1.0 + s)
193
+ else:
194
+ v2 = (l + s) - (s * l)
195
+
196
+ v1 = 2.0 * l - v2
197
+
198
+ r = self.hue_to_rgb(v1, v2, h + (1.0 / 3))
199
+ g = self.hue_to_rgb(v1, v2, h)
200
+ b = self.hue_to_rgb(v1, v2, h - (1.0 / 3))
201
+
202
+ return r, g, b
203
+
204
+ def rgb_to_hsl(self, rgb):
205
+ r, g, b = (float(v) for v in rgb)
206
+
207
+ for name, v in {'Red': r, 'Green': g, 'Blue': b}.items():
208
+ if not (0 - FLOAT_ERROR <= v <= 1 + FLOAT_ERROR):
209
+ raise ValueError("%s must be between 0 and 1. You provided %r."
210
+ % (name, v))
211
+
212
+ vmin = min(r, g, b) ## Min. value of RGB
213
+ vmax = max(r, g, b) ## Max. value of RGB
214
+ diff = vmax - vmin ## Delta RGB value
215
+
216
+ vsum = vmin + vmax
217
+
218
+ l = vsum / 2
219
+
220
+ if diff < FLOAT_ERROR:
221
+ return 0.0, 0.0, l
222
+
223
+ ##
224
+ ## Chromatic data...
225
+ ##
226
+
227
+ ## Saturation
228
+ if l < 0.5:
229
+ s = diff / vsum
230
+ else:
231
+ s = diff / (2.0 - vsum)
232
+
233
+ dr = (((vmax - r) / 6) + (diff / 2)) / diff
234
+ dg = (((vmax - g) / 6) + (diff / 2)) / diff
235
+ db = (((vmax - b) / 6) + (diff / 2)) / diff
236
+
237
+ if r == vmax:
238
+ h = db - dg
239
+ elif g == vmax:
240
+ h = (1.0 / 3) + dr - db
241
+ elif b == vmax:
242
+ h = (2.0 / 3) + dg - dr
243
+
244
+ if h < 0: h += 1
245
+ if h > 1: h -= 1
246
+
247
+ return h, s, l
248
+
249
+
250
+ class GradientGenerator:
251
+ def linear_gradient(self, color_start, color_end, steps):
252
+ gradient = []
253
+ for i in range(steps):
254
+ ratio = i / (steps - 1)
255
+ # Trộn màu
256
+ r = int(color_start[0] + (color_end[0] - color_start[0]) * ratio)
257
+ g = int(color_start[1] + (color_end[1] - color_start[1]) * ratio)
258
+ b = int(color_start[2] + (color_end[2] - color_start[2]) * ratio)
259
+ gradient.append((r, g, b))
260
+ return gradient
261
+
262
+ def multi_gradient(self, colors, steps):
263
+ gradient = []
264
+ segments = len(colors) - 1
265
+ steps_per_segment = steps // segments
266
+
267
+ for i in range(segments):
268
+ segment_grad = self.linear_gradient(
269
+ colors[i], colors[i + 1], steps_per_segment
270
+ )
271
+ gradient.extend(segment_grad)
272
+
273
+ return gradient
274
+ aliceblue = "#f0f8ff"
275
+ antiquewhite = "#faebd7"
276
+ aqua = "#00ffff"
277
+ aquamarine = "#7fffd4"
278
+ azure = "#f0ffff"
279
+ beige = "#f5f5dc"
280
+ bisque = "#ffe4c4"
281
+ black = "#000000"
282
+ blanchedalmond = "#ffebcd"
283
+ blue = "#0000ff"
284
+ blueviolet = "#8a2be2"
285
+ brown = "#a52a2a"
286
+ burlywood = "#deb887"
287
+ cadetblue = "#5f9ea0"
288
+ chartreuse = "#7fff00"
289
+ chocolate = "#d2691e"
290
+ coral = "#ff7f50"
291
+ cornflowerblue = "#6495ed"
292
+ cornsilk = "#fff8dc"
293
+ crimson = "#dc143c"
294
+ cyan = "#00ffff"
295
+ darkblue = "#00008b"
296
+ darkcyan = "#008b8b"
297
+ darkgoldenrod = "#b8860b"
298
+ darkgray = "#a9a9a9"
299
+ darkgrey = "#a9a9a9"
300
+ darkgreen = "#006400"
301
+ darkkhaki = "#bdb76b"
302
+ darkmagenta = "#8b008b"
303
+ darkolivegreen = "#556b2f"
304
+ darkorange = "#ff8c00"
305
+ darkorchid = "#9932cc"
306
+ darkred = "#8b0000"
307
+ darksalmon = "#e9967a"
308
+ darkseagreen = "#8fbc8f"
309
+ darkslateblue = "#483d8b"
310
+ darkslategray = "#2f4f4f"
311
+ darkslategrey = "#2f4f4f"
312
+ darkturquoise = "#00ced1"
313
+ darkviolet = "#9400d3"
314
+ deeppink = "#ff1493"
315
+ deepskyblue = "#00bfff"
316
+ dimgray = "#696969"
317
+ dimgrey = "#696969"
318
+ dodgerblue = "#1e90ff"
319
+ firebrick = "#b22222"
320
+ floralwhite = "#fffaf0"
321
+ forestgreen = "#228b22"
322
+ fuchsia = "#ff00ff"
323
+ gainsboro = "#dcdcdc"
324
+ ghostwhite = "#f8f8ff"
325
+ gold = "#ffd700"
326
+ goldenrod = "#daa520"
327
+ gray = "#808080"
328
+ grey = "#808080"
329
+ green = "#008000"
330
+ greenyellow = "#adff2f"
331
+ honeydew = "#f0fff0"
332
+ hotpink = "#ff69b4"
333
+ indianred = "#cd5c5c"
334
+ indigo = "#4b0082"
335
+ ivory = "#fffff0"
336
+ khaki = "#f0e68c"
337
+ lavender = "#e6e6fa"
338
+ lavenderblush = "#fff0f5"
339
+ lawngreen = "#7cfc00"
340
+ lemonchiffon = "#fffacd"
341
+ lightblue = "#add8e6"
342
+ lightcoral = "#f08080"
343
+ lightcyan = "#e0ffff"
344
+ lightgoldenrodyellow = "#fafad2"
345
+ lightgray = "#d3d3d3"
346
+ lightgrey = "#d3d3d3"
347
+ lightgreen = "#90ee90"
348
+ lightpink = "#ffb6c1"
349
+ lightsalmon = "#ffa07a"
350
+ lightseagreen = "#20b2aa"
351
+ lightskyblue = "#87cefa"
352
+ lightslategray = "#778899"
353
+ lightslategrey = "#778899"
354
+ lightsteelblue = "#b0c4de"
355
+ lightyellow = "#ffffe0"
356
+ lime = "#00ff00"
357
+ limegreen = "#32cd32"
358
+ linen = "#faf0e6"
359
+ magenta = "#ff00ff"
360
+ maroon = "#800000"
361
+ mediumaquamarine = "#66cdaa"
362
+ mediumblue = "#0000cd"
363
+ mediumorchid = "#ba55d3"
364
+ mediumpurple = "#9370db"
365
+ mediumseagreen = "#3cb371"
366
+ mediumslateblue = "#7b68ee"
367
+ mediumspringgreen = "#00fa9a"
368
+ mediumturquoise = "#48d1cc"
369
+ mediumvioletred = "#c71585"
370
+ midnightblue = "#191970"
371
+ mintcream = "#f5fffa"
372
+ mistyrose = "#ffe4e1"
373
+ moccasin = "#ffe4b5"
374
+ navajowhite = "#ffdead"
375
+ navy = "#000080"
376
+ oldlace = "#fdf5e6"
377
+ olive = "#808000"
378
+ olivedrab = "#6b8e23"
379
+ orange = "#ffa500"
380
+ orangered = "#ff4500"
381
+ orchid = "#da70d6"
382
+ palegoldenrod = "#eee8aa"
383
+ palegreen = "#98fb98"
384
+ paleturquoise = "#afeeee"
385
+ palevioletred = "#db7093"
386
+ papayawhip = "#ffefd5"
387
+ peachpuff = "#ffdab9"
388
+ peru = "#cd853f"
389
+ pink = "#ffc0cb"
390
+ plum = "#dda0dd"
391
+ powderblue = "#b0e0e6"
392
+ purple = "#800080"
393
+ red = "#ff0000"
394
+ rosybrown = "#bc8f8f"
395
+ royalblue = "#4169e1"
396
+ saddlebrown = "#8b4513"
397
+ salmon = "#fa8072"
398
+ sandybrown = "#f4a460"
399
+ seagreen = "#2e8b57"
400
+ seashell = "#fff5ee"
401
+ sienna = "#a0522d"
402
+ silver = "#c0c0c0"
403
+ skyblue = "#87ceeb"
404
+ slateblue = "#6a5acd"
405
+ slategray = "#708090"
406
+ slategrey = "#708090"
407
+ snow = "#fffafa"
408
+ springgreen = "#00ff7f"
409
+ steelblue = "#4682b4"
410
+ tan = "#d2b48c"
411
+ teal = "#008080"
412
+ thistle = "#d8bfd8"
413
+ tomato = "#ff6347"
414
+ turquoise = "#40e0d0"
415
+ violet = "#ee82ee"
416
+ wheat = "#f5deb3"
417
+ white = "#ffffff"
418
+ whitesmoke = "#f5f5f5"
419
+ yellow = "#ffff00"
420
+ yellowgreen = "#9acd32"