style.go

  1package ansi
  2
  3import (
  4	"image/color"
  5	"strconv"
  6	"strings"
  7)
  8
  9// ResetStyle is a SGR (Select Graphic Rendition) style sequence that resets
 10// all attributes.
 11// See: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters
 12const ResetStyle = "\x1b[m"
 13
 14// Attr is a SGR (Select Graphic Rendition) style attribute.
 15type Attr = int
 16
 17// Style represents an ANSI SGR (Select Graphic Rendition) style.
 18type Style []string
 19
 20// NewStyle returns a new style with the given attributes.
 21func NewStyle(attrs ...Attr) Style {
 22	if len(attrs) == 0 {
 23		return Style{}
 24	}
 25	s := make(Style, 0, len(attrs))
 26	for _, a := range attrs {
 27		attr, ok := attrStrings[a]
 28		if ok {
 29			s = append(s, attr)
 30		} else {
 31			if a < 0 {
 32				a = 0
 33			}
 34			s = append(s, strconv.Itoa(a))
 35		}
 36	}
 37	return s
 38}
 39
 40// String returns the ANSI SGR (Select Graphic Rendition) style sequence for
 41// the given style.
 42func (s Style) String() string {
 43	if len(s) == 0 {
 44		return ResetStyle
 45	}
 46	return "\x1b[" + strings.Join(s, ";") + "m"
 47}
 48
 49// Styled returns a styled string with the given style applied.
 50func (s Style) Styled(str string) string {
 51	if len(s) == 0 {
 52		return str
 53	}
 54	return s.String() + str + ResetStyle
 55}
 56
 57// Reset appends the reset style attribute to the style.
 58func (s Style) Reset() Style {
 59	return append(s, resetAttr)
 60}
 61
 62// Bold appends the bold style attribute to the style.
 63func (s Style) Bold() Style {
 64	return append(s, boldAttr)
 65}
 66
 67// Faint appends the faint style attribute to the style.
 68func (s Style) Faint() Style {
 69	return append(s, faintAttr)
 70}
 71
 72// Italic appends the italic style attribute to the style.
 73func (s Style) Italic() Style {
 74	return append(s, italicAttr)
 75}
 76
 77// Underline appends the underline style attribute to the style.
 78func (s Style) Underline() Style {
 79	return append(s, underlineAttr)
 80}
 81
 82// UnderlineStyle appends the underline style attribute to the style.
 83func (s Style) UnderlineStyle(u UnderlineStyle) Style {
 84	switch u {
 85	case NoUnderlineStyle:
 86		return s.NoUnderline()
 87	case SingleUnderlineStyle:
 88		return s.Underline()
 89	case DoubleUnderlineStyle:
 90		return append(s, doubleUnderlineStyle)
 91	case CurlyUnderlineStyle:
 92		return append(s, curlyUnderlineStyle)
 93	case DottedUnderlineStyle:
 94		return append(s, dottedUnderlineStyle)
 95	case DashedUnderlineStyle:
 96		return append(s, dashedUnderlineStyle)
 97	}
 98	return s
 99}
100
101// DoubleUnderline appends the double underline style attribute to the style.
102// This is a convenience method for UnderlineStyle(DoubleUnderlineStyle).
103func (s Style) DoubleUnderline() Style {
104	return s.UnderlineStyle(DoubleUnderlineStyle)
105}
106
107// CurlyUnderline appends the curly underline style attribute to the style.
108// This is a convenience method for UnderlineStyle(CurlyUnderlineStyle).
109func (s Style) CurlyUnderline() Style {
110	return s.UnderlineStyle(CurlyUnderlineStyle)
111}
112
113// DottedUnderline appends the dotted underline style attribute to the style.
114// This is a convenience method for UnderlineStyle(DottedUnderlineStyle).
115func (s Style) DottedUnderline() Style {
116	return s.UnderlineStyle(DottedUnderlineStyle)
117}
118
119// DashedUnderline appends the dashed underline style attribute to the style.
120// This is a convenience method for UnderlineStyle(DashedUnderlineStyle).
121func (s Style) DashedUnderline() Style {
122	return s.UnderlineStyle(DashedUnderlineStyle)
123}
124
125// SlowBlink appends the slow blink style attribute to the style.
126func (s Style) SlowBlink() Style {
127	return append(s, slowBlinkAttr)
128}
129
130// RapidBlink appends the rapid blink style attribute to the style.
131func (s Style) RapidBlink() Style {
132	return append(s, rapidBlinkAttr)
133}
134
135// Reverse appends the reverse style attribute to the style.
136func (s Style) Reverse() Style {
137	return append(s, reverseAttr)
138}
139
140// Conceal appends the conceal style attribute to the style.
141func (s Style) Conceal() Style {
142	return append(s, concealAttr)
143}
144
145// Strikethrough appends the strikethrough style attribute to the style.
146func (s Style) Strikethrough() Style {
147	return append(s, strikethroughAttr)
148}
149
150// NormalIntensity appends the normal intensity style attribute to the style.
151func (s Style) NormalIntensity() Style {
152	return append(s, normalIntensityAttr)
153}
154
155// NoItalic appends the no italic style attribute to the style.
156func (s Style) NoItalic() Style {
157	return append(s, noItalicAttr)
158}
159
160// NoUnderline appends the no underline style attribute to the style.
161func (s Style) NoUnderline() Style {
162	return append(s, noUnderlineAttr)
163}
164
165// NoBlink appends the no blink style attribute to the style.
166func (s Style) NoBlink() Style {
167	return append(s, noBlinkAttr)
168}
169
170// NoReverse appends the no reverse style attribute to the style.
171func (s Style) NoReverse() Style {
172	return append(s, noReverseAttr)
173}
174
175// NoConceal appends the no conceal style attribute to the style.
176func (s Style) NoConceal() Style {
177	return append(s, noConcealAttr)
178}
179
180// NoStrikethrough appends the no strikethrough style attribute to the style.
181func (s Style) NoStrikethrough() Style {
182	return append(s, noStrikethroughAttr)
183}
184
185// DefaultForegroundColor appends the default foreground color style attribute to the style.
186func (s Style) DefaultForegroundColor() Style {
187	return append(s, defaultForegroundColorAttr)
188}
189
190// DefaultBackgroundColor appends the default background color style attribute to the style.
191func (s Style) DefaultBackgroundColor() Style {
192	return append(s, defaultBackgroundColorAttr)
193}
194
195// DefaultUnderlineColor appends the default underline color style attribute to the style.
196func (s Style) DefaultUnderlineColor() Style {
197	return append(s, defaultUnderlineColorAttr)
198}
199
200// ForegroundColor appends the foreground color style attribute to the style.
201func (s Style) ForegroundColor(c Color) Style {
202	return append(s, foregroundColorString(c))
203}
204
205// BackgroundColor appends the background color style attribute to the style.
206func (s Style) BackgroundColor(c Color) Style {
207	return append(s, backgroundColorString(c))
208}
209
210// UnderlineColor appends the underline color style attribute to the style.
211func (s Style) UnderlineColor(c Color) Style {
212	return append(s, underlineColorString(c))
213}
214
215// UnderlineStyle represents an ANSI SGR (Select Graphic Rendition) underline
216// style.
217type UnderlineStyle = byte
218
219const (
220	doubleUnderlineStyle = "4:2"
221	curlyUnderlineStyle  = "4:3"
222	dottedUnderlineStyle = "4:4"
223	dashedUnderlineStyle = "4:5"
224)
225
226const (
227	// NoUnderlineStyle is the default underline style.
228	NoUnderlineStyle UnderlineStyle = iota
229	// SingleUnderlineStyle is a single underline style.
230	SingleUnderlineStyle
231	// DoubleUnderlineStyle is a double underline style.
232	DoubleUnderlineStyle
233	// CurlyUnderlineStyle is a curly underline style.
234	CurlyUnderlineStyle
235	// DottedUnderlineStyle is a dotted underline style.
236	DottedUnderlineStyle
237	// DashedUnderlineStyle is a dashed underline style.
238	DashedUnderlineStyle
239)
240
241// SGR (Select Graphic Rendition) style attributes.
242// See: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters
243const (
244	ResetAttr                        Attr = 0
245	BoldAttr                         Attr = 1
246	FaintAttr                        Attr = 2
247	ItalicAttr                       Attr = 3
248	UnderlineAttr                    Attr = 4
249	SlowBlinkAttr                    Attr = 5
250	RapidBlinkAttr                   Attr = 6
251	ReverseAttr                      Attr = 7
252	ConcealAttr                      Attr = 8
253	StrikethroughAttr                Attr = 9
254	NormalIntensityAttr              Attr = 22
255	NoItalicAttr                     Attr = 23
256	NoUnderlineAttr                  Attr = 24
257	NoBlinkAttr                      Attr = 25
258	NoReverseAttr                    Attr = 27
259	NoConcealAttr                    Attr = 28
260	NoStrikethroughAttr              Attr = 29
261	BlackForegroundColorAttr         Attr = 30
262	RedForegroundColorAttr           Attr = 31
263	GreenForegroundColorAttr         Attr = 32
264	YellowForegroundColorAttr        Attr = 33
265	BlueForegroundColorAttr          Attr = 34
266	MagentaForegroundColorAttr       Attr = 35
267	CyanForegroundColorAttr          Attr = 36
268	WhiteForegroundColorAttr         Attr = 37
269	ExtendedForegroundColorAttr      Attr = 38
270	DefaultForegroundColorAttr       Attr = 39
271	BlackBackgroundColorAttr         Attr = 40
272	RedBackgroundColorAttr           Attr = 41
273	GreenBackgroundColorAttr         Attr = 42
274	YellowBackgroundColorAttr        Attr = 43
275	BlueBackgroundColorAttr          Attr = 44
276	MagentaBackgroundColorAttr       Attr = 45
277	CyanBackgroundColorAttr          Attr = 46
278	WhiteBackgroundColorAttr         Attr = 47
279	ExtendedBackgroundColorAttr      Attr = 48
280	DefaultBackgroundColorAttr       Attr = 49
281	ExtendedUnderlineColorAttr       Attr = 58
282	DefaultUnderlineColorAttr        Attr = 59
283	BrightBlackForegroundColorAttr   Attr = 90
284	BrightRedForegroundColorAttr     Attr = 91
285	BrightGreenForegroundColorAttr   Attr = 92
286	BrightYellowForegroundColorAttr  Attr = 93
287	BrightBlueForegroundColorAttr    Attr = 94
288	BrightMagentaForegroundColorAttr Attr = 95
289	BrightCyanForegroundColorAttr    Attr = 96
290	BrightWhiteForegroundColorAttr   Attr = 97
291	BrightBlackBackgroundColorAttr   Attr = 100
292	BrightRedBackgroundColorAttr     Attr = 101
293	BrightGreenBackgroundColorAttr   Attr = 102
294	BrightYellowBackgroundColorAttr  Attr = 103
295	BrightBlueBackgroundColorAttr    Attr = 104
296	BrightMagentaBackgroundColorAttr Attr = 105
297	BrightCyanBackgroundColorAttr    Attr = 106
298	BrightWhiteBackgroundColorAttr   Attr = 107
299
300	RGBColorIntroducerAttr      Attr = 2
301	ExtendedColorIntroducerAttr Attr = 5
302)
303
304const (
305	resetAttr                        = "0"
306	boldAttr                         = "1"
307	faintAttr                        = "2"
308	italicAttr                       = "3"
309	underlineAttr                    = "4"
310	slowBlinkAttr                    = "5"
311	rapidBlinkAttr                   = "6"
312	reverseAttr                      = "7"
313	concealAttr                      = "8"
314	strikethroughAttr                = "9"
315	normalIntensityAttr              = "22"
316	noItalicAttr                     = "23"
317	noUnderlineAttr                  = "24"
318	noBlinkAttr                      = "25"
319	noReverseAttr                    = "27"
320	noConcealAttr                    = "28"
321	noStrikethroughAttr              = "29"
322	blackForegroundColorAttr         = "30"
323	redForegroundColorAttr           = "31"
324	greenForegroundColorAttr         = "32"
325	yellowForegroundColorAttr        = "33"
326	blueForegroundColorAttr          = "34"
327	magentaForegroundColorAttr       = "35"
328	cyanForegroundColorAttr          = "36"
329	whiteForegroundColorAttr         = "37"
330	extendedForegroundColorAttr      = "38"
331	defaultForegroundColorAttr       = "39"
332	blackBackgroundColorAttr         = "40"
333	redBackgroundColorAttr           = "41"
334	greenBackgroundColorAttr         = "42"
335	yellowBackgroundColorAttr        = "43"
336	blueBackgroundColorAttr          = "44"
337	magentaBackgroundColorAttr       = "45"
338	cyanBackgroundColorAttr          = "46"
339	whiteBackgroundColorAttr         = "47"
340	extendedBackgroundColorAttr      = "48"
341	defaultBackgroundColorAttr       = "49"
342	extendedUnderlineColorAttr       = "58"
343	defaultUnderlineColorAttr        = "59"
344	brightBlackForegroundColorAttr   = "90"
345	brightRedForegroundColorAttr     = "91"
346	brightGreenForegroundColorAttr   = "92"
347	brightYellowForegroundColorAttr  = "93"
348	brightBlueForegroundColorAttr    = "94"
349	brightMagentaForegroundColorAttr = "95"
350	brightCyanForegroundColorAttr    = "96"
351	brightWhiteForegroundColorAttr   = "97"
352	brightBlackBackgroundColorAttr   = "100"
353	brightRedBackgroundColorAttr     = "101"
354	brightGreenBackgroundColorAttr   = "102"
355	brightYellowBackgroundColorAttr  = "103"
356	brightBlueBackgroundColorAttr    = "104"
357	brightMagentaBackgroundColorAttr = "105"
358	brightCyanBackgroundColorAttr    = "106"
359	brightWhiteBackgroundColorAttr   = "107"
360)
361
362// foregroundColorString returns the style SGR attribute for the given
363// foreground color.
364// See: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters
365func foregroundColorString(c Color) string {
366	switch c := c.(type) {
367	case BasicColor:
368		// 3-bit or 4-bit ANSI foreground
369		// "3<n>" or "9<n>" where n is the color number from 0 to 7
370		switch c {
371		case Black:
372			return blackForegroundColorAttr
373		case Red:
374			return redForegroundColorAttr
375		case Green:
376			return greenForegroundColorAttr
377		case Yellow:
378			return yellowForegroundColorAttr
379		case Blue:
380			return blueForegroundColorAttr
381		case Magenta:
382			return magentaForegroundColorAttr
383		case Cyan:
384			return cyanForegroundColorAttr
385		case White:
386			return whiteForegroundColorAttr
387		case BrightBlack:
388			return brightBlackForegroundColorAttr
389		case BrightRed:
390			return brightRedForegroundColorAttr
391		case BrightGreen:
392			return brightGreenForegroundColorAttr
393		case BrightYellow:
394			return brightYellowForegroundColorAttr
395		case BrightBlue:
396			return brightBlueForegroundColorAttr
397		case BrightMagenta:
398			return brightMagentaForegroundColorAttr
399		case BrightCyan:
400			return brightCyanForegroundColorAttr
401		case BrightWhite:
402			return brightWhiteForegroundColorAttr
403		}
404	case ExtendedColor:
405		// 256-color ANSI foreground
406		// "38;5;<n>"
407		return "38;5;" + strconv.FormatUint(uint64(c), 10)
408	case TrueColor, color.Color:
409		// 24-bit "true color" foreground
410		// "38;2;<r>;<g>;<b>"
411		r, g, b, _ := c.RGBA()
412		return "38;2;" +
413			strconv.FormatUint(uint64(shift(r)), 10) + ";" +
414			strconv.FormatUint(uint64(shift(g)), 10) + ";" +
415			strconv.FormatUint(uint64(shift(b)), 10)
416	}
417	return defaultForegroundColorAttr
418}
419
420// backgroundColorString returns the style SGR attribute for the given
421// background color.
422// See: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters
423func backgroundColorString(c Color) string {
424	switch c := c.(type) {
425	case BasicColor:
426		// 3-bit or 4-bit ANSI foreground
427		// "4<n>" or "10<n>" where n is the color number from 0 to 7
428		switch c {
429		case Black:
430			return blackBackgroundColorAttr
431		case Red:
432			return redBackgroundColorAttr
433		case Green:
434			return greenBackgroundColorAttr
435		case Yellow:
436			return yellowBackgroundColorAttr
437		case Blue:
438			return blueBackgroundColorAttr
439		case Magenta:
440			return magentaBackgroundColorAttr
441		case Cyan:
442			return cyanBackgroundColorAttr
443		case White:
444			return whiteBackgroundColorAttr
445		case BrightBlack:
446			return brightBlackBackgroundColorAttr
447		case BrightRed:
448			return brightRedBackgroundColorAttr
449		case BrightGreen:
450			return brightGreenBackgroundColorAttr
451		case BrightYellow:
452			return brightYellowBackgroundColorAttr
453		case BrightBlue:
454			return brightBlueBackgroundColorAttr
455		case BrightMagenta:
456			return brightMagentaBackgroundColorAttr
457		case BrightCyan:
458			return brightCyanBackgroundColorAttr
459		case BrightWhite:
460			return brightWhiteBackgroundColorAttr
461		}
462	case ExtendedColor:
463		// 256-color ANSI foreground
464		// "48;5;<n>"
465		return "48;5;" + strconv.FormatUint(uint64(c), 10)
466	case TrueColor, color.Color:
467		// 24-bit "true color" foreground
468		// "38;2;<r>;<g>;<b>"
469		r, g, b, _ := c.RGBA()
470		return "48;2;" +
471			strconv.FormatUint(uint64(shift(r)), 10) + ";" +
472			strconv.FormatUint(uint64(shift(g)), 10) + ";" +
473			strconv.FormatUint(uint64(shift(b)), 10)
474	}
475	return defaultBackgroundColorAttr
476}
477
478// underlineColorString returns the style SGR attribute for the given underline
479// color.
480// See: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters
481func underlineColorString(c Color) string {
482	switch c := c.(type) {
483	// NOTE: we can't use 3-bit and 4-bit ANSI color codes with underline
484	// color, use 256-color instead.
485	//
486	// 256-color ANSI underline color
487	// "58;5;<n>"
488	case BasicColor:
489		return "58;5;" + strconv.FormatUint(uint64(c), 10)
490	case ExtendedColor:
491		return "58;5;" + strconv.FormatUint(uint64(c), 10)
492	case TrueColor, color.Color:
493		// 24-bit "true color" foreground
494		// "38;2;<r>;<g>;<b>"
495		r, g, b, _ := c.RGBA()
496		return "58;2;" +
497			strconv.FormatUint(uint64(shift(r)), 10) + ";" +
498			strconv.FormatUint(uint64(shift(g)), 10) + ";" +
499			strconv.FormatUint(uint64(shift(b)), 10)
500	}
501	return defaultUnderlineColorAttr
502}
503
504// ReadStyleColor decodes a color from a slice of parameters. It returns the
505// number of parameters read and the color. This function is used to read SGR
506// color parameters following the ITU T.416 standard.
507//
508// It supports reading the following color types:
509//   - 0: implementation defined
510//   - 1: transparent
511//   - 2: RGB direct color
512//   - 3: CMY direct color
513//   - 4: CMYK direct color
514//   - 5: indexed color
515//   - 6: RGBA direct color (WezTerm extension)
516//
517// The parameters can be separated by semicolons (;) or colons (:). Mixing
518// separators is not allowed.
519//
520// The specs supports defining a color space id, a color tolerance value, and a
521// tolerance color space id. However, these values have no effect on the
522// returned color and will be ignored.
523//
524// This implementation includes a few modifications to the specs:
525//  1. Support for legacy color values separated by semicolons (;) with respect to RGB, and indexed colors
526//  2. Support ignoring and omitting the color space id (second parameter) with respect to RGB colors
527//  3. Support ignoring and omitting the 6th parameter with respect to RGB and CMY colors
528//  4. Support reading RGBA colors
529func ReadStyleColor(params Params, co *color.Color) (n int) {
530	if len(params) < 2 { // Need at least SGR type and color type
531		return 0
532	}
533
534	// First parameter indicates one of 38, 48, or 58 (foreground, background, or underline)
535	s := params[0]
536	p := params[1]
537	colorType := p.Param(0)
538	n = 2
539
540	paramsfn := func() (p1, p2, p3, p4 int) {
541		// Where should we start reading the color?
542		switch {
543		case s.HasMore() && p.HasMore() && len(params) > 8 && params[2].HasMore() && params[3].HasMore() && params[4].HasMore() && params[5].HasMore() && params[6].HasMore() && params[7].HasMore():
544			// We have color space id, a 6th parameter, a tolerance value, and a tolerance color space
545			n += 7
546			return params[3].Param(0), params[4].Param(0), params[5].Param(0), params[6].Param(0)
547		case s.HasMore() && p.HasMore() && len(params) > 7 && params[2].HasMore() && params[3].HasMore() && params[4].HasMore() && params[5].HasMore() && params[6].HasMore():
548			// We have color space id, a 6th parameter, and a tolerance value
549			n += 6
550			return params[3].Param(0), params[4].Param(0), params[5].Param(0), params[6].Param(0)
551		case s.HasMore() && p.HasMore() && len(params) > 6 && params[2].HasMore() && params[3].HasMore() && params[4].HasMore() && params[5].HasMore():
552			// We have color space id and a 6th parameter
553			// 48 : 4 : : 1 : 2 : 3 :4
554			n += 5
555			return params[3].Param(0), params[4].Param(0), params[5].Param(0), params[6].Param(0)
556		case s.HasMore() && p.HasMore() && len(params) > 5 && params[2].HasMore() && params[3].HasMore() && params[4].HasMore() && !params[5].HasMore():
557			// We have color space
558			// 48 : 3 : : 1 : 2 : 3
559			n += 4
560			return params[3].Param(0), params[4].Param(0), params[5].Param(0), -1
561		case s.HasMore() && p.HasMore() && p.Param(0) == 2 && params[2].HasMore() && params[3].HasMore() && !params[4].HasMore():
562			// We have color values separated by colons (:)
563			// 48 : 2 : 1 : 2 : 3
564			fallthrough
565		case !s.HasMore() && !p.HasMore() && p.Param(0) == 2 && !params[2].HasMore() && !params[3].HasMore() && !params[4].HasMore():
566			// Support legacy color values separated by semicolons (;)
567			// 48 ; 2 ; 1 ; 2 ; 3
568			n += 3
569			return params[2].Param(0), params[3].Param(0), params[4].Param(0), -1
570		}
571		// Ambiguous SGR color
572		return -1, -1, -1, -1
573	}
574
575	switch colorType {
576	case 0: // implementation defined
577		return 2
578	case 1: // transparent
579		*co = color.Transparent
580		return 2
581	case 2: // RGB direct color
582		if len(params) < 5 {
583			return 0
584		}
585
586		r, g, b, _ := paramsfn()
587		if r == -1 || g == -1 || b == -1 {
588			return 0
589		}
590
591		*co = color.RGBA{
592			R: uint8(r), //nolint:gosec
593			G: uint8(g), //nolint:gosec
594			B: uint8(b), //nolint:gosec
595			A: 0xff,
596		}
597		return
598
599	case 3: // CMY direct color
600		if len(params) < 5 {
601			return 0
602		}
603
604		c, m, y, _ := paramsfn()
605		if c == -1 || m == -1 || y == -1 {
606			return 0
607		}
608
609		*co = color.CMYK{
610			C: uint8(c), //nolint:gosec
611			M: uint8(m), //nolint:gosec
612			Y: uint8(y), //nolint:gosec
613			K: 0,
614		}
615		return
616
617	case 4: // CMYK direct color
618		if len(params) < 6 {
619			return 0
620		}
621
622		c, m, y, k := paramsfn()
623		if c == -1 || m == -1 || y == -1 || k == -1 {
624			return 0
625		}
626
627		*co = color.CMYK{
628			C: uint8(c), //nolint:gosec
629			M: uint8(m), //nolint:gosec
630			Y: uint8(y), //nolint:gosec
631			K: uint8(k), //nolint:gosec
632		}
633		return
634
635	case 5: // indexed color
636		if len(params) < 3 {
637			return 0
638		}
639		switch {
640		case s.HasMore() && p.HasMore() && !params[2].HasMore():
641			// Colon separated indexed color
642			// 38 : 5 : 234
643		case !s.HasMore() && !p.HasMore() && !params[2].HasMore():
644			// Legacy semicolon indexed color
645			// 38 ; 5 ; 234
646		default:
647			return 0
648		}
649		*co = ExtendedColor(params[2].Param(0)) //nolint:gosec
650		return 3
651
652	case 6: // RGBA direct color
653		if len(params) < 6 {
654			return 0
655		}
656
657		r, g, b, a := paramsfn()
658		if r == -1 || g == -1 || b == -1 || a == -1 {
659			return 0
660		}
661
662		*co = color.RGBA{
663			R: uint8(r), //nolint:gosec
664			G: uint8(g), //nolint:gosec
665			B: uint8(b), //nolint:gosec
666			A: uint8(a), //nolint:gosec
667		}
668		return
669
670	default:
671		return 0
672	}
673}